From cec4acc1bc6ec094152934099a770ce798dff2bb Mon Sep 17 00:00:00 2001 From: apl Date: Mon, 26 Sep 2016 20:01:28 +0300 Subject: [PATCH] Implementation '22873: EDF 8651 GEOM: Annotate shapes into the OCC viewer' issue --- doc/salome/gui/GEOM/images/annotation.png | Bin 0 -> 14164 bytes .../gui/GEOM/images/annotation_preview.png | Bin 0 -> 9913 bytes doc/salome/gui/GEOM/input/annotation.doc | 57 + .../GEOM/input/using_measurement_tools.doc | 1 + resources/CMakeLists.txt | 1 + resources/SalomeApp.xml.in | 8 + resources/annotation.png | Bin 0 -> 355 bytes src/GEOMBase/GEOMBase_Helper.h | 5 +- src/GEOMGUI/CMakeLists.txt | 8 + src/GEOMGUI/GEOMGUI_AnnotationAttrs.cxx | 552 +++++++++ src/GEOMGUI/GEOMGUI_AnnotationAttrs.h | 220 ++++ src/GEOMGUI/GEOMGUI_AnnotationMgr.cxx | 899 +++++++++++++++ src/GEOMGUI/GEOMGUI_AnnotationMgr.h | 136 +++ src/GEOMGUI/GEOMGUI_DimensionProperty.h | 3 + src/GEOMGUI/GEOMGUI_OCCSelector.cxx | 11 +- src/GEOMGUI/GEOMGUI_Selection.cxx | 71 ++ src/GEOMGUI/GEOMGUI_Selection.h | 7 + src/GEOMGUI/GEOMGUI_TextTreeSelector.cxx | 168 +++ src/GEOMGUI/GEOMGUI_TextTreeSelector.h | 63 ++ src/GEOMGUI/GEOMGUI_TextTreeWdg.cxx | 702 ++++++++++-- src/GEOMGUI/GEOMGUI_TextTreeWdg.h | 104 +- src/GEOMGUI/GEOM_Displayer.cxx | 49 +- src/GEOMGUI/GEOM_Displayer.h | 2 + src/GEOMGUI/GEOM_images.ts | 4 + src/GEOMGUI/GEOM_msg_en.ts | 163 +++ src/GEOMGUI/GEOM_msg_fr.ts | 68 ++ src/GEOMGUI/GEOM_msg_ja.ts | 68 ++ src/GEOMGUI/GeometryGUI.cxx | 215 +++- src/GEOMGUI/GeometryGUI.h | 12 +- src/GEOMGUI/GeometryGUI_Operations.h | 5 + src/MeasureGUI/CMakeLists.txt | 6 + src/MeasureGUI/MeasureGUI.cxx | 176 ++- src/MeasureGUI/MeasureGUI.h | 15 + src/MeasureGUI/MeasureGUI_AnnotationDlg.cxx | 1008 +++++++++++++++++ src/MeasureGUI/MeasureGUI_AnnotationDlg.h | 129 +++ .../MeasureGUI_AnnotationInteractor.cxx | 333 ++++++ .../MeasureGUI_AnnotationInteractor.h | 122 ++ .../MeasureGUI_ManageDimensionsDlg.cxx | 10 +- src/OBJECT/CMakeLists.txt | 2 + src/OBJECT/GEOM_Annotation.cxx | 943 +++++++++++++++ src/OBJECT/GEOM_Annotation.hxx | 417 +++++++ src/OBJECT/GEOM_Constants.cxx | 4 +- src/OBJECT/GEOM_Constants.h | 3 +- 43 files changed, 6565 insertions(+), 205 deletions(-) create mode 100644 doc/salome/gui/GEOM/images/annotation.png create mode 100644 doc/salome/gui/GEOM/images/annotation_preview.png create mode 100644 doc/salome/gui/GEOM/input/annotation.doc mode change 100644 => 100755 resources/SalomeApp.xml.in create mode 100644 resources/annotation.png create mode 100755 src/GEOMGUI/GEOMGUI_AnnotationAttrs.cxx create mode 100755 src/GEOMGUI/GEOMGUI_AnnotationAttrs.h create mode 100755 src/GEOMGUI/GEOMGUI_AnnotationMgr.cxx create mode 100755 src/GEOMGUI/GEOMGUI_AnnotationMgr.h create mode 100644 src/GEOMGUI/GEOMGUI_TextTreeSelector.cxx create mode 100644 src/GEOMGUI/GEOMGUI_TextTreeSelector.h mode change 100644 => 100755 src/GEOMGUI/GEOMGUI_TextTreeWdg.cxx mode change 100644 => 100755 src/GEOMGUI/GEOM_Displayer.cxx mode change 100644 => 100755 src/GEOMGUI/GEOM_Displayer.h mode change 100644 => 100755 src/GEOMGUI/GEOM_msg_en.ts mode change 100644 => 100755 src/GEOMGUI/GEOM_msg_fr.ts mode change 100644 => 100755 src/GEOMGUI/GEOM_msg_ja.ts mode change 100644 => 100755 src/GEOMGUI/GeometryGUI.cxx mode change 100644 => 100755 src/GEOMGUI/GeometryGUI_Operations.h mode change 100644 => 100755 src/MeasureGUI/MeasureGUI.cxx mode change 100644 => 100755 src/MeasureGUI/MeasureGUI.h create mode 100755 src/MeasureGUI/MeasureGUI_AnnotationDlg.cxx create mode 100755 src/MeasureGUI/MeasureGUI_AnnotationDlg.h create mode 100755 src/MeasureGUI/MeasureGUI_AnnotationInteractor.cxx create mode 100755 src/MeasureGUI/MeasureGUI_AnnotationInteractor.h create mode 100755 src/OBJECT/GEOM_Annotation.cxx create mode 100755 src/OBJECT/GEOM_Annotation.hxx diff --git a/doc/salome/gui/GEOM/images/annotation.png b/doc/salome/gui/GEOM/images/annotation.png new file mode 100644 index 0000000000000000000000000000000000000000..584104fc36dfbe72197df9f215d5818833390142 GIT binary patch literal 14164 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 literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GEOM/images/annotation_preview.png b/doc/salome/gui/GEOM/images/annotation_preview.png new file mode 100644 index 0000000000000000000000000000000000000000..0cb50206deaf049f8d347f53143f36b1d0e77223 GIT binary patch literal 9913 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 X% Annotation functionality allows showing in the viewer special user-defined text label connected to corresponding part of a CAD model with a line. +Annotation text is always parallel to the screen and horizontal. It is is not zoomed or rotated when a 3D scene is zoomed or rotated by the user. +The annotation text is defined using UTF-8 encoding and thus support any Unicode characters. + +There are several algorithms for the annotation position calculation during the scene manipulations (panning, zooming, rotation): +

    +
  • Algorithm 1: an annotation has fixed position in 2D screen coordinates (fixed screen position mode). In this mode, the annotations are always visible (appear as topmost objects), never hidden by the (annotated) geometry.
  • +
  • Algorithm 2: an annotation has fixed position in 3D model space, this position is projected onto the screen just as normal point coordinates. In this mode, some annotations may be invisible depending on the camera (position, orientation, zoom).
  • +
+ +\image html annotation_preview.png + +It can be accessed from the main menu via Inspection -> Annotation + +\image html annotation.png "Create Annotation dialog" + +In this dialog you can: +
    +
  • Set Text text shown in View 3d and a name of annotation presented in the Text Browser.
  • +
  • Select a \b Shape to which the annotation will be assigned.
  • +
  • Set Fixed screen position to select alogithm for the annotation position caldulation.
  • +
  • Select a Shape Type to which the annotation will be assigned on the shape. + It contains "Whole shape", "Vertex", "Edge", "Face" and "Solid" choices.
  • +
  • Select a sub shape to assign annotation to. Text control contains information about local selection in the viewer.
  • +
  • Move annotation dragging it in 3D view to select an appropriate position.
  • +
  • Push \b Apply or Apply and Close button to commit creation of the field.
  • +
+ +Annotations appear in an Annotations sub-tree in Text Browser. +The foolowing context menu commands are provided for annotation object in Text Browser: +
    +
  • Edit allows modifying the annotation text, the positioning algorithm and the annotation position.
  • +
  • Delete deletes selected annotation.
  • +
  • Show/Hide change visibility of annotation in the active view.
  • +
+Edit and Delete actions are also available in View 3d for selected annotation object/s. + +All annotations may be shown/hidden in a 3D view. The corresponded popup menu is available in Text Browser. + +All annotations of a shape may be shown/hidden in a 3D view using corresponded popup menu on the shape item in Object Browser. + +Synchronization of selection between 3D view and Text browser is available. It means that selection of annotation in 3D view will select this annotation in Text browser and vice versa. + +Annotation is logically connected to the shape: +
    +
  • Selection of an annotation will highlight corresponding shape/subshape in 3D view.
  • +
  • When the shape is deleted, the annotation will be also deleted.
  • +
+ +The user is able to modify the font, the style, the color and the size of the annotation text and the color, the width and the style of the connection line applied to all annotations. +It can be accessed from the main menu via File -> Preferences. The Shape annotations group on Geometry Settings pane contains controls for it. + +*/ diff --git a/doc/salome/gui/GEOM/input/using_measurement_tools.doc b/doc/salome/gui/GEOM/input/using_measurement_tools.doc index 515a94ce4..feca9e24f 100644 --- a/doc/salome/gui/GEOM/input/using_measurement_tools.doc +++ b/doc/salome/gui/GEOM/input/using_measurement_tools.doc @@ -17,6 +17,7 @@
  • \subpage angle_page "Angle"
  • \subpage tolerance_page "Tolerance"
  • \subpage managing_dimensions_page "Dimensions"
  • +
  • \subpage annotation_page "Annotations"
  • \subpage whatis_page "WhatIs"
  • \subpage inspect_object_operation_page "Inspect Object"
  • \subpage shape_statistics_operation_page "Shape Statistics"
  • diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt index dc98cbf97..74be117a6 100755 --- a/resources/CMakeLists.txt +++ b/resources/CMakeLists.txt @@ -39,6 +39,7 @@ SET( _res_files isoline.png isoline_v.png angle.png + annotation.png arc.png arccenter.png arcofellipse.png diff --git a/resources/SalomeApp.xml.in b/resources/SalomeApp.xml.in old mode 100644 new mode 100755 index 45e41fc70..72d1c700f --- a/resources/SalomeApp.xml.in +++ b/resources/SalomeApp.xml.in @@ -100,6 +100,14 @@ + + + + + + + + diff --git a/resources/annotation.png b/resources/annotation.png new file mode 100644 index 0000000000000000000000000000000000000000..a02ff683c1cda378f102fa409f829b21e25f5032 GIT binary patch literal 355 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VOR^eP*AeOHKHUqKdq!Zu_%?Hyu4g5GcUV1Ik6yBFTW^#_B$IXprQw!E{-7< zy>BlWdOHP5w11o*bx*ZvPIi`FM#nTZ&gYACIatEG+x9uG>+7qXxX-!Ona@w~D*Fc2 z?7;TwrQIh?KXLHdU4Cf0=l|z9#c|Wlcq=C7^P5ij*pVDk&|!A&;!(+Y$9#YG91ybG z*cbX{Q7hlKi|)eZFPBY~G_UZ_@iXwriq}}wZd$WkdK1s@8wVYQesyWfJe0e=!>zRK zioLS=(y~rn`}}D~-Ln2R+&<~wdEvn3ijca)>}-!ZXJlQUZSnKGOT}T|4uc&6ucte; th<;RB5PO&Djg;b{2O$o-4QDTGa+98};jDPZ>=)3l44$rjF6*2UngBmqii-dM literal 0 HcmV?d00001 diff --git a/src/GEOMBase/GEOMBase_Helper.h b/src/GEOMBase/GEOMBase_Helper.h index 64d46f202..a62b2f129 100755 --- a/src/GEOMBase/GEOMBase_Helper.h +++ b/src/GEOMBase/GEOMBase_Helper.h @@ -65,6 +65,8 @@ public: static SUIT_ViewWindow* getActiveView(); protected: + typedef std::list PrsList; + static GEOM::GEOM_Gen_ptr getGeomEngine(); void display ( const ObjectList&, const bool = true ); @@ -97,6 +99,8 @@ protected: const bool = true ); void erasePreview ( const bool = true ); + const PrsList& getPreview() const { return myPreview; } + void localSelection( const ObjectList&, const std::list ); void localSelection( const ObjectList&, const int ); void localSelection( GEOM::GEOM_Object_ptr, const std::list ); @@ -210,7 +214,6 @@ private: void clearShapeBuffer( GEOM::GEOM_Object_ptr ); private: - typedef std::list PrsList; PrsList myPreview; GEOM_Displayer* myDisplayer; diff --git a/src/GEOMGUI/CMakeLists.txt b/src/GEOMGUI/CMakeLists.txt index dba48f806..9dd7a50d8 100755 --- a/src/GEOMGUI/CMakeLists.txt +++ b/src/GEOMGUI/CMakeLists.txt @@ -66,6 +66,7 @@ SET(_link_LIBRARIES SET(GEOMGUI_HEADERS GeometryGUI.h + GEOMGUI_AnnotationMgr.h GeometryGUI_Operations.h GEOMGUI.h GEOMPluginGUI.h @@ -75,13 +76,17 @@ SET(GEOMGUI_HEADERS GEOM_GEOMGUI.hxx GEOMGUI_CreationInfoWdg.h GEOMGUI_TextTreeWdg.h + GEOMGUI_TextTreeSelector.h GEOMGUI_DimensionProperty.h + GEOMGUI_AnnotationAttrs.h ) # header files / to be processed by moc SET(_moc_HEADERS + GEOMGUI_AnnotationMgr.h GEOMGUI_CreationInfoWdg.h GEOMGUI_TextTreeWdg.h + GEOMGUI_TextTreeSelector.h GeometryGUI.h ) @@ -108,6 +113,7 @@ QT_ADD_RESOURCES(_rcc_SOURCES ${_rcc_RESOURCES}) SET(GEOMGUI_SOURCES GeometryGUI.cxx + GEOMGUI_AnnotationMgr.cxx GEOMGUI.cxx GEOMPluginGUI.cxx GEOM_Displayer.cxx @@ -115,7 +121,9 @@ SET(GEOMGUI_SOURCES GEOMGUI_Selection.cxx GEOMGUI_CreationInfoWdg.cxx GEOMGUI_TextTreeWdg.cxx + GEOMGUI_TextTreeSelector.cxx GEOMGUI_DimensionProperty.cxx + GEOMGUI_AnnotationAttrs.cxx ${_moc_SOURCES} ${_rcc_SOURCES} ) diff --git a/src/GEOMGUI/GEOMGUI_AnnotationAttrs.cxx b/src/GEOMGUI/GEOMGUI_AnnotationAttrs.cxx new file mode 100755 index 000000000..1a09b5024 --- /dev/null +++ b/src/GEOMGUI/GEOMGUI_AnnotationAttrs.cxx @@ -0,0 +1,552 @@ +// Copyright (C) 2007-2016 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, or (at your option) any later version. +// +// 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 +// + +// File : GEOMGUI_AnnotationAttr.cxx +// Author : Anton POLETAEV, Open CASCADE S.A.S. +// + +// SALOME includes +#include +#include +#include + +// STL includes +#include +#include +#include + +IMPLEMENT_STANDARD_RTTIEXT( GEOMGUI_AnnotationAttrs, Standard_Transient ) + +namespace +{ + static const std::string PARAMETER_COUNT = "GEOMGUI_AnnotationAttrs_Count"; + + std::string PARAMETER_I( const std::string& s, const int i ) { + std::stringstream ss; + ss << i; + return std::string( s ) + ss.str(); + } + std::string PARAMETER_IS_VISIBLE( const int i ) { + return PARAMETER_I( "GEOMGUI_AnnotationAttrs_IsVisible", i ); + } + std::string PARAMETER_IS_2D( const int i ) { + return PARAMETER_I( "GEOMGUI_AnnotationAttrs_Is2D", i ); + } + std::string PARAMETER_TEXT( const int i ) { + return PARAMETER_I( "GEOMGUI_AnnotationAttrs_Text", i ); + } + std::string PARAMETER_POSITION( const int i ) { + return PARAMETER_I( "GEOMGUI_AnnotationAttrs_Position", i ); + } + std::string PARAMETER_ATTACH( const int i ) { + return PARAMETER_I( "GEOMGUI_AnnotationAttrs_Attach", i ); + } + std::string PARAMETER_SHAPE( const int i ) { + return PARAMETER_I( "GEOMGUI_AnnotationAttrs_Shape", i ); + } + + // REGEXP pattern for converting array of entries into plain text string. + // The pattern has the following structure: + // ENTRY: { text[string] : visibility[bool] : screen fixed[bool] : position[xyz] : attach[xyz] } + static const QString PATTERN_ITEM_GROUP = "\\{ (Text=(?::{2,}|.)*:(?!:)Screen=.*:Position=\\{(.*):(.*):(.*)\\}:Attach=\\{(.*):(.*):(.*)\\}:ShapeIdx=.*:ShapeType=.*) \\}"; + static const QString PATTERN_ITEM = "Text=((?::{2,}|.)*):(?!:)Screen=(\\d{1}):Position=\\{(.*):(.*):(.*)\\}:Attach=\\{(.*):(.*):(.*)\\}:ShapeIdx=(\\-?\\d{1,}):ShapeType=(\\d{1})"; + static QString toPattern (const QString& theText, + const bool theIsFixed, + const gp_Pnt& thePosition, + const gp_Pnt& theAttach, + const int theShapeIndex, + const int theShapeType) + { + return QString( "{ Text=" ) + theText + + QString( ":" ) + QString( "Screen=" ) + QString::number( theIsFixed ? 1 : 0 ) + + QString( ":" ) + QString( "Position={" ) + + QString::number( thePosition.X() ) + QString( ":" ) + + QString::number( thePosition.Y() ) + QString( ":" ) + + QString::number( thePosition.Z() ) + QString( "}" ) + + QString( ":" ) + QString( "Attach={" ) + + QString::number( theAttach.X() ) + QString( ":" ) + + QString::number( theAttach.Y() ) + QString( ":" ) + + QString::number( theAttach.Z() ) + QString( "}" ) + + QString( ":" ) + QString( "ShapeIdx=" ) + QString::number( theShapeIndex ) + + QString( ":" ) + QString( "ShapeType=" ) + QString::number( theShapeType ) + + QString( " }" ); + } +}; + +//================================================================================= +// function : FindAttributes +// purpose : +//================================================================================= +Handle(GEOMGUI_AnnotationAttrs) GEOMGUI_AnnotationAttrs::FindAttributes( const _PTR(SObject)& theObject ) +{ + _PTR(GenericAttribute) aGenericAttr; + _PTR(AttributeParameter) aParameterMap; + + if ( !theObject || !theObject->FindAttribute( aGenericAttr, "AttributeParameter" ) ) + { + return Handle(GEOMGUI_AnnotationAttrs)(); + } + + aParameterMap = aGenericAttr; + + if ( !aParameterMap->IsSet( PARAMETER_COUNT, PT_INTEGER ) ) + { + return Handle(GEOMGUI_AnnotationAttrs)(); + } + + return new GEOMGUI_AnnotationAttrs( theObject, aParameterMap ); +} + +//================================================================================= +// function : FindOrCreateAttributes +// purpose : +//================================================================================= +Handle(GEOMGUI_AnnotationAttrs) GEOMGUI_AnnotationAttrs::FindOrCreateAttributes( + const _PTR(SObject)& theObject, SalomeApp_Study* theStudy ) +{ + _PTR(StudyBuilder) aBuilder = theStudy->studyDS()->NewBuilder(); + _PTR(AttributeParameter) aParameterMap = aBuilder->FindOrCreateAttribute( theObject, "AttributeParameter" ); + if ( !aParameterMap->IsSet( PARAMETER_COUNT, PT_INTEGER ) ) + { + aParameterMap->SetInt( PARAMETER_COUNT, 0 ); + } + + return new GEOMGUI_AnnotationAttrs( theObject, aParameterMap ); +} + +//================================================================================= +// function : Remove +// purpose : +//================================================================================= +void GEOMGUI_AnnotationAttrs::Remove( const _PTR(SObject)& theObject ) +{ + _PTR(GenericAttribute) aGenericAttr; + _PTR(AttributeParameter) aParameterMap; + + if ( !theObject->FindAttribute( aGenericAttr, "AttributeParameter" ) ) + { + return; + } + + aParameterMap = aGenericAttr; + + if ( !aParameterMap->IsSet( PARAMETER_COUNT, PT_INTEGER ) ) + { + return; + } + + const int aParamCount = aParameterMap->GetInt( PARAMETER_COUNT ); + + for ( int anI = 0; anI < aParamCount; ++anI ) + { + aParameterMap->RemoveID( PARAMETER_IS_VISIBLE( anI ), PT_BOOLEAN ); + aParameterMap->RemoveID( PARAMETER_IS_2D( anI ), PT_BOOLEAN ); + aParameterMap->RemoveID( PARAMETER_TEXT( anI ), PT_STRING ); + aParameterMap->RemoveID( PARAMETER_POSITION( anI ), PT_REALARRAY ); + aParameterMap->RemoveID( PARAMETER_ATTACH( anI ), PT_REALARRAY ); + aParameterMap->RemoveID( PARAMETER_SHAPE( anI ), PT_INTARRAY ); + } + + aParameterMap->RemoveID( PARAMETER_COUNT, PT_INTEGER ); +} + +//================================================================================= +// function : ExportAsPropertyString +// purpose : +//================================================================================= +QString GEOMGUI_AnnotationAttrs::ExportAsPropertyString() const +{ + QStringList anItems; + + for ( int anI = 0; anI < GetNbAnnotation(); ++anI ) + { + Properties aEntry; + + GetProperties( anI, aEntry ); + + anItems.append( toPattern( aEntry.Text, + aEntry.IsScreenFixed, + aEntry.Position, + aEntry.Attach, + aEntry.ShapeIndex, + aEntry.ShapeType ) ); + } + + return anItems.join( ":" ); +} + +//================================================================================= +// function : ImportFromPropertyString +// purpose : +//================================================================================= +void GEOMGUI_AnnotationAttrs::ImportFromPropertyString( const QString& theString ) +{ + SetNbAnnotation( 0 ); + + QRegExp aRegExpItemGroups( PATTERN_ITEM_GROUP ); + QRegExp aRegExpItem( "^" + PATTERN_ITEM + "$" ); + aRegExpItemGroups.setMinimal( true ); + aRegExpItem.setMinimal( true ); + + int aPos = 0; + while ( ( aPos = aRegExpItemGroups.indexIn( theString, aPos ) ) != -1 ) + { + aPos += aRegExpItemGroups.matchedLength(); + + QString aStrItem = aRegExpItemGroups.cap(1); + + if ( aRegExpItem.indexIn( aStrItem ) < 0 ) + { + continue; + } + + QString aStrText = aRegExpItem.cap( 1 ); + QString aStrFixed = aRegExpItem.cap( 2 ); + QString aStrPosX = aRegExpItem.cap( 3 ); + QString aStrPosY = aRegExpItem.cap( 4 ); + QString aStrPosZ = aRegExpItem.cap( 5 ); + QString aStrAttX = aRegExpItem.cap( 6 ); + QString aStrAttY = aRegExpItem.cap( 7 ); + QString aStrAttZ = aRegExpItem.cap( 8 ); + QString aStrShapeIdx = aRegExpItem.cap( 9 ); + QString aStrShapeType = aRegExpItem.cap( 10 ); + aStrText.replace( "::", ":" ); + + Properties aEntry; + aEntry.Text = aStrText; + aEntry.IsVisible = false; + aEntry.IsScreenFixed = aStrFixed.toInt() != 0; + aEntry.Position.SetX( aStrPosX.toDouble() ); + aEntry.Position.SetY( aStrPosY.toDouble() ); + aEntry.Position.SetZ( aStrPosZ.toDouble() ); + aEntry.Attach.SetX( aStrAttX.toDouble() ); + aEntry.Attach.SetY( aStrAttY.toDouble() ); + aEntry.Attach.SetZ( aStrAttZ.toDouble() ); + aEntry.ShapeIndex = aStrShapeIdx.toInt(); + aEntry.ShapeType = aStrShapeType.toInt(); + + Append( aEntry ); + } +} + +//================================================================================= +// function : SetNbAnnotation +// purpose : +//================================================================================= +void GEOMGUI_AnnotationAttrs::SetNbAnnotation( const int theCount ) const +{ + const int aCount = this->GetNbAnnotation(); + + if ( aCount < theCount ) + { + // set default values + for ( int anI = aCount; anI < theCount; ++anI ) + { + myParameterMap->SetBool( PARAMETER_IS_VISIBLE( anI ), true ); + myParameterMap->SetBool( PARAMETER_IS_2D( anI ), false ); + myParameterMap->SetString( PARAMETER_TEXT( anI ), std::string() ); + myParameterMap->SetRealArray( PARAMETER_POSITION( anI ), std::vector(3, 0.0) ); + myParameterMap->SetRealArray( PARAMETER_ATTACH( anI ), std::vector(3, 0.0) ); + myParameterMap->SetIntArray( PARAMETER_SHAPE( anI ), std::vector(2, 0) ); + } + } + else + { + // remove exceeding values + for ( int anI = theCount; anI < aCount; ++anI ) + { + myParameterMap->RemoveID( PARAMETER_IS_VISIBLE( anI ), PT_BOOLEAN ); + myParameterMap->RemoveID( PARAMETER_IS_2D( anI ), PT_BOOLEAN ); + myParameterMap->RemoveID( PARAMETER_TEXT( anI ), PT_STRING ); + myParameterMap->RemoveID( PARAMETER_POSITION( anI ), PT_REALARRAY ); + myParameterMap->RemoveID( PARAMETER_ATTACH( anI ), PT_REALARRAY ); + myParameterMap->RemoveID( PARAMETER_SHAPE( anI ), PT_INTARRAY ); + } + } + + myParameterMap->SetInt( PARAMETER_COUNT, theCount ); +} + +//================================================================================= +// function : GetNbAnnotation +// purpose : +//================================================================================= +int GEOMGUI_AnnotationAttrs::GetNbAnnotation() const +{ + return myParameterMap->GetInt( PARAMETER_COUNT ); +} + +//================================================================================= +// function : SetVisible +// purpose : +//================================================================================= +void GEOMGUI_AnnotationAttrs::SetIsVisible( const int theIndex, const bool theIsVisible ) +{ + myParameterMap->SetBool( PARAMETER_IS_VISIBLE( theIndex ), theIsVisible ); +} + +//================================================================================= +// function : GetIsVisible +// purpose : +//================================================================================= +bool GEOMGUI_AnnotationAttrs::GetIsVisible( const int theIndex ) const +{ + return myParameterMap->GetBool( PARAMETER_IS_VISIBLE( theIndex ) ); +} + +//================================================================================= +// function : SetText +// purpose : +//================================================================================= +void GEOMGUI_AnnotationAttrs::SetText( const int theIndex, const QString& theText ) +{ + myParameterMap->SetString( PARAMETER_TEXT( theIndex ), theText.toStdString() ); +} + +//================================================================================= +// function : GetText +// purpose : +//================================================================================= +QString GEOMGUI_AnnotationAttrs::GetText( const int theIndex ) const +{ + return QString::fromStdString( myParameterMap->GetString( PARAMETER_TEXT( theIndex ) ) ); +} + +//================================================================================= +// function : SetIsScreenFixed +// purpose : +//================================================================================= +void GEOMGUI_AnnotationAttrs::SetIsScreenFixed( const int theIndex, const bool theIsScreenFixed ) +{ + myParameterMap->SetBool( PARAMETER_IS_2D( theIndex ), theIsScreenFixed ); +} + +//================================================================================= +// function : GetIsScreenFixed +// purpose : +//================================================================================= +bool GEOMGUI_AnnotationAttrs::GetIsScreenFixed( const int theIndex ) const +{ + return myParameterMap->GetBool( PARAMETER_IS_2D( theIndex ) ); +} + +//================================================================================= +// function : SetPosition +// purpose : +//================================================================================= +void GEOMGUI_AnnotationAttrs::SetPosition( const int theIndex, const gp_Pnt& thePosition ) +{ + std::vector aCoords( 3 ); + + aCoords[0] = thePosition.X(); + aCoords[1] = thePosition.Y(); + aCoords[2] = thePosition.Z(); + + myParameterMap->SetRealArray( PARAMETER_POSITION( theIndex ), aCoords ); +} + +//================================================================================= +// function : GetPosition +// purpose : +//================================================================================= +gp_Pnt GEOMGUI_AnnotationAttrs::GetPosition( const int theIndex ) const +{ + std::vector aCoords = + myParameterMap->GetRealArray( PARAMETER_POSITION( theIndex ) ); + + return gp_Pnt( aCoords[0], aCoords[1], aCoords[2] ); +} + +//================================================================================= +// function : SetAttach +// purpose : +//================================================================================= +void GEOMGUI_AnnotationAttrs::SetAttach( const int theIndex, const gp_Pnt& theAttach ) +{ + std::vector aCoords( 3 ); + + aCoords[0] = theAttach.X(); + aCoords[1] = theAttach.Y(); + aCoords[2] = theAttach.Z(); + + myParameterMap->SetRealArray( PARAMETER_ATTACH( theIndex ), aCoords ); +} + +//================================================================================= +// function : GetAttach +// purpose : +//================================================================================= +gp_Pnt GEOMGUI_AnnotationAttrs::GetAttach( const int theIndex ) const +{ + std::vector aCoords = + myParameterMap->GetRealArray( PARAMETER_ATTACH( theIndex ) ); + + return gp_Pnt( aCoords[0], aCoords[1], aCoords[2] ); +} + +//================================================================================= +// function : SetShapeSel +// purpose : +//================================================================================= +void GEOMGUI_AnnotationAttrs::SetShapeSel( const int theIndex, const int theShapeType, const int theSubIdx ) +{ + std::vector aSelection( 2 ); + + aSelection[0] = theShapeType; + aSelection[1] = theSubIdx; + + myParameterMap->SetIntArray( PARAMETER_SHAPE( theIndex ), aSelection ); +} + +//================================================================================= +// function : GetShapeSel +// purpose : +//================================================================================= +void GEOMGUI_AnnotationAttrs::GetShapeSel( const int theIndex, int& theShapeType, int& theSubIdx ) const +{ + std::vector aSelection = + myParameterMap->GetIntArray( PARAMETER_SHAPE( theIndex ) ); + + theShapeType = aSelection[0]; + theSubIdx = aSelection[1]; +} + +//================================================================================= +// function : Append +// purpose : +//================================================================================= +void GEOMGUI_AnnotationAttrs::Append( const Properties& theProps ) +{ + this->Append( theProps, gp_Ax3() ); +} + +//================================================================================= +// function : Append +// purpose : +//================================================================================= +void GEOMGUI_AnnotationAttrs::Append( const Properties& theProps, const gp_Ax3& theShapeLCS ) +{ + const int aCount = this->GetNbAnnotation(); + this->SetNbAnnotation( aCount + 1 ); + this->SetProperties( aCount, theProps, theShapeLCS ); +} + +//================================================================================= +// function : Remove +// purpose : +//================================================================================= +void GEOMGUI_AnnotationAttrs::Remove( const Standard_Integer theIndex ) +{ + const int aCount = this->GetNbAnnotation(); + if ( theIndex < 0 || theIndex >= aCount ) { + return; + } + + std::vector aEntries( (aCount - 1) - theIndex ); + for ( int anI = theIndex + 1; anI < aCount; ++anI ) { + GetProperties( anI, aEntries[ anI - (theIndex + 1) ] ); + } + + SetNbAnnotation( theIndex ); + + for ( int anI = 0; anI < static_cast( aEntries.size() ); ++anI ) { + Append( aEntries[anI] ); + } +} + +//================================================================================= +// function : SetProperties +// purpose : +//================================================================================= +void GEOMGUI_AnnotationAttrs::SetProperties( const int theIndex, const Properties& theProps ) +{ + this->SetProperties( theIndex, theProps, gp_Ax3() ); +} + +//================================================================================= +// function : SetProperties +// purpose : +//================================================================================= +void GEOMGUI_AnnotationAttrs::SetProperties( const int theIndex, const Properties& theProps, + const gp_Ax3& theShapeLCS ) +{ + gp_Trsf aToShapeLCS; + aToShapeLCS.SetTransformation( gp_Ax3(), theShapeLCS ); + + this->SetText( theIndex, theProps.Text ); + this->SetIsVisible( theIndex, theProps.IsVisible ); + this->SetIsScreenFixed( theIndex, theProps.IsScreenFixed ); + this->SetShapeSel( theIndex, theProps.ShapeType, theProps.ShapeIndex ); + this->SetAttach( theIndex, theProps.Attach.Transformed( aToShapeLCS ) ); + this->SetPosition( theIndex, (theProps.IsScreenFixed) ? + theProps.Position : theProps.Position.Transformed( aToShapeLCS ) ); +} + +//================================================================================= +// function : GetProperties +// purpose : +//================================================================================= +void GEOMGUI_AnnotationAttrs::GetProperties( const int theIndex, Properties& theProps ) const +{ + theProps.Text = this->GetText( theIndex ); + theProps.IsVisible = this->GetIsVisible( theIndex ); + theProps.IsScreenFixed = this->GetIsScreenFixed( theIndex ); + theProps.Position = this->GetPosition( theIndex ); + theProps.Attach = this->GetAttach( theIndex ); + + this->GetShapeSel( theIndex, theProps.ShapeType, theProps.ShapeIndex ); +} + +//================================================================================= +// function : SetupPresentation +// purpose : +//================================================================================= +void GEOMGUI_AnnotationAttrs::SetupPresentation( const Handle(GEOM_Annotation)& thePresentation, + const Properties& theProps, + const gp_Ax3& theShapeLCS ) +{ + gp_Trsf aFromShapeLCS; + aFromShapeLCS.SetTransformation( theShapeLCS, gp_Ax3() ); + + TCollection_ExtendedString aText; + for (int i = 0; i < (int)theProps.Text.length(); i++ ) + aText.Insert( i + 1, theProps.Text[ i ].unicode() ); + + thePresentation->SetText( aText ); + thePresentation->SetIsScreenFixed( theProps.IsScreenFixed ); + thePresentation->SetAttachPoint( theProps.Attach.Transformed( aFromShapeLCS ) ); + thePresentation->SetPosition( (theProps.IsScreenFixed) ? + theProps.Position : theProps.Position.Transformed( aFromShapeLCS ) ); +} + +//================================================================================= +// function : SetupPresentation +// purpose : +//================================================================================= +void GEOMGUI_AnnotationAttrs::SetupPresentation( const Handle(GEOM_Annotation)& thePresentation, + const int theIndex, + const gp_Ax3& theShapeLCS ) +{ + Properties aProps; + this->GetProperties( theIndex, aProps ); + this->SetupPresentation( thePresentation, aProps, theShapeLCS ); +} diff --git a/src/GEOMGUI/GEOMGUI_AnnotationAttrs.h b/src/GEOMGUI/GEOMGUI_AnnotationAttrs.h new file mode 100755 index 000000000..9d93347aa --- /dev/null +++ b/src/GEOMGUI/GEOMGUI_AnnotationAttrs.h @@ -0,0 +1,220 @@ +// Copyright (C) 2007-2016 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, or (at your option) any later version. +// +// 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 +// + +// File : GEOMGUI_AnnotationAttrs.h +// Author : Anton POLETAEV, Open CASCADE S.A.S. +// + +#ifndef GEOMGUI_ANNOTATIONATTRS_H +#define GEOMGUI_ANNOTATIONATTRS_H + +// SALOME GUI includes +#include +#include + +// OCCT includes +#include +#include +#include + +// Qt, STL includes +#include + +class GEOM_Annotation; +class gp_Ax3; + +/*! + * \brief Attribute-style helper tool to manage shape annotation data of an object. + */ +class GEOMGUI_AnnotationAttrs : public Standard_Transient +{ +public: + + DEFINE_STANDARD_RTTIEXT( GEOMGUI_AnnotationAttrs, Standard_Transient ) + + //! Find annotation data defined for an object. + GEOMGUI_EXPORT static Handle(GEOMGUI_AnnotationAttrs) FindAttributes( const _PTR(SObject)& theObject ); + + //! Find or create annotation data fields for an object. + GEOMGUI_EXPORT static Handle(GEOMGUI_AnnotationAttrs) FindOrCreateAttributes( const _PTR(SObject)& theObject, + SalomeApp_Study* theStudy ); + + //! Remove annotation data fields for an object. + GEOMGUI_EXPORT static void Remove( const _PTR(SObject)& theObject ); + +// Import / Export +public: + + //! Exports annotation records as a property string. + GEOMGUI_EXPORT QString ExportAsPropertyString() const; + + //! Imports annotation records from a property string. + GEOMGUI_EXPORT void ImportFromPropertyString( const QString& theString ); + +public: + + /*! + * \ brief Structure representing visual properties of the shape annotation. + */ + struct Properties + { + QString Text; //!< Displayed annotation text. + bool IsVisible; //!< Application visibility flag of annotation. + bool IsScreenFixed; //!< Fixed screen mode flag. + gp_Pnt Position; //!< Position of the annotation. + gp_Pnt Attach; //!< Attachment point of the annotation. + int ShapeIndex; //!< Index of the annotated subshape. + int ShapeType; //!< Type of the annotated subshape. + }; + + //! Setup parameters of the annotation presentation with the properties given. + //! @param thePresentation [in] the presentation to setup. + //! @param theProps [in] the set of properties. + //! @param theShapeLCS [in] the local coordinate system of the shape. + GEOMGUI_EXPORT static void SetupPresentation( const Handle(GEOM_Annotation)& thePresentation, + const Properties& theProps, + const gp_Ax3& theShapeLCS ); + + //! Setup parameters of the annotation presentation with the properties of a definition. + //! @param thePresentation [in] the presentation to setup. + //! @param theIndex [in] the index of the annotation definition. + //! @param theShapeLCS [in] the local coordinate system of the shape. + GEOMGUI_EXPORT void SetupPresentation( const Handle(GEOM_Annotation)& thePresentation, + const int theIndex, + const gp_Ax3& theShapeLCS ); + +public: + + //! Changes count of annotation definitions stored on the object. + //! If the count is decreased the extra annotation definitions are + //! cleared out from the attribute. + //! @param theNumber [in] the new number of annotation definitions. + GEOMGUI_EXPORT void SetNbAnnotation( const int theCount ) const; + + //! Returns number of annotation definitions stored on the object. + GEOMGUI_EXPORT int GetNbAnnotation() const; + + //! Sets application visibility state of an annotation definition. + //! @param theIndex [in] the index of the annotation definition. + //! @param theIsVisible [in] the visibility state. + GEOMGUI_EXPORT void SetIsVisible( const int theIndex, const bool theIsVisible ); + + //! Returns applicationb visibility state of an annotaion definition. + GEOMGUI_EXPORT bool GetIsVisible( const int theIndex ) const; + + //! Sets annotation label's text. + //! @param theIndex [in] the index of the annotation definition. + //! @param theText [in] the text string. + GEOMGUI_EXPORT void SetText( const int theIndex, const QString& theText ); + + //! Returns annotation label's text. + GEOMGUI_EXPORT QString GetText( const int theIndex ) const; + + //! Sets screen fixed flag of the annotation definition. + //! @param theIndex [in] the index of the annotation definition. + //! @param theIsScreenFixed [in] the presentation flag. + GEOMGUI_EXPORT void SetIsScreenFixed( const int theIndex, const bool theIsScreenFixed ); + + //! Returns screen fixed flag of the annotation definition. + GEOMGUI_EXPORT bool GetIsScreenFixed( const int theIndex ) const; + + //! Sets position of the annotation definition. + //! @param theIndex [in] the index of the annotation definition. + //! @param thePosition [in] the position of the annotation label. + GEOMGUI_EXPORT void SetPosition( const int theIndex, const gp_Pnt& thePosition ); + + //! Returns position of the annotation definition. + GEOMGUI_EXPORT gp_Pnt GetPosition( const int theIndex ) const; + + //! Sets attach point of the annotation definition. + //! @param theIndex [in] the index of the annotation definition. + //! @param theAttach [in] the attach point of the annotation. + GEOMGUI_EXPORT void SetAttach( const int theIndex, const gp_Pnt& theAttach ); + + //! Returns attach point of the annotation definition. + GEOMGUI_EXPORT gp_Pnt GetAttach( const int theIndex ) const; + + //! Sets shape selection arguments. + //! @param theIndex [in] the index of the annotation definition. + //! @param theShapeType, theSubIdx [in] the type of the selected shape and the sub-shape index. + GEOMGUI_EXPORT void SetShapeSel( const int theIndex, const int theShapeType, const int theSubIdx ); + + //! Returns shape selection arguments. + //! @param theIndex [in] the index of the annotation definition. + //! @param theShapeType, theSubIdx [out] the type of the selected shape and the sub-shape index. + GEOMGUI_EXPORT void GetShapeSel( const int theIndex, int& theShapeType, int& theSubIdx ) const; + +public: + + //! Appends new annotation definition with the given properties. + GEOMGUI_EXPORT void Append( const Properties& theProps ); + + //! Appends new annotation definition with the given properties and converts + //! position and attachment points to the given shape's local frame of reference. + //! @param theShapeLCS [in] the position of shape's local frame of reference with respect + //! to the world frame of reference. + GEOMGUI_EXPORT void Append( const Properties& theProps, const gp_Ax3& theShapeLCS ); + + //! Removes annotation definition by the given index. + //! This methods performs iterative reindexing of elements starting + //! from the given index, so sequential removal should be performed + //! from the last element, or avoided at all. + GEOMGUI_EXPORT void Remove( const Standard_Integer theIndex ); + + //! Sets complete properties of an annotation definition. + //! @param theIndex [in] the index of the annotation definition. + //! @param theProps [in] the structure containing the properties. + GEOMGUI_EXPORT void SetProperties( const int theIndex, const Properties& theProps ); + + //! Sets complete properties of an annotation definition with converting + //! position and attachment points to the given shape's local frame + //! of reference. + //! @param theIndex [in] the index of the annotation definition. + //! @param theProps [in] the structure containing the properties. + //! @param theShapeLCS [in] the position of shape's local frame of reference with respect + //! to the world frame of reference. + GEOMGUI_EXPORT void SetProperties( const int theIndex, const Properties& theProps, const gp_Ax3& theShapeLCS ); + + //! Returns complete properties of an annotation definition. + //! @param theIndex [in] the index of the annotation definition. + //! @param theProps [out] the structure containing the properties. + GEOMGUI_EXPORT void GetProperties( const int theIndex, Properties& theProps ) const; + +private: + + GEOMGUI_AnnotationAttrs( const _PTR(SObject)& theObject, const _PTR(AttributeParameter)& theParameter ) + : myObj( theObject ), + myParameterMap( theParameter ) {} + + GEOMGUI_AnnotationAttrs( const GEOMGUI_AnnotationAttrs& theOther ) {} + + void operator=( const GEOMGUI_AnnotationAttrs& theOther ) {} + +private: + + _PTR(SObject) myObj; + _PTR(AttributeParameter) myParameterMap; +}; + +DEFINE_STANDARD_HANDLE( GEOMGUI_AnnotationAttrs, Standard_Transient ) + +#endif diff --git a/src/GEOMGUI/GEOMGUI_AnnotationMgr.cxx b/src/GEOMGUI/GEOMGUI_AnnotationMgr.cxx new file mode 100755 index 000000000..f46d527d3 --- /dev/null +++ b/src/GEOMGUI/GEOMGUI_AnnotationMgr.cxx @@ -0,0 +1,899 @@ +// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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, or (at your option) any later version. +// +// 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 +// + +#include "GEOMGUI_AnnotationMgr.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + + +GEOMGUI_AnnotationMgr::GEOMGUI_AnnotationMgr( SalomeApp_Application* theApplication ) +: myApplication( theApplication ) +{ +} + +QString GEOMGUI_AnnotationMgr::GetEntrySeparator() +{ + return "_annotation:"; +} + +//================================================================ +// Function : CreatePresentation +// Purpose : +//================================================================ +SALOME_Prs* GEOMGUI_AnnotationMgr::CreatePresentation( const GEOMGUI_AnnotationAttrs::Properties& theProperty, + GEOM::GEOM_Object_ptr theObject, + SOCC_Viewer* theView, + const QString& theEntry ) +{ + SOCC_Viewer* aView = viewOrActiveView( theView ); + if ( !aView ) { + return NULL; + } + + Handle ( GEOM_Annotation ) aPresentation = new GEOM_Annotation(); + if ( !theEntry.isEmpty() ) { + // owner should be set to provide selection mechanizm + Handle( SALOME_InteractiveObject ) anIO = new SALOME_InteractiveObject(); + anIO->setEntry( theEntry.toLatin1().constData() ); + aPresentation->SetOwner( anIO ); + } + + aPresentation->SetIsScreenFixed( theProperty.IsScreenFixed ); + + TopoDS_Shape aShape = GEOM_Client::get_client().GetShape( GeometryGUI::GetGeomGen(), theObject ); + if ( !aShape.IsNull() ) { + + gp_Ax3 aShapeLCS = gp_Ax3().Transformed( aShape.Location().Transformation() ); + + GEOMGUI_AnnotationAttrs::SetupPresentation( aPresentation, theProperty, aShapeLCS ); + + if ( theProperty.ShapeType == TopAbs_SHAPE ) { + + aPresentation->SetHilightShape( aShape ); + } + else if ( theProperty.ShapeIndex > 0 ) { + + TopTools_IndexedMapOfShape aSubShapeMap; + TopExp::MapShapes( aShape, static_cast( theProperty.ShapeType ), aSubShapeMap ); + if ( theProperty.ShapeIndex <= aSubShapeMap.Extent() ) { + + aPresentation->SetHilightShape( aSubShapeMap( theProperty.ShapeIndex ) ); + } + } + } + + setDisplayProperties( aPresentation, aView, getEntry( theObject ).c_str() ); + + // add Prs to preview + SUIT_ViewWindow* vw = getApplication()->desktop()->activeWindow(); + SOCC_Prs* aPrs = + dynamic_cast( ( aView )->CreatePrs( 0 ) ); + + if ( aPrs ) + aPrs->AddObject( aPresentation ); + + return aPrs; +} + +bool GEOMGUI_AnnotationMgr::IsDisplayed( const QString& theEntry, const int theIndex, SOCC_Viewer* theView ) const +{ + SOCC_Viewer* aView = viewOrActiveView( theView ); + if ( !aView || !myVisualized.contains( aView ) ) + return false; + + EntryToAnnotations anEntryToAnnotation = myVisualized[aView]; + if ( !anEntryToAnnotation.contains( theEntry ) ) + return false; + + AnnotationToPrs anAnnotationToPrs = anEntryToAnnotation[theEntry]; + if ( !anAnnotationToPrs.contains( theIndex ) ) + return false; + + return true; +} + +//======================================================================= +// function : GEOMGUI_AnnotationMgr::Display +// purpose : Displays annotation shape presentation in view. It creates an annotation presentation +// and stores it in an internal container +//======================================================================= +void GEOMGUI_AnnotationMgr::Display( const QString& theEntry, const int theIndex, SOCC_Viewer* theView, + const bool isStoreViewState, const bool isUpdateViewer ) +{ + SOCC_Viewer* aView = viewOrActiveView( theView ); + if ( !aView ) + return; + + if ( IsDisplayed( theEntry, theIndex, aView ) ) + return; + + GEOMGUI_AnnotationAttrs::Properties aProperty; + GEOM::GEOM_Object_ptr anObject; + getObject( theEntry, theIndex, anObject, aProperty ); + + // display presentation in the viewer + QString anEntry = QString("%1%2%3").arg(theEntry).arg(GetEntrySeparator()).arg(theIndex); + SALOME_Prs* aPrs = CreatePresentation( aProperty, anObject, aView, anEntry ); + ((SALOME_View*)aView)->Display( getDisplayer(), aPrs ); + if ( isUpdateViewer ) + getDisplayer()->UpdateViewer(); + + EntryToAnnotations anEntryToMap; + if ( myVisualized.contains( aView ) ) + anEntryToMap = myVisualized[aView]; + + // store displayed parameters to an internal container + AnnotationToPrs anAnnotationToPrsMap; + if ( anEntryToMap.contains( theEntry ) ) + anAnnotationToPrsMap = anEntryToMap[theEntry]; + anAnnotationToPrsMap[theIndex] = aPrs; + anEntryToMap[theEntry] = anAnnotationToPrsMap; + myVisualized[aView] = anEntryToMap; + + if ( isStoreViewState ) { + // change persistent for the entry: set visible state in true for indices which presentations are shown + storeVisibleState( theEntry, theView ); + storeFixedPosition( theEntry, theView ); + } +} + +void GEOMGUI_AnnotationMgr::Redisplay( const QString& theEntry, const int theIndex, + const GEOMGUI_AnnotationAttrs::Properties& theProperty ) +{ + SUIT_Session* ses = SUIT_Session::session(); + SUIT_Application* app = ses->activeApplication(); + if ( app ) + { + SUIT_Desktop* desk = app->desktop(); + QList wnds = desk->windows(); + SUIT_ViewWindow* wnd; + QListIterator it( wnds ); + while ( it.hasNext() && (wnd = it.next()) ) + { + SUIT_ViewManager* vman = wnd->getViewManager(); + if ( vman ) + { + SUIT_ViewModel* vmodel = vman->getViewModel(); + if ( vmodel ) + { + SOCC_Viewer* aView = dynamic_cast(vmodel); + if ( aView ) + Redisplay( theEntry, theIndex, theProperty, aView ); + } + } + } + } +} + +void GEOMGUI_AnnotationMgr::Redisplay( const QString& theEntry, const int theIndex, + const GEOMGUI_AnnotationAttrs::Properties& theProperty, + SOCC_Viewer* theView ) +{ + SOCC_Viewer* aView = viewOrActiveView( theView ); + if ( !aView ) + return; + + if ( !myVisualized.contains( aView ) ) + return; + + EntryToAnnotations anEntryToAnnotation = myVisualized[aView]; + if ( !anEntryToAnnotation.contains( theEntry ) ) + return; + + AnnotationToPrs anAnnotationToPrs = anEntryToAnnotation[theEntry]; + if ( !anAnnotationToPrs.contains( theIndex ) ) + return; + + GEOMGUI_AnnotationAttrs::Properties aProperty; + GEOM::GEOM_Object_ptr anObject; + getObject( theEntry, theIndex, anObject, aProperty ); + TopoDS_Shape aShape = GEOM_Client::get_client().GetShape( GeometryGUI::GetGeomGen(), anObject ); + gp_Ax3 aShapeLCS = gp_Ax3().Transformed( aShape.Location().Transformation() ); + + // erase presentation from the viewer + SALOME_Prs* aPrs = anAnnotationToPrs[theIndex]; + SOCC_Prs* anOCCPrs = dynamic_cast( aPrs ); + if ( anOCCPrs ) { + AIS_ListOfInteractive anIOs; + anOCCPrs->GetObjects( anIOs ); + AIS_ListIteratorOfListOfInteractive anIter( anIOs ); + + for ( ; anIter.More(); anIter.Next() ) { + Handle(AIS_InteractiveObject) aPrs = anIter.Value(); + Handle(GEOM_Annotation) aPresentation = Handle(GEOM_Annotation)::DownCast( aPrs ); + + GEOMGUI_AnnotationAttrs::SetupPresentation( aPresentation, theProperty, aShapeLCS ); + aView->getAISContext()->Redisplay( aPresentation ); + } + } +} + +void GEOMGUI_AnnotationMgr::Erase( const QString& theEntry, const int theIndex, SOCC_Viewer* theView, + const bool isUpdateViewer ) +{ + SOCC_Viewer* aView = viewOrActiveView( theView ); + if ( !aView ) + return; + + if ( !myVisualized.contains( aView ) ) + return; + + EntryToAnnotations anEntryToAnnotation = myVisualized[aView]; + if ( !anEntryToAnnotation.contains( theEntry ) ) + return; + + AnnotationToPrs anAnnotationToPrs = anEntryToAnnotation[theEntry]; + if ( !anAnnotationToPrs.contains( theIndex ) ) + return; + + // erase presentation from the viewer + SALOME_Prs* aPrs = anAnnotationToPrs[theIndex]; + ((SALOME_View*)aView)->Erase( getDisplayer(), aPrs ); + if ( isUpdateViewer ) + getDisplayer()->UpdateViewer(); + + // remove displayed parameters from an internal container + anAnnotationToPrs.remove( theIndex ); + anEntryToAnnotation[theEntry] = anAnnotationToPrs; + if (anAnnotationToPrs.isEmpty()) { + anEntryToAnnotation.remove( theEntry ); + } + else { + anEntryToAnnotation[theEntry] = anAnnotationToPrs; + } + myVisualized[aView] = anEntryToAnnotation; + + // change persistent for the entry: set visible state in true for indices which presentations are shown + storeVisibleState( theEntry, theView ); +} + +void GEOMGUI_AnnotationMgr::DisplayVisibleAnnotations( const QString& theEntry, SOCC_Viewer* theView, + const bool isUpdateViewer ) +{ + SalomeApp_Study* aStudy = dynamic_cast( getApplication()->activeStudy() ); + _PTR(SObject) aSObj = aStudy->studyDS()->FindObjectID( theEntry.toStdString() ); + const Handle(GEOMGUI_AnnotationAttrs) aShapeAnnotations = GEOMGUI_AnnotationAttrs::FindAttributes( aSObj ); + if ( !aShapeAnnotations.IsNull() ) { + const int aCount = aShapeAnnotations->GetNbAnnotation(); + std::vector isVisible( aCount ); + for ( int anIndex = 0; anIndex < aCount; ++anIndex ) + { + isVisible[anIndex] = aShapeAnnotations->GetIsVisible( anIndex ); + } + for ( int anIndex = 0; anIndex < aCount; ++anIndex ) + { + if ( isVisible[anIndex] ) + Display( theEntry, anIndex, theView, true, isUpdateViewer ); + } + } +} + +void GEOMGUI_AnnotationMgr::EraseVisibleAnnotations( const QString& theEntry, SOCC_Viewer* theView, + const bool isUpdateViewer ) +{ + SOCC_Viewer* aView = viewOrActiveView( theView ); + if ( !myVisualized.contains( aView ) ) + return; + + EntryToAnnotations anEntryToAnnotation = myVisualized[aView]; + if ( !anEntryToAnnotation.contains( theEntry ) ) + return; + AnnotationToPrs anAnnotationToPrs = anEntryToAnnotation[theEntry]; + + SalomeApp_Study* aStudy = dynamic_cast( getApplication()->activeStudy() ); + _PTR(SObject) aSObj = aStudy->studyDS()->FindObjectID( theEntry.toStdString() ); + const Handle(GEOMGUI_AnnotationAttrs) aShapeAnnotations = GEOMGUI_AnnotationAttrs::FindAttributes( aSObj ); + + const int aCount = aShapeAnnotations->GetNbAnnotation(); + for ( int anIndex = 0; anIndex < aCount; ++anIndex ) + { + if ( !anAnnotationToPrs.contains( anIndex ) ) + continue; + + // erase presentation from the viewer + SALOME_Prs* aPrs = anAnnotationToPrs[anIndex]; + ((SALOME_View*)aView)->Erase( getDisplayer(), aPrs ); + } + if ( isUpdateViewer ) + getDisplayer()->UpdateViewer(); + anEntryToAnnotation.remove( theEntry ); + myVisualized[aView] = anEntryToAnnotation; +} + +//======================================================================= +// function : GEOMGUI_AnnotationMgr::EraseRemovedAnnotation +// purpose : Method to update internal maps after removing an +// annotation from the object. +//======================================================================= +void GEOMGUI_AnnotationMgr::EraseRemovedAnnotation( const QString& theEntry, const int theIndex ) +{ + QMap::iterator aEntryMapIt = myVisualized.begin(); + for ( ; aEntryMapIt != myVisualized.end(); ++aEntryMapIt ) { + SOCC_Viewer* aView = aEntryMapIt.key(); + EntryToAnnotations& anEntryToAnnotation = aEntryMapIt.value(); + if ( !anEntryToAnnotation.contains( theEntry ) ) + continue; + + AnnotationToPrs aUpdatedToPrs; + AnnotationToPrs& anAnnotationToPrs = anEntryToAnnotation[theEntry]; + AnnotationToPrs::iterator anAnnotationIt = anAnnotationToPrs.begin(); + for ( ; anAnnotationIt != anAnnotationToPrs.end(); ++anAnnotationIt ) { + + const int aIndex = anAnnotationIt.key(); + SALOME_Prs* aPrs = anAnnotationIt.value(); + if ( aIndex > theIndex ) { + aUpdatedToPrs[aIndex - 1] = aPrs; + } + else if ( aIndex != theIndex ) { + aUpdatedToPrs[aIndex] = aPrs; + } + else { + ((SALOME_View*)aView)->Erase( getDisplayer(), aPrs ); + } + } + + anAnnotationToPrs = aUpdatedToPrs; + } + getDisplayer()->UpdateViewer(); +} + +//======================================================================= +// function : GEOMGUI_AnnotationMgr::UpdateVisibleAnnotations +// purpose : +//======================================================================= +void GEOMGUI_AnnotationMgr::UpdateVisibleAnnotations( const QString& theEntry, SOCC_Viewer* theView ) +{ + SOCC_Viewer* aView = viewOrActiveView( theView ); + if ( !myVisualized.contains( aView ) ) + return; + + EntryToAnnotations& anEntryToAnnotation = myVisualized[aView]; + if ( !anEntryToAnnotation.contains( theEntry ) ) + return; + + AnnotationToPrs& anAnnotationToPrs = anEntryToAnnotation[theEntry]; + AnnotationToPrs::iterator anIt = anAnnotationToPrs.begin(); + for (; anIt != anAnnotationToPrs.end(); ++anIt ) { + SOCC_Prs* aPrs = + dynamic_cast (anIt.value()); + + GEOMGUI_AnnotationAttrs::Properties aProperty; + GEOM::GEOM_Object_ptr anObject; + getObject( theEntry, anIt.key(), anObject, aProperty ); + TopoDS_Shape aShape = GEOM_Client::get_client().GetShape( GeometryGUI::GetGeomGen(), anObject ); + gp_Ax3 aShapeLCS = gp_Ax3().Transformed( aShape.Location().Transformation() ); + + AIS_ListOfInteractive aIObjects; + aPrs->GetObjects( aIObjects ); + AIS_ListOfInteractive::Iterator aIOIt( aIObjects ); + for ( ; aIOIt.More(); aIOIt.Next() ) { + + Handle(GEOM_Annotation) aPresentation = + Handle(GEOM_Annotation)::DownCast( aIOIt.Value() ); + + if ( aPresentation.IsNull() ) + continue; + + if ( !aShape.IsNull() ) { + + gp_Ax3 aShapeLCS = gp_Ax3().Transformed( aShape.Location().Transformation() ); + GEOMGUI_AnnotationAttrs::SetupPresentation( aPresentation, aProperty, aShapeLCS ); + if ( aProperty.ShapeType == TopAbs_SHAPE ) { + aPresentation->SetHilightShape( aShape ); + } + else if ( aProperty.ShapeIndex > 0 ) { + TopTools_IndexedMapOfShape aSubShapeMap; + TopExp::MapShapes( aShape, static_cast( aProperty.ShapeType ), aSubShapeMap ); + if ( aProperty.ShapeIndex <= aSubShapeMap.Extent() ) { + aPresentation->SetHilightShape( aSubShapeMap( aProperty.ShapeIndex ) ); + } + } + } + + setDisplayProperties( aPresentation, aView, theEntry ); + + aView->getAISContext()->Redisplay( aPresentation ); + } + } + getDisplayer()->UpdateViewer(); +} + +void GEOMGUI_AnnotationMgr::DisplayAllAnnotations( SOCC_Viewer* theView ) +{ + SOCC_Viewer* aView = viewOrActiveView( theView ); + if ( !myVisualized.contains( aView ) ) + return; + + GeometryGUI* aModule = dynamic_cast( getApplication()->activeModule() ); + GEOMGUI_TextTreeWdg* aTextWidget = aModule->GetTextTreeWdg(); + QList anEntries = aTextWidget->getAllEntries( GEOMGUI_TextTreeWdg::AnnotationShape ); + + SalomeApp_Study* aStudy = dynamic_cast( getApplication()->activeStudy() ); + for ( int i = 0, aCount = anEntries.size(); i < aCount; i++ ) { + QString anEntry = anEntries[i]; + + _PTR(SObject) aSObj = aStudy->studyDS()->FindObjectID( anEntry.toStdString() ); + if ( !aSObj ) + continue; + + const Handle(GEOMGUI_AnnotationAttrs) aShapeAnnotations = GEOMGUI_AnnotationAttrs::FindAttributes( aSObj ); + if ( aShapeAnnotations.IsNull() ) + continue; + + int anAnnotationsCount = aShapeAnnotations->GetNbAnnotation(); + for ( int anIndex = 0; anIndex < anAnnotationsCount; ++anIndex ) + { + Display( anEntry, anIndex, aView, false, false ); + } + getDisplayer()->UpdateViewer(); + storeVisibleState( anEntry, aView ); + storeFixedPosition( anEntry, aView ); + } +} + +void GEOMGUI_AnnotationMgr::EraseAllAnnotations( SOCC_Viewer* theView ) +{ + SOCC_Viewer* aView = viewOrActiveView( theView ); + if ( !myVisualized.contains( aView ) ) + return; + + GeometryGUI* aModule = dynamic_cast( getApplication()->activeModule() ); + GEOMGUI_TextTreeWdg* aTextWidget = aModule->GetTextTreeWdg(); + QList anEntries = aTextWidget->getAllEntries( GEOMGUI_TextTreeWdg::AnnotationShape ); + + for ( int i = 0, aCount = anEntries.size(); i < aCount; i++ ) { + QString anEntry = anEntries[i]; + EraseVisibleAnnotations( anEntry, aView, false ); + storeVisibleState( anEntry, aView ); + } + getDisplayer()->UpdateViewer(); +} + +void GEOMGUI_AnnotationMgr::SetPreviewStyle( const QString& theEntry, const int theIndex, const bool theIsPreview ) +{ + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + const QColor aFontColor = aResMgr->colorValue( "Geometry", "shape_annotation_font_color", QColor( 255, 255, 255 ) ); + const QColor aLineColor = aResMgr->colorValue( "Geometry", "shape_annotation_line_color", QColor( 255, 255, 255 ) ); + + const Quantity_Color aOcctFontColor( aFontColor.redF(), aFontColor.greenF(), aFontColor.blueF(), Quantity_TOC_RGB ); + const Quantity_Color aOcctLineColor( aLineColor.redF(), aLineColor.greenF(), aLineColor.blueF(), Quantity_TOC_RGB ); + + QMap::Iterator aViewIt = myVisualized.begin(); + for (; aViewIt != myVisualized.end(); ++aViewIt ) { + + Handle(GEOM_Annotation) aPresentation = getAISPresentation ( theEntry, theIndex, aViewIt.key() ); + if ( aPresentation.IsNull() ) { + continue; + } + + if ( theIsPreview ) { + aPresentation->SetTextColor( Quantity_NOC_VIOLET ); + aPresentation->SetLineColor( Quantity_NOC_VIOLET ); + aPresentation->SetDepthCulling( Standard_False ); + } + else { + aPresentation->SetTextColor( aOcctFontColor ); + aPresentation->SetLineColor( aOcctLineColor ); + aPresentation->SetDepthCulling( Standard_True ); + } + } + getDisplayer()->UpdateViewer(); +} + +Handle(SALOME_InteractiveObject) GEOMGUI_AnnotationMgr::FindInteractiveObject( const QString& theEntry, + const int theIndex, + SOCC_Viewer* theView ) const +{ + Handle(SALOME_InteractiveObject) anIO; + + SOCC_Viewer* aView = viewOrActiveView( theView ); + if ( !myVisualized.contains( aView ) ) + return anIO; + + EntryToAnnotations anEntryToAnnotation = myVisualized[aView]; + if ( !anEntryToAnnotation.contains( theEntry ) ) + return anIO; + + AnnotationToPrs anAnnotationToPrs = anEntryToAnnotation[theEntry]; + if ( !anAnnotationToPrs.contains(theIndex) ) + return anIO; + + SALOME_Prs* aPrs = anAnnotationToPrs[theIndex]; + SOCC_Prs* anOCCPrs = dynamic_cast( aPrs ); + if ( !anOCCPrs ) + return anIO; + + AIS_ListOfInteractive anIOs; + anOCCPrs->GetObjects( anIOs ); + AIS_ListIteratorOfListOfInteractive anIter( anIOs ); + for ( ; anIter.More() && anIO.IsNull(); anIter.Next() ) { + Handle(AIS_InteractiveObject) aPrs = anIter.Value(); + if ( aPrs->GetOwner() ) + anIO = Handle(SALOME_InteractiveObject)::DownCast( aPrs->GetOwner() ); + } + return anIO; +} + +int GEOMGUI_AnnotationMgr::FindAnnotationIndex( Handle(SALOME_InteractiveObject) theIO, + SOCC_Viewer* theView ) +{ + int anIndex = -1; + + SOCC_Viewer* aView = viewOrActiveView( theView ); + if ( !myVisualized.contains( aView ) ) + return anIndex; + + QString anEntry = theIO->getEntry(); + + EntryToAnnotations anEntryToAnnotation = myVisualized[aView]; + if ( !anEntryToAnnotation.contains( anEntry ) ) + return anIndex; + + AnnotationToPrs anAnnotationToPrs = anEntryToAnnotation[anEntry]; + //typedef QMap AnnotationToPrs; + AnnotationToPrs::const_iterator anIt = anAnnotationToPrs.begin(), + aLast = anAnnotationToPrs.end(); + for (; anIt != aLast && anIndex < 0; anIt++) { + SALOME_Prs* aPrs = anIt.value(); + SOCC_Prs* anOCCPrs = dynamic_cast( aPrs ); + if ( !anOCCPrs ) + continue; + + AIS_ListOfInteractive anIOs; + anOCCPrs->GetObjects( anIOs ); + AIS_ListIteratorOfListOfInteractive anIter( anIOs ); + for ( ; anIter.More() && anIndex < 0; anIter.Next() ) { + Handle(AIS_InteractiveObject) aPrs = anIter.Value(); + if ( aPrs->GetOwner() ) { + Handle(SALOME_InteractiveObject) aPrsOwner = Handle(SALOME_InteractiveObject)::DownCast(aPrs->GetOwner()); + if ( aPrsOwner == theIO ) + anIndex = anIt.key(); + } + } + } + + return anIndex; +} + +//======================================================================= +// function : GEOMGUI_AnnotationMgr::RemoveView +// purpose : +//======================================================================= +void GEOMGUI_AnnotationMgr::RemoveView( SOCC_Viewer* theView ) +{ + if ( !theView && myVisualized.contains( theView ) ) + myVisualized.remove( theView ); +} + +QString GEOMGUI_AnnotationMgr::getDisplayedIndicesInfo( const QString& theEntry, SOCC_Viewer* theView ) const +{ + QString aDisplayedIndices; + + SalomeApp_Study* aStudy = dynamic_cast( getApplication()->activeStudy() ); + _PTR(SObject) aSObj = aStudy->studyDS()->FindObjectID( theEntry.toStdString() ); + if ( !aSObj ) + { + return aDisplayedIndices; + } + const Handle(GEOMGUI_AnnotationAttrs) aShapeAnnotations = GEOMGUI_AnnotationAttrs::FindAttributes( aSObj ); + if ( !aShapeAnnotations.IsNull() ) + { + const int aCount = aShapeAnnotations->GetNbAnnotation(); + QStringList anIndices; + for ( int anIndex = 0; anIndex < aCount; ++anIndex ) + { + if (IsDisplayed( theEntry, anIndex, theView ) ) + anIndices.append( QString::number(anIndex) ); + } + aDisplayedIndices = anIndices.join(";"); + } + return aDisplayedIndices; +} + +void GEOMGUI_AnnotationMgr::setDisplayedIndicesInfo( const QString& theEntry, SOCC_Viewer* theView, + const QString theIndicesInfo ) +{ + if ( theIndicesInfo.isEmpty() ) + return; + + QStringList anIndices = theIndicesInfo.split( ";" ); + for ( int i = 0, aCount = anIndices.size(); i < aCount; i++ ) { + Display( theEntry, anIndices[i].toInt(), theView ); + } +} + +GEOM_Displayer* GEOMGUI_AnnotationMgr::getDisplayer() const +{ + LightApp_Module* aModule = dynamic_cast( getApplication()->activeModule() ); + return dynamic_cast( aModule->displayer() ); +} + +SOCC_Viewer* GEOMGUI_AnnotationMgr::viewOrActiveView( SOCC_Viewer* theView ) const +{ + SOCC_Viewer* aView = theView; + if ( !aView ) { + SalomeApp_Application* anApp = getApplication(); + SUIT_ViewWindow* anActiveWindow = anApp->desktop()->activeWindow(); + if ( anActiveWindow ) { + aView = dynamic_cast( anActiveWindow->getViewManager()->getViewModel() ); + } + } + return aView; +} + +QString GEOMGUI_AnnotationMgr::makeAnnotationEntry( const QString& theEntry, const int theIndex ) +{ + return QString("%1%2%3").arg(theEntry).arg(GetEntrySeparator()).arg(theIndex); +} + +bool GEOMGUI_AnnotationMgr::getIndexFromEntry( const QString& theEntry, QString& theObjEntry, int& theIndex ) +{ + QStringList aSplit = theEntry.split( GetEntrySeparator() ); + if ( aSplit.size() < 2 ) + return false; + + bool isOk = true; + theObjEntry = aSplit.at( 0 ); + theIndex = aSplit.at( 1 ).toInt( &isOk ); + return isOk; +} + +void GEOMGUI_AnnotationMgr::getObject( const QString& theEntry, const int theIndex, + GEOM::GEOM_Object_ptr& theObject, + GEOMGUI_AnnotationAttrs::Properties& theProperty ) +{ + SalomeApp_Study* aStudy = dynamic_cast( getApplication()->activeStudy() ); + _PTR(SObject) aSObj = aStudy->studyDS()->FindObjectID( theEntry.toStdString() ); + const Handle(GEOMGUI_AnnotationAttrs) aShapeAnnotations = GEOMGUI_AnnotationAttrs::FindAttributes( aSObj ); + if ( !aShapeAnnotations.IsNull() ) { + aShapeAnnotations->GetProperties( theIndex, theProperty ); + + theObject = GEOM::GEOM_Object::_narrow( GeometryGUI::ClientSObjectToObject(aSObj) ); + } +} + +void GEOMGUI_AnnotationMgr::storeFixedPosition( const QString& theEntry, SOCC_Viewer* theView ) +{ + SOCC_Viewer* aView = viewOrActiveView( theView ); + if ( !aView || !myVisualized.contains( aView ) ) + return; + + SalomeApp_Study* aStudy = dynamic_cast( getApplication()->activeStudy() ); + _PTR(SObject) aSObj = aStudy->studyDS()->FindObjectID( theEntry.toStdString() ); + const Handle(GEOMGUI_AnnotationAttrs) aShapeAnnotations = GEOMGUI_AnnotationAttrs::FindAttributes( aSObj ); + if ( aShapeAnnotations.IsNull() ) + return; + + + EntryToAnnotations anEntryToAnnotation = myVisualized[aView]; + AnnotationToPrs anAnnotationToPrs; + if ( anEntryToAnnotation.contains( theEntry ) ) + anAnnotationToPrs = anEntryToAnnotation[theEntry]; + + AnnotationToPrs::iterator anIt = anAnnotationToPrs.begin(); + for (; anIt != anAnnotationToPrs.end(); ++anIt ) { + int anIndex = anIt.key(); + bool isFixedAnnotation = aShapeAnnotations->GetIsScreenFixed( anIndex ); + if ( !isFixedAnnotation ) + continue; + + SOCC_Prs* aPrs = dynamic_cast (anIt.value()); + Handle(GEOM_Annotation) anAnnotationPresentation; + + AIS_ListOfInteractive aIObjects; + aPrs->GetObjects( aIObjects ); + AIS_ListOfInteractive::Iterator aIOIt( aIObjects ); + for ( ; aIOIt.More(); aIOIt.Next() ) { + anAnnotationPresentation = Handle(GEOM_Annotation)::DownCast( aIOIt.Value() ); + if ( !anAnnotationPresentation.IsNull() ) + break; + } + if ( !anAnnotationPresentation.IsNull() ) + aShapeAnnotations->SetPosition( anIndex, anAnnotationPresentation->GetPosition() ); + } +} + +void GEOMGUI_AnnotationMgr::storeVisibleState( const QString& theEntry, SOCC_Viewer* theView ) +{ + SOCC_Viewer* aView = viewOrActiveView( theView ); + if ( !aView || !myVisualized.contains( aView ) ) + return; + + EntryToAnnotations anEntryToAnnotation = myVisualized[aView]; + AnnotationToPrs anAnnotationToPrs; + if ( anEntryToAnnotation.contains( theEntry ) ) + anAnnotationToPrs = anEntryToAnnotation[theEntry]; + + + SalomeApp_Study* aStudy = dynamic_cast( getApplication()->activeStudy() ); + _PTR(SObject) aSObj = aStudy->studyDS()->FindObjectID( theEntry.toStdString() ); + const Handle(GEOMGUI_AnnotationAttrs) aShapeAnnotations = GEOMGUI_AnnotationAttrs::FindAttributes( aSObj ); + if ( !aShapeAnnotations.IsNull() ) { + const int aCount = aShapeAnnotations->GetNbAnnotation(); + for ( int anIndex = 0; anIndex < aCount; ++anIndex ) { + bool aVisible = anAnnotationToPrs.contains( anIndex ); + aShapeAnnotations->SetIsVisible( anIndex, aVisible ); + } + } +} + +//======================================================================= +// function : GEOMGUI_AnnotationMgr::getEntry +// purpose : +//======================================================================= +std::string GEOMGUI_AnnotationMgr::getEntry( const GEOM::GEOM_Object_ptr theObject ) +{ + SUIT_Session* session = SUIT_Session::session(); + SalomeApp_Application* app = dynamic_cast( session->activeApplication() ); + if ( app ) + { + CORBA::String_var IOR = app->orb()->object_to_string( theObject ); + if ( strcmp(IOR.in(), "") != 0 ) + { + SalomeApp_Study* study = ( SalomeApp_Study* )app->activeStudy(); + _PTR(SObject) SO ( study->studyDS()->FindObjectIOR( std::string(IOR) ) ); + if ( SO ) + return SO->GetID(); + } + } + return std::string(); +} + +//======================================================================= +// function : GEOMGUI_AnnotationMgr::getName +// purpose : +//======================================================================= +std::string GEOMGUI_AnnotationMgr::getName( const GEOM::GEOM_Object_ptr theObject ) +{ + SUIT_Session* session = SUIT_Session::session(); + SalomeApp_Application* app = dynamic_cast( session->activeApplication() ); + if ( app ) + { + CORBA::String_var IOR = app->orb()->object_to_string( theObject ); + if ( strcmp(IOR.in(), "") != 0 ) + { + SalomeApp_Study* study = ( SalomeApp_Study* )app->activeStudy(); + _PTR(SObject) aSObj ( study->studyDS()->FindObjectIOR( std::string(IOR) ) ); + + _PTR(GenericAttribute) anAttr; + + if ( aSObj && aSObj->FindAttribute( anAttr, "AttributeName") ) + { + _PTR(AttributeName) aNameAttr( anAttr ); + return aNameAttr->Value(); + } + } + } + return std::string(); +} + +//======================================================================= +// function : GEOMGUI_AnnotationMgr::setDisplayProperties +// purpose : +//======================================================================= +void GEOMGUI_AnnotationMgr::setDisplayProperties( const Handle(GEOM_Annotation)& thePrs, + SOCC_Viewer* theView, + const QString& theEntry ) +{ + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + const QFont aFont = aResMgr->fontValue( "Geometry", "shape_annotation_font", QFont( "Y14.5M-2009", 24 ) ); + const QColor aFontColor = aResMgr->colorValue( "Geometry", "shape_annotation_font_color", QColor( 0, 0, 127 ) ); + const QColor aLineColor = aResMgr->colorValue( "Geometry", "shape_annotation_line_color", QColor( 0, 0, 127 ) ); + const double aLineWidth = aResMgr->doubleValue( "Geometry", "shape_annotation_line_width", 1.0 ); + const int aLineStyle = aResMgr->integerValue( "Geometry", "shape_annotation_line_style", 0 ); + const bool isAutoHide = aResMgr->booleanValue( "Geometry", "shape_annotation_autohide", false ); + + const Quantity_Color aOcctFontColor( aFontColor.redF(), aFontColor.greenF(), aFontColor.blueF(), Quantity_TOC_RGB ); + const Quantity_Color aOcctLineColor( aLineColor.redF(), aLineColor.greenF(), aLineColor.blueF(), Quantity_TOC_RGB ); + const Standard_Real aFontHeight = aFont.pixelSize() != -1 ? aFont.pixelSize() : aFont.pointSize(); + + thePrs->SetFont( TCollection_AsciiString( aFont.family().toLatin1().data() ) ); + thePrs->SetTextHeight( aFontHeight ); + thePrs->SetTextColor( Quantity_Color( aFontColor.redF(), aFontColor.greenF(), aFontColor.blueF(), Quantity_TOC_RGB ) ); + thePrs->SetLineColor( Quantity_Color( aLineColor.redF(), aLineColor.greenF(), aLineColor.blueF(), Quantity_TOC_RGB ) ); + thePrs->SetLineWidth( aLineWidth ); + thePrs->SetLineStyle( static_cast( aLineStyle ) ); + thePrs->SetAutoHide( isAutoHide ? Standard_True : Standard_False ); + thePrs->SetDepthCulling( Standard_True ); + + SOCC_Viewer* aView = viewOrActiveView( theView ); + if ( aView && !theEntry.isEmpty() ) { + + SalomeApp_Study* aStudy = dynamic_cast( getApplication()->activeStudy() ); + int aMgrId = dynamic_cast< SUIT_ViewModel* >( aView )->getViewManager()->getGlobalId(); + QVariant aVal = aStudy->getObjectProperty( aMgrId, theEntry, GEOM::propertyName( GEOM::TopLevel ), QVariant() ); + bool isBringToFront = aVal.isValid() ? aVal.toBool() : false; + if( isBringToFront ) { + thePrs->SetZLayer( Graphic3d_ZLayerId_Topmost ); + } + else { + thePrs->SetDefaultZLayer(); + } + } + else { + thePrs->SetDefaultZLayer(); + } +} + +//======================================================================= +// function : GEOMGUI_AnnotationMgr::getAISPresentation +// purpose : +//======================================================================= +Handle(GEOM_Annotation) GEOMGUI_AnnotationMgr::getAISPresentation ( const QString& theEntry, + const int theIndex, + SOCC_Viewer* theView ) +{ + if ( !myVisualized.contains( theView ) ) { + return Handle(GEOM_Annotation)(); + } + + EntryToAnnotations& aEntryToAnnotation = myVisualized[theView]; + if ( !aEntryToAnnotation.contains( theEntry ) ) { + return Handle(GEOM_Annotation)(); + } + + AnnotationToPrs& aAnnotationToPrs = aEntryToAnnotation[theEntry]; + if ( !aAnnotationToPrs.contains( theIndex ) ) { + return Handle(GEOM_Annotation)(); + } + + SALOME_Prs* aPrs = aAnnotationToPrs[theIndex]; + + // set or unset preview style for the presentation + AIS_ListOfInteractive aIObjects; + ((SOCC_Prs*)aPrs)->GetObjects( aIObjects ); + AIS_ListOfInteractive::Iterator aIOIt( aIObjects ); + for ( ; aIOIt.More(); aIOIt.Next() ) { + return Handle(GEOM_Annotation)::DownCast( aIOIt.Value() ); + } + + return Handle(GEOM_Annotation)(); +} diff --git a/src/GEOMGUI/GEOMGUI_AnnotationMgr.h b/src/GEOMGUI/GEOMGUI_AnnotationMgr.h new file mode 100755 index 000000000..52d3b1260 --- /dev/null +++ b/src/GEOMGUI/GEOMGUI_AnnotationMgr.h @@ -0,0 +1,136 @@ +// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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, or (at your option) any later version. +// +// 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 +// + +#ifndef GEOMGUI_ANNOTATIONMGR_H +#define GEOMGUI_ANNOTATIONMGR_H + +#include "GEOM_GEOMGUI.hxx" + +#include +#include CORBA_SERVER_HEADER(GEOM_Gen) + +#include +#include + +#include +#include + +#include + +class SalomeApp_Application; +class GEOM_Annotation; +class GEOM_Displayer; + +/*! + * \brief A help class to process visualizatin of annotation presentations. + * It contains a map of presentations shown in each viewer. + * and correct 2D position persistent properties of annotations of active viewer. + * When the viewer is closed, information about the viewer is removed from the manager + */ +class GEOMGUI_EXPORT GEOMGUI_AnnotationMgr : public QObject +{ + Q_OBJECT; + +public: + GEOMGUI_AnnotationMgr( SalomeApp_Application* theApplication ); + ~GEOMGUI_AnnotationMgr() {} + + static QString GetEntrySeparator(); + + SALOME_Prs* CreatePresentation( const GEOMGUI_AnnotationAttrs::Properties& theProperty, + GEOM::GEOM_Object_ptr theObject, + SOCC_Viewer* theView = 0, + const QString& theEntry = QString() ); + + bool IsDisplayed( const QString& theEntry, const int theIndex, SOCC_Viewer* theView = 0 ) const; + void Display( const QString& theEntry, const int theIndex, SOCC_Viewer* theView = 0, + const bool isStoreViewState = true, const bool isUpdateViewer = true ); + void Erase( const QString& theEntry, const int theIndex, SOCC_Viewer* theView = 0, + const bool isUpdateViewer = true ); + void EraseRemovedAnnotation( const QString& theEntry, const int theIndex ); + void Redisplay( const QString& theEntry, const int theIndex, + const GEOMGUI_AnnotationAttrs::Properties& theProperties); + void Redisplay( const QString& theEntry, const int theIndex, + const GEOMGUI_AnnotationAttrs::Properties& theProperties, SOCC_Viewer* theView ); + + void DisplayVisibleAnnotations( const QString& theEntry, SOCC_Viewer* theView = 0, + const bool isUpdateViewer = true ); + void EraseVisibleAnnotations( const QString& theEntry, SOCC_Viewer* theView = 0, + const bool isUpdateViewer = true ); + void UpdateVisibleAnnotations( const QString& theEntry, SOCC_Viewer* theView = 0 ); + + void DisplayAllAnnotations( SOCC_Viewer* theView = 0 ); + void EraseAllAnnotations( SOCC_Viewer* theView = 0 ); + + void SetPreviewStyle( const QString& theEntry, const int theIndex, const bool theIsPreview ); + + void RemoveView( SOCC_Viewer* theView ); + + int FindAnnotationIndex( Handle(SALOME_InteractiveObject) theIO, + SOCC_Viewer* theView = 0 ); + + Handle(SALOME_InteractiveObject) FindInteractiveObject( const QString& theEntry, const int theIndex, + SOCC_Viewer* theView = 0 ) const; + + QString getDisplayedIndicesInfo( const QString& theEntry, SOCC_Viewer* theView ) const; + + void setDisplayedIndicesInfo( const QString& theEntry, SOCC_Viewer* theView, const QString theIndicesInfo ); + + QString makeAnnotationEntry( const QString& theEntry, const int theIndex ); + + void storeFixedPosition( const QString& theEntry, SOCC_Viewer* theView ); + + bool getIndexFromEntry( const QString& theEntry, QString& theObjEntry, int& theIndex ); + + bool isAnnotationEntry( const QString& theEntry ) { return theEntry.indexOf( GetEntrySeparator() ) != -1; } + +protected: + + SalomeApp_Application* getApplication() const { return myApplication; } + + GEOM_Displayer* getDisplayer() const; + + SOCC_Viewer* viewOrActiveView( SOCC_Viewer* theView ) const; + + void getObject( const QString& theEntry, const int theIndex, + GEOM::GEOM_Object_ptr& anObject, + GEOMGUI_AnnotationAttrs::Properties& aProperty ); + + void storeVisibleState( const QString& theEntry, SOCC_Viewer* theView ); + + std::string getEntry( const GEOM::GEOM_Object_ptr theObject ); + + std::string getName( const GEOM::GEOM_Object_ptr theObject ); + + void setDisplayProperties( const Handle(GEOM_Annotation)& thePrs, + SOCC_Viewer* theView = 0, + const QString& theEntry = QString() ); + + Handle(GEOM_Annotation) getAISPresentation ( const QString& theEntry, + const int theIndex, + SOCC_Viewer* theView ); + +private: + SalomeApp_Application* myApplication; + + typedef QMap AnnotationToPrs; + typedef QMap EntryToAnnotations; + QMap myVisualized; +}; +#endif diff --git a/src/GEOMGUI/GEOMGUI_DimensionProperty.h b/src/GEOMGUI/GEOMGUI_DimensionProperty.h index 3ff770055..a2397968c 100644 --- a/src/GEOMGUI/GEOMGUI_DimensionProperty.h +++ b/src/GEOMGUI/GEOMGUI_DimensionProperty.h @@ -42,6 +42,9 @@ class SalomeApp_Study; +class GEOMGUI_DimensionProperty; +typedef QSharedPointer DimensionPropertyPtr; + /*! * \brief Utility class to unpack/pack dimension presentations as object property of study. * diff --git a/src/GEOMGUI/GEOMGUI_OCCSelector.cxx b/src/GEOMGUI/GEOMGUI_OCCSelector.cxx index b79ea3d35..4ab85d38a 100644 --- a/src/GEOMGUI/GEOMGUI_OCCSelector.cxx +++ b/src/GEOMGUI/GEOMGUI_OCCSelector.cxx @@ -24,6 +24,7 @@ // Author : Alexander SOLOVYOV, Open CASCADE S.A.S. (alexander.solovyov@opencascade.com) // #include "GEOMGUI_OCCSelector.h" +#include "GEOM_Annotation.hxx" #include @@ -300,8 +301,16 @@ void GEOMGUI_OCCSelector::setSelection( const SUIT_DataOwnerPtrList& aList ) { anOwner = Handle(StdSelect_BRepOwner)::DownCast(owners( i )); - if ( anOwner.IsNull() || !anOwner->HasShape() ) + if ( anOwner.IsNull() || !anOwner->HasShape() ) { + if ( globalSelMap.contains( entryStr ) ) { + Handle(GEOM_Annotation::GEOM_AnnotationOwner) anAnnotationOwner = + Handle(GEOM_Annotation::GEOM_AnnotationOwner)::DownCast(owners( i )); + if ( !anAnnotationOwner.IsNull() ) { + ownersmap.Add( anAnnotationOwner ); + } + } continue; + } // GLOBAL selection if ( !anOwner->ComesFromDecomposition() && globalSelMap.contains( entryStr ) ) diff --git a/src/GEOMGUI/GEOMGUI_Selection.cxx b/src/GEOMGUI/GEOMGUI_Selection.cxx index 51fd17889..87026424e 100644 --- a/src/GEOMGUI/GEOMGUI_Selection.cxx +++ b/src/GEOMGUI/GEOMGUI_Selection.cxx @@ -25,6 +25,8 @@ #include "GEOMGUI_Selection.h" #include +#include +#include #include "GeometryGUI.h" #include "GEOM_Displayer.h" @@ -151,6 +153,8 @@ QVariant GEOMGUI_Selection::parameter( const QString& p ) const v = hasImported(); else if ( p == "allImported" ) v = allImported(); + else if (p == "annotationsCount") + v = annotationsCount(); else v = LightApp_Selection::parameter( p ); return v; @@ -198,6 +202,10 @@ QVariant GEOMGUI_Selection::parameter( const int idx, const QString& p ) const v = hasHiddenDimensions(idx); else if ( p == "hasVisibleDimensions" ) v = hasVisibleDimensions(idx); + else if ( p == "hasHiddenAnnotations" ) + v = hasHiddenAnnotations(idx); + else if ( p == "hasVisibleAnnotations" ) + v = hasVisibleAnnotations(idx); else v = LightApp_Selection::parameter( idx, p ); @@ -207,6 +215,9 @@ QVariant GEOMGUI_Selection::parameter( const int idx, const QString& p ) const // the method to skip temporary objects from selection (called from LightApp) bool GEOMGUI_Selection::processOwner( const LightApp_DataOwner* theOwner ) { + if ( theOwner->entry().contains( GEOMGUI_AnnotationMgr::GetEntrySeparator() ) ) { + myAnnotationEntries.append( theOwner->entry() ); + } return !theOwner->entry().contains("_"); } @@ -853,3 +864,63 @@ bool GEOMGUI_Selection::hasVisibleDimensions( const int theIndex ) const return isAnyVisible; } +int GEOMGUI_Selection::annotationsCount() const +{ + return myAnnotationEntries.size(); +} + +bool GEOMGUI_Selection::hasAnnotations( const int theIndex, bool& theHidden, bool& theVisible ) const +{ + SalomeApp_Study* appStudy = dynamic_cast( study() ); + if ( !appStudy ) + return false; + + QString anEntry = entry( theIndex ); + _PTR(Study) aStudy = appStudy->studyDS(); + if ( !aStudy || anEntry.isNull() ) + return false; + + _PTR(SObject) aSObj = appStudy->studyDS()->FindObjectID( anEntry.toStdString() ); + + const Handle(GEOMGUI_AnnotationAttrs) + aShapeAnnotations = GEOMGUI_AnnotationAttrs::FindAttributes( aSObj ); + + if ( aShapeAnnotations.IsNull() ) + return false; + + theHidden = false; + theVisible = false; + + const int aCount = aShapeAnnotations->GetNbAnnotation(); + for ( int anI = 0; anI < aCount; ++anI ) + { + if ( aShapeAnnotations->GetIsVisible( anI ) ) + theVisible = true; + else + theHidden = true; + } + + return aCount > 0; +} + +bool GEOMGUI_Selection::hasHiddenAnnotations( const int theIndex ) const +{ + bool isAnyVisible, isAnyHidden = false; + if ( !hasAnnotations( theIndex, isAnyHidden, isAnyVisible ) ) + { + return false; + } + + return isAnyHidden; +} + +bool GEOMGUI_Selection::hasVisibleAnnotations( const int theIndex ) const +{ + bool isAnyVisible, isAnyHidden = false; + if ( !hasAnnotations( theIndex, isAnyHidden, isAnyVisible ) ) + { + return false; + } + + return isAnyVisible; +} diff --git a/src/GEOMGUI/GEOMGUI_Selection.h b/src/GEOMGUI/GEOMGUI_Selection.h index c5d229aa8..76dda787c 100644 --- a/src/GEOMGUI/GEOMGUI_Selection.h +++ b/src/GEOMGUI/GEOMGUI_Selection.h @@ -85,6 +85,12 @@ private: bool hasHiddenDimensions( const int ) const; bool hasVisibleDimensions( const int ) const; + int annotationsCount() const; + + bool hasAnnotations( const int, bool&, bool& ) const; + bool hasHiddenAnnotations( const int ) const; + bool hasVisibleAnnotations( const int ) const; + GEOM::GEOM_Object_ptr getObject( const int ) const; GEOM::GEOM_BaseObject_ptr getBaseObject( const int ) const; @@ -98,6 +104,7 @@ private: private: GeomObjectVector myObjects; + QStringList myAnnotationEntries; }; #endif diff --git a/src/GEOMGUI/GEOMGUI_TextTreeSelector.cxx b/src/GEOMGUI/GEOMGUI_TextTreeSelector.cxx new file mode 100644 index 000000000..8d77a3d34 --- /dev/null +++ b/src/GEOMGUI/GEOMGUI_TextTreeSelector.cxx @@ -0,0 +1,168 @@ +// Copyright (C) 2015-2016 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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, or (at your option) any later version. +// +// 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 +// + +// File : GEOMGUI_TextTreeSelector.cxx +// Author : +// +#include "GEOMGUI_TextTreeSelector.h" +#include "GEOMGUI_TextTreeWdg.h" +#include "GEOMGUI_AnnotationMgr.h" + +#include "LightApp_DataOwner.h" +#include "LightApp_DataObject.h" +#include "LightApp_Application.h" +#include +#include + +/*! + \class GEOMGUI_TextTreeSelector + \brief Text tree selection handler class. It provides selection synchronization between + application and text tree widget. This selector listens item selection changed signal of + text tree widget to emit common selection changed signal of SUIT selector to start selection + synchronization. In get/setSelection selector processes annotation items. These items have + specific entry generated in annotation manager, having the "object entry:annotation_id" structure. +*/ + +/*! + \brief Constructor. + \param widget text tree widget + \param theManager selection manager +*/ +GEOMGUI_TextTreeSelector::GEOMGUI_TextTreeSelector( GEOMGUI_TextTreeWdg* theWidget, + GEOMGUI_AnnotationMgr* theAnnotationMgr, + SUIT_SelectionMgr* theManager ) +: SUIT_Selector( theManager, theWidget ), + myTextTree( theWidget ), myAnnotationMgr( theAnnotationMgr ) +{ + if ( myTextTree ) { + connect( myTextTree, SIGNAL( itemSelectionChanged() ), this, SLOT( onSelectionChanged() ) ); + } +} + +/*! + \brief Destructor. +*/ +GEOMGUI_TextTreeSelector::~GEOMGUI_TextTreeSelector() +{ +} + +/*! + \brief Get object browser. + \return a pointer to the text tree widget +*/ +GEOMGUI_TextTreeWdg* GEOMGUI_TextTreeSelector::textTree() const +{ + return myTextTree; +} + +/*! + \brief Get selector unique type. + \return selector type +*/ +QString GEOMGUI_TextTreeSelector::type() const +{ + return "TextTree"; +} + +/*! + \brief Called when the Object browser selection is changed. It emits signal to synchronize + selection in application. +*/ +void GEOMGUI_TextTreeSelector::onSelectionChanged() +{ + mySelectedList.clear(); + selectionChanged(); +} + +/*! + \brief Get list of currently selected annotation objects. + \param theList list to be filled with the selected objects owners + The list contains owners for interactive objects of annotations +*/ +void GEOMGUI_TextTreeSelector::getSelection( SUIT_DataOwnerPtrList& theList ) const +{ + if ( mySelectedList.count() == 0 ) { + + GEOMGUI_TextTreeSelector* aThisSelector = (GEOMGUI_TextTreeSelector*)this; + QMap > aSelectedAnnotations; + myTextTree->getSelected(aSelectedAnnotations); + + QMap >::const_iterator anIt = aSelectedAnnotations.begin(), + aLast = aSelectedAnnotations.end(); + for ( ; anIt != aLast; anIt++ ) { + QString anEntry = anIt.key(); + QList anIndices = anIt.value(); + QList::const_iterator anIdIt = anIndices.begin(), anIdLast = anIndices.end(); + for ( ; anIdIt != anIdLast; anIdIt++ ) { + int anIndex = *anIdIt; + Handle(SALOME_InteractiveObject) anIO = myAnnotationMgr->FindInteractiveObject( anEntry, anIndex ); + if ( anIO.IsNull() ) + continue; + + LightApp_DataOwner* owner = new LightApp_DataOwner( anIO ); + aThisSelector->mySelectedList.append( SUIT_DataOwnerPtr( owner ) ); + } + } + } + theList = mySelectedList; +} + +/*! + \brief Set selection. + \param theList list of the object owners to be set selected +*/ +void GEOMGUI_TextTreeSelector::setSelection( const SUIT_DataOwnerPtrList& theList ) +{ + if ( !myTextTree ) + return; + + QMap > aSelectedAnnotations; + DataObjectList objList; + for ( SUIT_DataOwnerPtrList::const_iterator it = theList.begin(); + it != theList.end(); ++it ) { + const LightApp_DataOwner* anOwner = dynamic_cast( (*it).operator->() ); + if ( !anOwner ) + continue; + Handle(SALOME_InteractiveObject) anIO = anOwner->IO(); + if ( anIO.IsNull() ) + continue; + + QString anIOEntry = anIO->getEntry(); + QStringList anAnnotationInfo = anIOEntry.split(GEOMGUI_AnnotationMgr::GetEntrySeparator()); + if (anAnnotationInfo.size() != 2 ) + continue; + + QString anEntry = anAnnotationInfo[0]; + int anAnnotationId = anAnnotationInfo[1].toInt(); + if ( anAnnotationId < 0) + continue; + + QList anIndices; + if ( aSelectedAnnotations.contains( anEntry ) ) + anIndices = aSelectedAnnotations[anEntry]; + + if ( !anIndices.contains( anAnnotationId ) ) + anIndices.append( anAnnotationId ); + + aSelectedAnnotations[anEntry] = anIndices; + } + myTextTree->setSelected(aSelectedAnnotations); + mySelectedList.clear(); +} + diff --git a/src/GEOMGUI/GEOMGUI_TextTreeSelector.h b/src/GEOMGUI/GEOMGUI_TextTreeSelector.h new file mode 100644 index 000000000..7ae88764c --- /dev/null +++ b/src/GEOMGUI/GEOMGUI_TextTreeSelector.h @@ -0,0 +1,63 @@ +// Copyright (C) 2015-2016 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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, or (at your option) any later version. +// +// 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 +// + +// File : GEOMGUI_TextTreeSelector.h +// Author : +// +#ifndef GEOMGUI_TEXTTREESELECTOR_H +#define GEOMGUI_TEXTTREESELECTOR_H + +#include "GEOM_GEOMGUI.hxx" + +#include +#include + +#include + +class GEOMGUI_TextTreeWdg; +class GEOMGUI_AnnotationMgr; + +class GEOMGUI_EXPORT GEOMGUI_TextTreeSelector : public QObject, public SUIT_Selector +{ + Q_OBJECT + +public: + GEOMGUI_TextTreeSelector( GEOMGUI_TextTreeWdg* theWidget, + GEOMGUI_AnnotationMgr* theAnnotationMgr, + SUIT_SelectionMgr* theManager ); + virtual ~GEOMGUI_TextTreeSelector(); + + GEOMGUI_TextTreeWdg* textTree() const; + + virtual QString type() const; + +private slots: + void onSelectionChanged(); + +protected: + virtual void getSelection( SUIT_DataOwnerPtrList& ) const; + virtual void setSelection( const SUIT_DataOwnerPtrList& ); + +private: + GEOMGUI_TextTreeWdg* myTextTree; + GEOMGUI_AnnotationMgr* myAnnotationMgr; + SUIT_DataOwnerPtrList mySelectedList; +}; + +#endif diff --git a/src/GEOMGUI/GEOMGUI_TextTreeWdg.cxx b/src/GEOMGUI/GEOMGUI_TextTreeWdg.cxx old mode 100644 new mode 100755 index 2e3218b1e..d69e7bba2 --- a/src/GEOMGUI/GEOMGUI_TextTreeWdg.cxx +++ b/src/GEOMGUI/GEOMGUI_TextTreeWdg.cxx @@ -22,6 +22,8 @@ #include "GEOMGUI_TextTreeWdg.h" #include "GEOMGUI_DimensionProperty.h" +#include "GEOMGUI_AnnotationAttrs.h" +#include "GEOMGUI_AnnotationMgr.h" #include "GeometryGUI.h" #include "GeometryGUI_Operations.h" #include @@ -49,6 +51,110 @@ #include #include +// ---------------------------------------------------------------------------- +// Common style interface for managing dimension and annotation properties +// ---------------------------------------------------------------------------- +namespace +{ + //! Access interface implementation for shape dimension attribute/property. + class DimensionsProperty : public GEOMGUI_TextTreeWdg::VisualProperty + { + public: + + DimensionsProperty( SalomeApp_Study* theStudy, const std::string& theEntry ) : + myStudy( theStudy ), myEntry( theEntry ) { + myAttr.LoadFromAttribute( theStudy, theEntry ); + } + virtual int GetNumber() Standard_OVERRIDE { + return myAttr.GetNumber(); + } + virtual QString GetName( const int theIndex ) Standard_OVERRIDE { + return myAttr.GetName( theIndex ); + } + virtual bool GetIsVisible( const int theIndex ) Standard_OVERRIDE { + return myAttr.IsVisible( theIndex ); + } + virtual void SetIsVisible( const int theIndex, const bool theIsVisible ) Standard_OVERRIDE { + myAttr.SetVisible( theIndex, theIsVisible ); + } + virtual void Save() Standard_OVERRIDE { + myAttr.SaveToAttribute( myStudy, myEntry ); + } + GEOMGUI_DimensionProperty& Attr() { return myAttr; } + + private: + GEOMGUI_DimensionProperty myAttr; + SalomeApp_Study* myStudy; + std::string myEntry; + }; + + //! Access interface implementation for shape annotation attribute. + class AnnotationsProperty : public GEOMGUI_TextTreeWdg::VisualProperty + { + public: + + AnnotationsProperty( SalomeApp_Study* theStudy, const std::string& theEntry ) { + myEntry = theEntry.c_str(); + myStudy = theStudy; + _PTR(SObject) aSObj = theStudy->studyDS()->FindObjectID( theEntry ); + if ( aSObj ) { + myAttr = GEOMGUI_AnnotationAttrs::FindAttributes( aSObj ); + } + } + virtual int GetNumber() Standard_OVERRIDE { + return !myAttr.IsNull() ? myAttr->GetNbAnnotation() : 0; + } + virtual QString GetName( const int theIndex ) Standard_OVERRIDE { + return !myAttr.IsNull() ? myAttr->GetText( theIndex ) : QString(); + } + virtual bool GetIsVisible( const int theIndex ) Standard_OVERRIDE { + GEOMGUI_AnnotationMgr* aMgr = annotationMgr(); + if (!aMgr) { + return false; + } + return aMgr->IsDisplayed( myEntry, theIndex ); + } + virtual void SetIsVisible( const int theIndex, const bool theIsVisible ) Standard_OVERRIDE { + GEOMGUI_AnnotationMgr* aMgr = annotationMgr(); + if (!aMgr) { + return; + } + if (theIsVisible) + annotationMgr()->Display(myEntry, theIndex); + else + annotationMgr()->Erase(myEntry, theIndex); + } + virtual void Save() Standard_OVERRIDE { + /* every change is automatically saved */ + } + Handle(GEOMGUI_AnnotationAttrs) Attr() { return myAttr; } + +protected: + GEOMGUI_AnnotationMgr* annotationMgr() const + { + CAM_Application* anApp = dynamic_cast(myStudy->application()); + GeometryGUI* aModule = dynamic_cast(anApp->activeModule()); + if (!aModule) { + return NULL; + } + return aModule->GetAnnotationMgr(); + } + +private: + QString myEntry; + Handle(GEOMGUI_AnnotationAttrs) myAttr; + SalomeApp_Study* myStudy; + }; +} + +// ---------------------------------------------------------------------------- +// Text tree widget implementation +// ---------------------------------------------------------------------------- + +//================================================================================= +// function : Constructor +// purpose : +//================================================================================= GEOMGUI_TextTreeWdg::GEOMGUI_TextTreeWdg( SalomeApp_Application* app ) : myDisplayer(NULL) { @@ -84,6 +190,12 @@ GEOMGUI_TextTreeWdg::GEOMGUI_TextTreeWdg( SalomeApp_Application* app ) myDimensionsItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled ); addTopLevelItem( myDimensionsItem ); + rootNames.clear(); + rootNames << tr("GEOM_ANNOTATIONS") << ""; + myAnnotationsItem = new QTreeWidgetItem( this, rootNames ); + myAnnotationsItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled ); + addTopLevelItem( myAnnotationsItem ); + // get a free dockable window id myWindowID = 11; while( app->dockWindow( myWindowID )) @@ -93,18 +205,28 @@ GEOMGUI_TextTreeWdg::GEOMGUI_TextTreeWdg( SalomeApp_Application* app ) createActions(); setContextMenuPolicy( Qt::CustomContextMenu ); connect( this, SIGNAL( customContextMenuRequested(const QPoint&) ), - this, SLOT( showContextMenu(const QPoint&) ) ); + this, SLOT( showContextMenu(const QPoint&) ) ); - connect( myStudy, SIGNAL( objVisibilityChanged( QString, Qtx::VisibilityState ) ), - this, SLOT( updateVisibilityColumn( QString, Qtx::VisibilityState ) ) ); connect( app->objectBrowser(), SIGNAL( updated() ), this, SLOT( updateTree() ) ); + GeometryGUI* aGeomGUI = dynamic_cast( app->module( "Geometry" ) ); - connect( aGeomGUI, SIGNAL( DimensionsUpdated( const QString& ) ), this, SLOT( updateBranch( const QString& ) ) ); - connect( this, SIGNAL( itemClicked( QTreeWidgetItem*, int) ), - this, SLOT( onItemClicked( QTreeWidgetItem*, int ) ) ); + connect( aGeomGUI, SIGNAL( DimensionsUpdated( const QString& ) ), + this, SLOT( updateDimensionBranch( const QString& ) ) ); + connect( aGeomGUI, SIGNAL( SignalAnnotationsUpdated( const QString& ) ), + this, SLOT( updateAnnotationBranch( const QString& ) ) ); + connect( aGeomGUI, SIGNAL( SignalTextTreeRenameObject( const QString& ) ), + this, SLOT( updateObjectName( const QString& ) ) ); + connect( this, SIGNAL( itemClicked( QTreeWidgetItem*, int) ), + this, SLOT( onItemClicked( QTreeWidgetItem*, int ) ) ); + connect( myStudy, SIGNAL( objVisibilityChanged( QString, Qtx::VisibilityState ) ), + this, SLOT( onUpdateVisibilityColumn( QString, Qtx::VisibilityState ) ) ); } +//================================================================================= +// function : Destructor +// purpose : +//================================================================================= GEOMGUI_TextTreeWdg::~GEOMGUI_TextTreeWdg() { //std::cout<<"~GEOMGUI_TextTreeWdg"<NewChildIterator( SC ) ); anIter->InitEx( true ); - QList objEntries = myObjects.keys(); + QList aDimensionObjEntries = getObjects( DimensionShape ).keys(); + QList anAnnotationObjEntries = getObjects( AnnotationShape ).keys(); while( anIter->More() ) { - _PTR(SObject) valSO ( anIter->Value() ); - _PTR(SObject) refSO; - if ( !valSO->ReferencedObject( refSO ) ) { - // update tree of object's dimensions - QString anEntry = valSO->GetID().c_str(); - updateBranch( anEntry ); - objEntries.removeAll( anEntry ); - } - anIter->Next(); + _PTR(SObject) valSO ( anIter->Value() ); + _PTR(SObject) refSO; + if ( !valSO->ReferencedObject( refSO ) ) { + // update tree of object's dimensions + QString anEntry = valSO->GetID().c_str(); + updateBranches( anEntry ); + aDimensionObjEntries.removeAll( anEntry ); + anAnnotationObjEntries.removeAll( anEntry ); + } + anIter->Next(); } - foreach (QString entry, objEntries) { - removeBranch( entry, true ); + foreach ( QString entry, aDimensionObjEntries ) { + removeBranch( DimensionShape, entry, true ); + } + foreach ( QString entry, anAnnotationObjEntries ) { + removeBranch( AnnotationShape, entry, true ); } } } } - + //================================================================================= -// function : updateBranch -// purpose : +// function : updateBranches +// purpose : Rebuild branches for object of the given entry +//================================================================================= +void GEOMGUI_TextTreeWdg::updateBranches( const QString& theEntry ) +{ + updateDimensionBranch( theEntry ); + updateAnnotationBranch( theEntry ); +} + +//================================================================================= +// function : updateDimensionBranch +// purpose : Rebuild branch of dimension type for object of the given entry +//================================================================================= +void GEOMGUI_TextTreeWdg::updateDimensionBranch( const QString& theEntry ) +{ + fillBranch( DimensionShape, theEntry ); +} + +//================================================================================= +// function : updateAnnotationBranch +// purpose : Rebuild branch of annotation type for object of the given entry +//================================================================================= +void GEOMGUI_TextTreeWdg::updateAnnotationBranch( const QString& theEntry ) +{ + fillBranch( AnnotationShape, theEntry ); +} + +//================================================================================= +// function : updateObjectName +// purpose : Find name of the given object and set the name for corresponded tree item //================================================================================= -void GEOMGUI_TextTreeWdg::updateBranch( const QString& theEntry ) +void GEOMGUI_TextTreeWdg::updateObjectName( const QString& theEntry ) { + QTreeWidgetItem* anObjectItem; + + QHash anObjects = getObjects( DimensionShape ); + if ( anObjects.contains( theEntry ) ) + anObjectItem = anObjects.value( theEntry ); + else { + anObjects = getObjects( AnnotationShape ); + if ( anObjects.contains( theEntry ) ) + anObjectItem = anObjects.value( theEntry ); + } + if ( !anObjectItem ) + return; + myStudy = dynamic_cast( SUIT_Session::session()->activeApplication()->activeStudy() ); if ( myStudy ) { + _PTR(Study) aStudyDS = myStudy->studyDS(); + if ( aStudyDS ) { + _PTR(SObject) anObject( aStudyDS->FindObjectID( theEntry.toStdString() ) ); + if ( anObject.get() ) + anObjectItem->setText( 0, anObject->GetName().c_str() ); + } + } +} + +//================================================================================= +// function : fillBranch +// purpose : +//================================================================================= +void GEOMGUI_TextTreeWdg::fillBranch( const BranchType& theBranchType, const QString& theEntry ) +{ + myStudy = dynamic_cast( SUIT_Session::session()->activeApplication()->activeStudy() ); + + if ( myStudy && !theEntry.isEmpty() ) { + QSharedPointer aProp = getVisualProperty( theBranchType, myStudy, theEntry.toStdString() ); + if ( !aProp ) { + return; + } + _PTR(Study) aStudyDS = myStudy->studyDS(); if ( aStudyDS ) { _PTR(SObject) obj( aStudyDS->FindObjectID( theEntry.toStdString() ) ); - QString aName = obj->GetName().c_str(); - - GEOMGUI_DimensionProperty aProp; - aProp.LoadFromAttribute( myStudy, theEntry.toStdString() ); - int nbProps = aProp.GetNumber(); + const QString aName = obj->GetName().c_str(); + const int nbProps = aProp->GetNumber(); - QTreeWidgetItem* objectItem = itemFromEntry( theEntry ); + QTreeWidgetItem* objectItem = itemFromEntry( theBranchType, theEntry ); if ( objectItem ) { - removeBranch( theEntry, nbProps > 0 ? false : true ); + removeBranch( theBranchType, theEntry, nbProps > 0 ? false : true ); } QStringList itemName; if ( nbProps > 0 ) { - itemName << aName << ""; - if ( !objectItem ) { - objectItem = new QTreeWidgetItem( myDimensionsItem, itemName ); - objectItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled ); - objectItem->setData( 1, Qt::UserRole, theEntry ); - myDimensionsItem->addChild( objectItem ); - myObjects.insert( theEntry, objectItem ); - if ( myDimensionsItem->childCount() == 1 ) - myDimensionsItem->setExpanded( true ); - } - bool isDisplayed = myDisplayer.IsDisplayed( theEntry ); - // read dimension records from property - for ( int anIt = 0; anIt < aProp.GetNumber(); ++anIt ) - { - QString aName = aProp.GetName( anIt ); - bool isVisible = aProp.IsVisible( anIt ); - - QTreeWidgetItem* anItem = new QTreeWidgetItem; - anItem->setText( 0, aName ); - // if ( isDisplayed ) - anItem->setIcon( 1, isVisible ? myVisibleIcon : myInvisibleIcon ); - anItem->setData( 0, Qt::UserRole, anIt ); - anItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled ); - objectItem->addChild( anItem ); - } + itemName << aName << ""; + if ( !objectItem ) { + QTreeWidgetItem* aPropRootItem = getPropertyRootItem( theBranchType ); + + objectItem = new QTreeWidgetItem( aPropRootItem, itemName ); + objectItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled ); + objectItem->setData( 1, Qt::UserRole, theEntry ); + aPropRootItem->addChild( objectItem ); + getObjects( theBranchType ).insert( theEntry, objectItem ); + if ( aPropRootItem->childCount() == 1 ) + aPropRootItem->setExpanded( true ); + } + for ( int anIt = 0; anIt < nbProps; ++anIt ) { + const QString aPropName = aProp->GetName( anIt ); + const bool isVisible = aProp->GetIsVisible( anIt ); + QTreeWidgetItem* anItem = new QTreeWidgetItem; + anItem->setText( 0, aPropName ); + anItem->setIcon( 1, isVisible ? myVisibleIcon : myInvisibleIcon ); + anItem->setData( 0, Qt::UserRole, anIt ); + anItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled ); + objectItem->addChild( anItem ); + } } } } } +//================================================================================= +// function : getVisualProperty +// purpose : +//================================================================================= +QSharedPointer + GEOMGUI_TextTreeWdg::getVisualProperty( const BranchType& theBranchType, + SalomeApp_Study* theStudy, + const std::string& theEntry ) +{ + switch ( theBranchType ) + { + case DimensionShape : return QSharedPointer( new DimensionsProperty( theStudy, theEntry ) ); + case AnnotationShape : return QSharedPointer( new AnnotationsProperty( theStudy, theEntry ) ); + default: break; + } + return QSharedPointer(); +} + //================================================================================= // function : removeBranch // purpose : //================================================================================= -void GEOMGUI_TextTreeWdg::removeBranch( const QString& theEntry, bool force ) +void GEOMGUI_TextTreeWdg::removeBranch( const BranchType& theBranchType, const QString& theEntry, + bool force ) { - QTreeWidgetItem* objectItem = itemFromEntry( theEntry ); + QTreeWidgetItem* objectItem = itemFromEntry( theBranchType, theEntry ); if ( !objectItem ) return; qDeleteAll( objectItem->takeChildren() ); if ( force ) { - myDimensionsItem->removeChild( objectItem ); - myObjects.remove( theEntry ); + QTreeWidgetItem* aPropRootItem = getPropertyRootItem( theBranchType ); + aPropRootItem->removeChild( objectItem ); + getObjects( theBranchType ).remove( theEntry ); } } @@ -236,17 +442,22 @@ void GEOMGUI_TextTreeWdg::onItemClicked( QTreeWidgetItem* theItem, int theColumn return; std::string anEntry = entryFromItem( theItem->parent() ).toStdString(); + BranchType aBranchType = branchTypeFromItem( theItem ); + int aDimIndex = idFromItem( theItem ); - GEOMGUI_DimensionProperty aProp; - aProp.LoadFromAttribute( myStudy, anEntry ); - if ( aProp.IsVisible( aDimIndex ) ) { - aProp.SetVisible( aDimIndex, false ); + + QSharedPointer aProp = getVisualProperty( aBranchType, myStudy, anEntry ); + + CAM_Application* anApp = dynamic_cast(myStudy->application()); + GeometryGUI* aModule = dynamic_cast(anApp->activeModule()); + if ( aProp->GetIsVisible( aDimIndex ) ) { + aModule->GetAnnotationMgr()->Erase(anEntry.c_str(), aDimIndex); theItem->setIcon( 1, myInvisibleIcon ); } else { - aProp.SetVisible( aDimIndex, true ); + aModule->GetAnnotationMgr()->Display(anEntry.c_str(), aDimIndex); + theItem->setIcon( 1, myVisibleIcon ); } - aProp.SaveToAttribute( myStudy, anEntry ); redisplay( anEntry.c_str() ); } @@ -269,7 +480,7 @@ int GEOMGUI_TextTreeWdg::idFromItem( QTreeWidgetItem* theItem ) // function : entryFromItem // purpose : //================================================================================= -QString GEOMGUI_TextTreeWdg::entryFromItem( QTreeWidgetItem* theShapeItem ) +QString GEOMGUI_TextTreeWdg::entryFromItem( QTreeWidgetItem* theShapeItem ) const { if ( !theShapeItem ) return ""; @@ -281,33 +492,49 @@ QString GEOMGUI_TextTreeWdg::entryFromItem( QTreeWidgetItem* theShapeItem ) // function : itemFromEntry // purpose : //================================================================================= -QTreeWidgetItem* GEOMGUI_TextTreeWdg::itemFromEntry( QString theEntry ) +QTreeWidgetItem* GEOMGUI_TextTreeWdg::itemFromEntry( const BranchType& theBranchType, QString theEntry ) { if ( theEntry.isEmpty() ) return 0; - return myObjects.value( theEntry, 0 ); + return getObjects(theBranchType).value( theEntry, 0 ); +} + +//================================================================================= +// function : onUpdateVisibilityColumn +// purpose : Update visible state of icons of entry items. +//================================================================================= +void GEOMGUI_TextTreeWdg::onUpdateVisibilityColumn( QString theEntry, Qtx::VisibilityState theState ) +{ + // dimension property branch + updateVisibilityColumn( DimensionShape, theEntry, theState ); + + // annotation property branch + updateVisibilityColumn( AnnotationShape, theEntry, theState ); } //================================================================================= // function : updateVisibilityColumn // purpose : Update icons of dimension items. //================================================================================= -void GEOMGUI_TextTreeWdg::updateVisibilityColumn( QString theEntry, Qtx::VisibilityState theState ) +void GEOMGUI_TextTreeWdg::updateVisibilityColumn( const BranchType& theBranchType, QString theEntry, + Qtx::VisibilityState theState ) { - QTreeWidgetItem* anItem = itemFromEntry( theEntry ); + QTreeWidgetItem* anItem = itemFromEntry( theBranchType, theEntry ); if ( !anItem ) return; anItem->setDisabled( theState != Qtx::ShownState ); QTreeWidgetItem* aChildItem; - GEOMGUI_DimensionProperty aProp; + + QSharedPointer aProp = getVisualProperty( theBranchType, myStudy, theEntry.toStdString() ); + for ( int i=0; i < anItem->childCount(); i++ ) { aChildItem = anItem->child( i ); if ( theState == Qtx::ShownState ) { - aProp.LoadFromAttribute( myStudy, theEntry.toStdString() ); - if ( aProp.GetNumber() == 0 ) - continue; - aChildItem->setIcon( 1, aProp.IsVisible( idFromItem( aChildItem ) ) ? myVisibleIcon : myInvisibleIcon ); + if ( aProp->GetNumber() == 0 ) + continue; + aChildItem->setIcon( 1, aProp->GetIsVisible( idFromItem( aChildItem ) ) ? myVisibleIcon + : myInvisibleIcon ); aChildItem->setDisabled( false ); } else { aChildItem->setIcon( 1, QIcon() ); @@ -322,95 +549,278 @@ void GEOMGUI_TextTreeWdg::updateVisibilityColumn( QString theEntry, Qtx::Visibil //================================================================================= void GEOMGUI_TextTreeWdg::showContextMenu( const QPoint& pos ) { - if ( selectedItems().isEmpty() ) - return; + CAM_Application* anApp = dynamic_cast(myStudy->application()); + GeometryGUI* aModule = dynamic_cast(anApp->activeModule()); + QMenu aMenu; - aMenu.addAction( myActions[GEOMOp::OpShow] ); - aMenu.addAction( myActions[GEOMOp::OpHide] ); - if ( selectedItems().count() == 1 ) { + if ( !selectedItems().isEmpty() && selectedItems().count() == 1 ) { QTreeWidgetItem* anItem = selectedItems().first(); QString anEntry = entryFromItem( anItem->parent() ); if ( !anEntry.isEmpty() ) { - GEOMGUI_DimensionProperty aProp; - aProp.LoadFromAttribute( myStudy, anEntry.toStdString() ); - if ( aProp.GetNumber() == 0 ) - return; - aMenu.clear(); - if ( aProp.IsVisible( idFromItem( anItem ) ) ) - aMenu.addAction( myActions[GEOMOp::OpHide] ); + BranchType aBranchType = branchTypeFromItem( anItem ); + QSharedPointer + aProp = getVisualProperty( aBranchType, myStudy, anEntry.toStdString() ); + + if ( aProp->GetNumber() == 0 ) + return; + // Edit annotation action + QAction* anEditAction = aModule->action(GEOMOp::OpEditAnnotation); + if ( anEditAction ) + aMenu.addAction( anEditAction ); + QAction* aDeleteAction = aModule->action(GEOMOp::OpDeleteAnnotation); + if ( aDeleteAction ) + aMenu.addAction( aDeleteAction ); + // Show/Hide actions + if ( aProp->GetIsVisible( idFromItem( anItem ) ) ) + aMenu.addAction( myActions[GEOMOp::OpHide] ); else - aMenu.addAction( myActions[GEOMOp::OpShow] ); + aMenu.addAction( myActions[GEOMOp::OpShow] ); + } + } + + if (selectedItems().isEmpty() && currentItem()) { + QTreeWidgetItem* anItem = currentItem(); + bool aShowAll = false; + if (anItem == getPropertyRootItem(AnnotationShape)) + aShowAll = true; + else { + QHash anObjects = getObjects( AnnotationShape ); + QHash::const_iterator anIt = anObjects.begin(), + aLast = anObjects.end(); + for (; anIt != aLast && !aShowAll; anIt++) { + aShowAll = anIt.value() == anItem; + } + } + if (aShowAll) { + aMenu.addAction( aModule->action(GEOMOp::OpShowAllAnnotations) ); + aMenu.addAction( aModule->action(GEOMOp::OpHideAllAnnotations) ); } } QAction* selPopupItem = aMenu.exec( viewport()->mapToGlobal(pos) ); - if ( selPopupItem == myActions[GEOMOp::OpShow] ) - setVisibility( true ); - else if ( selPopupItem == myActions[GEOMOp::OpHide] ) - setVisibility( false ); + + if ( selPopupItem == myActions[GEOMOp::OpShow] || + selPopupItem == myActions[GEOMOp::OpHide] ) { + bool isVisible = selPopupItem == myActions[GEOMOp::OpShow]; + foreach ( QTreeWidgetItem* anItem, selectedItems() ) { + setVisibility( anItem, isVisible ); + } + } } //================================================================================= // function : setVisibility -// purpose : +// purpose : set item visible //================================================================================= -void GEOMGUI_TextTreeWdg::setVisibility( bool theVisibility ) +void GEOMGUI_TextTreeWdg::setVisibility( QTreeWidgetItem* theItem, bool theVisibility ) { - if ( myDimensionsItem->isSelected() ) { - // set visibility for all dimensions + BranchType aBranchType = branchTypeFromItem( theItem ); + if ( theItem == myDimensionsItem || + theItem == myAnnotationsItem ) { + QTreeWidgetItem* anItem; - foreach ( QString entry, myObjects.keys() ) { - anItem = itemFromEntry( entry ); + foreach ( QString entry, getObjects( aBranchType ).keys() ) { + anItem = itemFromEntry( aBranchType, entry ); if ( !anItem->isDisabled() ) - setShapeDimensionsVisibility( entry, theVisibility ); + setAllShapeItemsVisibility( aBranchType, entry, theVisibility ); } return; } - foreach ( QTreeWidgetItem* item, selectedItems() ) { - if ( item->isDisabled() || item->parent()->isSelected() ) - continue; - QString anEntry = entryFromItem( item ); - if ( !anEntry.isEmpty() ) { - // it is a shape item - setShapeDimensionsVisibility( anEntry, theVisibility ); - } else { - // it is a dimension item - anEntry = entryFromItem( item->parent() ); - setDimensionVisibility( anEntry, item, theVisibility ); + else { + if ( !theItem->isDisabled() && !theItem->parent()->isSelected() ) { + QString anEntry = entryFromItem( theItem ); + if ( !anEntry.isEmpty() ) { + // it is a shape item + setAllShapeItemsVisibility( aBranchType, anEntry, theVisibility ); + } else { + // it is a dimension item + anEntry = entryFromItem( theItem->parent() ); + setShapeItemVisibility( aBranchType, anEntry, theItem, theVisibility ); + } } } } //================================================================================= -// function : setShapeDimensionsVisibility +// function : setAllShapeItemsVisibility // purpose : //================================================================================= -void GEOMGUI_TextTreeWdg::setShapeDimensionsVisibility( QString theEntry, bool theVisibility ) +void GEOMGUI_TextTreeWdg::setAllShapeItemsVisibility( const BranchType& theBranchType, + const QString& theEntry, + const bool theVisibility ) { - QTreeWidgetItem* anItem = itemFromEntry( theEntry ); + QSharedPointer + aProp = getVisualProperty( theBranchType, myStudy, theEntry.toStdString() ); + + QTreeWidgetItem* anItem = itemFromEntry( theBranchType, theEntry ); QTreeWidgetItem* aChildItem; for ( int i=0; i < anItem->childCount(); i++ ) { aChildItem = anItem->child( i ); - setDimensionVisibility( theEntry, aChildItem, theVisibility ); + setShapeItemVisibility( aProp, aChildItem, theVisibility ); } + + aProp->Save(); + redisplay( theEntry ); } //================================================================================= -// function : setDimensionVisibility +// function : setShapeItemVisibility // purpose : //================================================================================= -void GEOMGUI_TextTreeWdg::setDimensionVisibility( QString theEntry, QTreeWidgetItem* theDimItem, bool theVisibility ) +void GEOMGUI_TextTreeWdg::setShapeItemVisibility( const BranchType& theBranchType, + const QString& theEntry, + QTreeWidgetItem* theWidgetItem, + const bool theVisibility ) { - GEOMGUI_DimensionProperty aProp; - aProp.LoadFromAttribute( myStudy, theEntry.toStdString() ); - int aDimIndex = idFromItem( theDimItem ); - if ( aProp.GetNumber() == 0 || aProp.IsVisible( aDimIndex ) == theVisibility ) - return;; - aProp.SetVisible( aDimIndex, theVisibility ); - aProp.SaveToAttribute( myStudy, theEntry.toStdString() ); + QSharedPointer + aProp = getVisualProperty( theBranchType, myStudy, theEntry.toStdString() ); - theDimItem->setIcon( 1, theVisibility ? myVisibleIcon : myInvisibleIcon ); - redisplay( theEntry ); + if ( setShapeItemVisibility( aProp, theWidgetItem, theVisibility ) ) { + aProp->Save(); + redisplay( theEntry ); + } +} + +//================================================================================= +// function : setShapeItemVisibility +// purpose : +//================================================================================= +void GEOMGUI_TextTreeWdg::updateVisibility() +{ + //QList aDimensionObjEntries = getObjects( DimensionShape ).keys(); + BranchType aBranchType = AnnotationShape; + + QList anAnnotationObjEntries = getObjects( aBranchType ).keys(); + + QTreeWidgetItem* anEntryItem; + foreach ( QString anEntry, getObjects( aBranchType ).keys() ) + { + anEntryItem = itemFromEntry( aBranchType, anEntry ); + + QTreeWidgetItem* anItem; + for ( int i = 0; i < anEntryItem->childCount(); i++ ) { + anItem = anEntryItem->child( i ); + int aDimIndex = idFromItem( anItem ); + QSharedPointer aProp = getVisualProperty( aBranchType, myStudy, + anEntry.toStdString() ); + bool isItemVisible = aProp->GetIsVisible( aDimIndex ); + anItem->setIcon( 1, isItemVisible ? myVisibleIcon : myInvisibleIcon ); + } + + redisplay( anEntry ); + } +} + +//================================================================================= +// function : getSelected +// purpose : +//================================================================================= +void GEOMGUI_TextTreeWdg::getSelected( QMap >& theAnnotations ) +{ + theAnnotations.clear(); + + QItemSelectionModel* aSelectionModel = selectionModel(); + QModelIndexList aSelectedIndices = aSelectionModel->selectedIndexes(); + + for (int i = 0, aNbItems = aSelectedIndices.size(); i < aNbItems; i++) { + QTreeWidgetItem* anItem = itemFromIndex( aSelectedIndices[i] ); + if ( !anItem ) + continue; + QString anEntry = entryFromItem( anItem->parent() ); + int aDimIndex = idFromItem( anItem ); + if ( aDimIndex < 0 ) + continue; + + if ( theAnnotations.contains( anEntry ) ) + theAnnotations[anEntry].append( aDimIndex ); + else { + QList anIndices; + anIndices.append( aDimIndex ); + theAnnotations[anEntry] = anIndices; + } + } +} + +//================================================================================= +// function : setSelected +// purpose : +//================================================================================= +void GEOMGUI_TextTreeWdg::setSelected( const QMap >& theAnnotations ) +{ + QItemSelectionModel* aSelectionModel = selectionModel(); + aSelectionModel->clearSelection(); + + QMap >::const_iterator anIt = theAnnotations.begin(), + aLast = theAnnotations.end(); + BranchType aBranchType = AnnotationShape; + for ( ; anIt != aLast; anIt++ ) { + QString anEntry = anIt.key(); + QTreeWidgetItem* anEntryItem = itemFromEntry( aBranchType, anEntry ); + if ( !anEntryItem ) + continue; + + QList anAnnotationIds = anIt.value(); + QTreeWidgetItem* anItem; + for ( int i = 0; i < anEntryItem->childCount(); i++ ) { + anItem = anEntryItem->child( i ); + int aDimIndex = idFromItem( anItem ); + if ( anAnnotationIds.contains( aDimIndex ) ) { + QModelIndex anIndex = indexFromItem( anItem ); + aSelectionModel->select( anIndex, QItemSelectionModel::Select ); + } + } + } +} + +//================================================================================= +// function : getAllEntries +// purpose : +//================================================================================= +QList GEOMGUI_TextTreeWdg::getAllEntries( const BranchType& theBranchType ) +{ + return getObjects( theBranchType ).keys(); +} + +//================================================================================= +// function : getSingleSelectedObject +// purpose : +//================================================================================= +QString GEOMGUI_TextTreeWdg::getSingleSelectedObject() +{ + QString anEntry; + QTreeWidgetItem* anItem = currentItem(); + if (anItem) { + QHash anObjects = getObjects( AnnotationShape ); + QHash::const_iterator anIt = anObjects.begin(), + aLast = anObjects.end(); + for (; anIt != aLast; anIt++) { + if ( anIt.value() == anItem ) { + anEntry = anIt.key(); + break; + } + } + } + return anEntry; +} + +//================================================================================= +// function : setShapeItemVisibility +// purpose : +//================================================================================= +bool GEOMGUI_TextTreeWdg::setShapeItemVisibility( QSharedPointer& theProps, + QTreeWidgetItem* theWidgetItem, + const bool theVisibility ) +{ + int aDimIndex = idFromItem( theWidgetItem ); + if ( theProps->GetNumber() == 0 + || theProps->GetIsVisible( aDimIndex ) == theVisibility ) { + return false; + } + theProps->SetIsVisible( aDimIndex, theVisibility ); + + theWidgetItem->setIcon( 1, theVisibility ? myVisibleIcon : myInvisibleIcon ); + + return true; } //================================================================================= @@ -422,3 +832,45 @@ void GEOMGUI_TextTreeWdg::redisplay( QString theEntry ) Handle(SALOME_InteractiveObject) io = new SALOME_InteractiveObject( theEntry.toLatin1().constData(), "GEOM", "TEMP_IO" ); myDisplayer.Redisplay( io ); } + +//================================================================================= +// function : getPropertyRootItem +// purpose : +//================================================================================= +QTreeWidgetItem* GEOMGUI_TextTreeWdg::getPropertyRootItem( const BranchType& theBranchType ) +{ + return (theBranchType == DimensionShape) ? myDimensionsItem : myAnnotationsItem; +} + +//================================================================================= +// function : getObjects +// purpose : +//================================================================================= +QHash& GEOMGUI_TextTreeWdg::getObjects( const BranchType& theBranchType ) +{ + return (theBranchType == DimensionShape) ? myDimensionObjects : myAnnotationObjects; +} + +//================================================================================= +// function : branchTypeFromItem +// purpose : +//================================================================================= +GEOMGUI_TextTreeWdg::BranchType GEOMGUI_TextTreeWdg::branchTypeFromItem( QTreeWidgetItem* theItem ) +{ + BranchType aBranchType = DimensionShape; + + bool aBranchTypeFound = false; + QTreeWidgetItem* anItem = theItem; + while( !aBranchTypeFound && anItem ) { + if ( anItem == myDimensionsItem || + anItem == myAnnotationsItem) { + aBranchTypeFound = true; + aBranchType = (anItem == myDimensionsItem) ? DimensionShape : AnnotationShape; + } + else { + anItem = anItem->parent(); + } + } + + return aBranchType; +} diff --git a/src/GEOMGUI/GEOMGUI_TextTreeWdg.h b/src/GEOMGUI/GEOMGUI_TextTreeWdg.h index 4f6677c88..abce0083f 100644 --- a/src/GEOMGUI/GEOMGUI_TextTreeWdg.h +++ b/src/GEOMGUI/GEOMGUI_TextTreeWdg.h @@ -23,8 +23,11 @@ #include "GEOM_GEOMGUI.hxx" #include "GEOM_Displayer.h" -#include #include +#include +#include +#include +#include #include @@ -44,46 +47,97 @@ class GEOMGUI_EXPORT GEOMGUI_TextTreeWdg : public QTreeWidget { Q_OBJECT - public: +public: + enum BranchType { DimensionShape, AnnotationShape }; + +public: GEOMGUI_TextTreeWdg( SalomeApp_Application* app ); ~GEOMGUI_TextTreeWdg(); int getWinID() { return myWindowID; } - void removeBranch( const QString& theEntry, - bool force = true ); + void removeBranch( const BranchType& theBranchType, const QString& theEntry, + bool force = true ); int idFromItem( QTreeWidgetItem* theItem ); - QString entryFromItem( QTreeWidgetItem* theShapeItem ); - QTreeWidgetItem* itemFromEntry( QString theEntry ); - void setShapeDimensionsVisibility( QString theEntry, bool theVisibility ); - void setDimensionVisibility( QString theEntry, QTreeWidgetItem* theDimItem, bool theVisibility ); + QString entryFromItem( QTreeWidgetItem* theShapeItem ) const; + QTreeWidgetItem* itemFromEntry( const BranchType& theBranchType, QString theEntry ); + void setAllShapeItemsVisibility( const BranchType& theBranchType, + const QString& theEntry, + const bool theVisibility ); + void setShapeItemVisibility( const BranchType& theBranchType, + const QString& theEntry, + QTreeWidgetItem* theWidgetItem, + const bool theVisibility ); + void updateVisibility(); + + void getSelected( QMap >& theAnnotations ); + void setSelected( const QMap >& theAnnotations ); + + QList getAllEntries( const BranchType& theBranchType ); + + QString getSingleSelectedObject(); protected: void createActions(); void redisplay( QString theEntry ); - public slots: +public slots: void updateTree(); - void updateBranch( const QString& theEntry ); + void updateBranches( const QString& theEntry ); + void updateDimensionBranch( const QString& theEntry ); + void updateAnnotationBranch( const QString& theEntry ); + void updateObjectName( const QString& theEntry ); private slots: + void onUpdateVisibilityColumn( QString theEntry, Qtx::VisibilityState theState ); void onItemClicked(QTreeWidgetItem*, int ); - void updateVisibilityColumn( QString theEntry, Qtx::VisibilityState theState ); - void setVisibility( bool visibility ); + void setVisibility( QTreeWidgetItem* theItem, bool visibility ); void showContextMenu( const QPoint& pos ); - private: - - int myWindowID; - - QIcon myVisibleIcon; - QIcon myInvisibleIcon; - QHash myObjects; - SalomeApp_Study* myStudy; - QTreeWidgetItem* myDimensionsItem; - GEOM_Displayer myDisplayer; - - QMap myActions; //!< menu actions list - +public: + + /*! + * \brief Common interface for working with shape dimension and annotation properties + * of object in a unified way irrespectively of the implementation. + */ + class VisualProperty + { + public: + virtual int GetNumber() = 0; + virtual QString GetName( const int theIndex ) = 0; + virtual bool GetIsVisible( const int theIndex ) = 0; + virtual void SetIsVisible( const int theIndex, const bool theIsVisible ) = 0; + virtual void Save() = 0; + }; + +private: + bool setShapeItemVisibility( QSharedPointer& theProps, + QTreeWidgetItem* theWidgetItem, + const bool theVisibility ); + QSharedPointer getVisualProperty( const BranchType& theBranchType, + SalomeApp_Study* theStudy, + const std::string& theEntry ); + void fillBranch( const BranchType& theBranchType, + const QString& theEntry ); + void updateVisibilityColumn( const BranchType& theBranchType, + QString theEntry, + Qtx::VisibilityState theState ); + QTreeWidgetItem* getPropertyRootItem( const BranchType& theBranchType ); + QHash& getObjects( const BranchType& theBranchType ); + BranchType branchTypeFromItem( QTreeWidgetItem* theItem ); + +private: + + int myWindowID; + QIcon myVisibleIcon; + QIcon myInvisibleIcon; + QHash myDimensionObjects; + QHash myAnnotationObjects; + SalomeApp_Study* myStudy; + QTreeWidgetItem* myDimensionsItem; + QTreeWidgetItem* myAnnotationsItem; + GEOM_Displayer myDisplayer; + QMap myActions; //!< menu actions list }; + #endif diff --git a/src/GEOMGUI/GEOM_Displayer.cxx b/src/GEOMGUI/GEOM_Displayer.cxx old mode 100644 new mode 100755 index 3ed44e128..137895022 --- a/src/GEOMGUI/GEOM_Displayer.cxx +++ b/src/GEOMGUI/GEOM_Displayer.cxx @@ -25,7 +25,6 @@ // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) #include "GEOM_Displayer.h" -#include "GEOMGUI_DimensionProperty.h" #include "GeometryGUI.h" #include @@ -39,12 +38,17 @@ #include #include +#include #include #include #include #include #include +#include +#include +#include + #include #include @@ -460,6 +464,7 @@ static std::string getName( GEOM::GEOM_BaseObject_ptr object ) */ //================================================================= GEOM_Displayer::GEOM_Displayer( SalomeApp_Study* st ) +: myIsRedisplayed( false ) { if( st ) myApp = dynamic_cast( st->application() ); @@ -510,7 +515,8 @@ GEOM_Displayer::GEOM_Displayer( SalomeApp_Study* st ) #if OCC_VERSION_MAJOR >= 7 myColorScale = new AIS_ColorScale; myColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD); - myColorScale->SetTransformPersistence (Graphic3d_TMF_2d, gp_Pnt (-1,-1,0)); + myColorScale->SetTransformPersistence ( + Graphic3d_TransformPers::FromDeprecatedParams(Graphic3d_TMF_2d, gp_Pnt (-1,-1,0))); #endif myFieldDataType = GEOM::FDT_Double; @@ -636,6 +642,8 @@ void GEOM_Displayer::Redisplay( const Handle(SALOME_InteractiveObject)& theIO, const bool updateViewer, const bool checkActiveViewer ) { + bool aRedisplayed = myIsRedisplayed; + myIsRedisplayed = true; // Remove the object permanently ( == true) SUIT_Session* ses = SUIT_Session::session(); SUIT_Application* app = ses->activeApplication(); @@ -665,6 +673,7 @@ void GEOM_Displayer::Redisplay( const Handle(SALOME_InteractiveObject)& theIO, } } } + myIsRedisplayed = aRedisplayed; } //================================================================= @@ -684,8 +693,23 @@ void GEOM_Displayer::Redisplay( const Handle(SALOME_InteractiveObject)& theIO, return; } + bool aRedisplayed = myIsRedisplayed; + myIsRedisplayed = true; Erase( theIO, true, false, theViewFrame ); Display( theIO, theUpdateViewer, theViewFrame ); + myIsRedisplayed = aRedisplayed; + // hide annotations for erased presentation + SUIT_Session* session = SUIT_Session::session(); + SalomeApp_Application* anApp = dynamic_cast( session->activeApplication() ); + GeometryGUI* aModule = dynamic_cast( anApp->activeModule() ); + if ( aModule ) { + if ( !theViewFrame->isVisible( theIO ) ) { + aModule->GetAnnotationMgr()->EraseVisibleAnnotations(QString(theIO->getEntry()), dynamic_cast( theViewFrame )); + } + else { + aModule->GetAnnotationMgr()->DisplayVisibleAnnotations(QString(theIO->getEntry()), dynamic_cast( theViewFrame )); + } + } } //================================================================= @@ -2052,6 +2076,18 @@ void GEOM_Displayer::BeforeDisplay( SALOME_View* v, const SALOME_OCCPrs* ) void GEOM_Displayer::AfterDisplay( SALOME_View* v, const SALOME_OCCPrs* p ) { UpdateColorScale(false,false); + + // visualize annotations for displayed presentation + SUIT_Session* session = SUIT_Session::session(); + SalomeApp_Application* anApp = dynamic_cast( session->activeApplication() ); + GeometryGUI* aModule = dynamic_cast( anApp->activeModule() ); + if ( aModule ) { + if ( !myIsRedisplayed ) { + aModule->GetAnnotationMgr()->DisplayVisibleAnnotations(QString(p->GetEntry()), dynamic_cast( v )); + } else { + aModule->GetAnnotationMgr()->UpdateVisibleAnnotations(QString(p->GetEntry()), dynamic_cast( v )); + } + } } void GEOM_Displayer::BeforeErase( SALOME_View* v, const SALOME_OCCPrs* p ) @@ -2064,6 +2100,15 @@ void GEOM_Displayer::AfterErase( SALOME_View* v, const SALOME_OCCPrs* p ) { LightApp_Displayer::AfterErase( v, p ); UpdateColorScale(false,false); + + if ( !myIsRedisplayed ) { + // hide annotations for erased presentation + SUIT_Session* session = SUIT_Session::session(); + SalomeApp_Application* anApp = dynamic_cast( session->activeApplication() ); + GeometryGUI* aModule = dynamic_cast( anApp->activeModule() ); + if ( aModule ) + aModule->GetAnnotationMgr()->EraseVisibleAnnotations(QString(p->GetEntry()), dynamic_cast( v )); + } } //================================================================= diff --git a/src/GEOMGUI/GEOM_Displayer.h b/src/GEOMGUI/GEOM_Displayer.h old mode 100644 new mode 100755 index cf5a9df55..390466f58 --- a/src/GEOMGUI/GEOM_Displayer.h +++ b/src/GEOMGUI/GEOM_Displayer.h @@ -263,6 +263,7 @@ protected: void updateShapeProperties( const Handle(GEOM_AISShape)&, bool ); void updateActorProperties( GEOM_Actor*, bool ); void updateDimensions( const Handle(SALOME_InteractiveObject)&, SALOME_OCCPrs*, const gp_Ax3& ); + void updateShapeAnnotations( const Handle(SALOME_InteractiveObject)&, SALOME_OCCPrs*, const gp_Ax3& ); PropMap getObjectProperties( SalomeApp_Study*, const QString&, SALOME_View* = 0 ); PropMap getDefaultPropertyMap(); @@ -317,6 +318,7 @@ protected: Aspect_TypeOfMarker myTypeOfMarker; double myScaleOfMarker; double myTransparency; + bool myIsRedisplayed; private: SalomeApp_Application* myApp; diff --git a/src/GEOMGUI/GEOM_images.ts b/src/GEOMGUI/GEOM_images.ts index aeaedb609..4b1c19571 100644 --- a/src/GEOMGUI/GEOM_images.ts +++ b/src/GEOMGUI/GEOM_images.ts @@ -1215,6 +1215,10 @@ ICO_MANAGE_DIMENSIONS managedimensions.png + + ICO_ANNOTATION + annotation.png + ICO_POINT point2.png diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts old mode 100644 new mode 100755 index 7591ab083..22fc71ae4 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -575,6 +575,10 @@ Please, select face, shell or solid and try again GEOM_DIMENSIONS Dimensions + + GEOM_ANNOTATIONS + Annotations + GEOM_SKETCHER_DIST Distance @@ -3500,6 +3504,50 @@ Please, select face, shell or solid and try again PREF_DIMENSIONS_USE_TEXT3D Use 3D text + + PREF_SHAPE_ANNOTATIONS + Shape annotations + + + PREF_SHAPE_ANNOTATIONS_FONT + Font + + + PREF_SHAPE_ANNOTATIONS_FONT_COLOR + Font color + + + PREF_SHAPE_ANNOTATIONS_LINE_COLOR + Line color + + + PREF_SHAPE_ANNOTATIONS_LINE_WIDTH + Line width + + + PREF_SHAPE_ANNOTATIONS_LINE_STYLE + Line style + + + PREF_SHAPE_ANNOTATIONS_AUTOHIDE + Hide when attachment is invisible + + + PREF_SHAPE_ANNOTATIONS_LINESTYLE_SOLID + Solid + + + PREF_SHAPE_ANNOTATIONS_LINESTYLE_DASH + Dashed + + + PREF_SHAPE_ANNOTATIONS_LINESTYLE_DOT + Dotted + + + PREF_SHAPE_ANNOTATIONS_LINESTYLE_DOTDASH + Mixed + PREF_HIDE_INPUT_OBJECT Hide input objects from the viewer @@ -4956,6 +5004,42 @@ Please, select face, shell or solid and try again STB_MANAGE_DIMENSIONS Manage measurement dimensions of an object + + TOP_ANNOTATION + Annotation + + + MEN_ANNOTATION + Annotation + + + STB_ANNOTATION + Annotation + + + TOP_EDIT_ANNOTATION + Edit Annotation + + + MEN_EDIT_ANNOTATION + Edit + + + STB_EDIT_ANNOTATION + Edit Annotation + + + TOP_DELETE_ANNOTATION + Delete Annotation + + + MEN_DELETE_ANNOTATION + Delete + + + STB_DELETE_ANNOTATION + Delete Annotation + MEN_POP_SHOW_DEPENDENCY_TREE Show dependency tree @@ -4996,6 +5080,30 @@ Please, select face, shell or solid and try again TOP_POP_HIDE_ALL_DIMENSIONS Show all visible measures (dimension) created for the object + + MEN_POP_SHOW_ALL_ANNOTATIONS + Show all annotations + + + STB_POP_SHOW_ALL_ANNOTATIONS + Show all shape annotations for the object + + + TOP_POP_SHOW_ALL_ANNOTATIONS + Show all shape annotations for the object + + + MEN_POP_HIDE_ALL_ANNOTATIONS + Hide all annotations + + + STB_POP_HIDE_ALL_ANNOTATIONS + Hide all shape annotations for the object + + + TOP_POP_HIDE_ALL_ANNOTATIONS + Hide all shape annotations for the object + TOP_POP_AUTO_COLOR Auto color @@ -6675,6 +6783,61 @@ Do you want to continue? Please specify suitable arguments. + + MeasureGUI_AnnotationDlg + + CREATE_ANNOTATION_TITLE + Create annotation + + + EDIT_ANNOTATION_TITLE + Edit annotation + + + ANNOTATION_PREFIX + Annotation + + + ANNOTATION_NAME + Annotation name + + + ANNOTATION_PROPERTIES + Properties + + + ANNOTATION_TEXT + Text + + + ANNOTATION_SHAPE + Shape + + + ANNOTATION_TYPE + Type + + + ANNOTATION_SUB_SHAPE + Sub-shape type + + + ANNOTATION_IS_SCREEN_FIXED + Fixed screen position + + + WHOLE_SHAPE + Whole shape + + + ANNOTATION_STYLE + Style + + + ANNOTATION_FONT + Font + + MeasureGUI_CheckShapeDlg diff --git a/src/GEOMGUI/GEOM_msg_fr.ts b/src/GEOMGUI/GEOM_msg_fr.ts old mode 100644 new mode 100755 index 8c16f25af..75e6aab0c --- a/src/GEOMGUI/GEOM_msg_fr.ts +++ b/src/GEOMGUI/GEOM_msg_fr.ts @@ -3492,6 +3492,50 @@ Choisissez une face, une coque ou un solide et essayez de nouveau PREF_DIMENSIONS_USE_TEXT3D Utiliser du texte 3D + + PREF_SHAPE_ANNOTATIONS + Shape annotations + + + PREF_SHAPE_ANNOTATIONS_FONT + Font + + + PREF_SHAPE_ANNOTATIONS_FONT_COLOR + Font color + + + PREF_SHAPE_ANNOTATIONS_LINE_COLOR + Line color + + + PREF_SHAPE_ANNOTATIONS_LINE_WIDTH + Line width + + + PREF_SHAPE_ANNOTATIONS_LINE_STYLE + Line style + + + PREF_SHAPE_ANNOTATIONS_AUTOHIDE + Hide when attachment is invisible + + + PREF_SHAPE_ANNOTATIONS_LINESTYLE_SOLID + Solid + + + PREF_SHAPE_ANNOTATIONS_LINESTYLE_DASH + Dashed + + + PREF_SHAPE_ANNOTATIONS_LINESTYLE_DOT + Dotted + + + PREF_SHAPE_ANNOTATIONS_LINESTYLE_DOTDASH + Mixed + PREF_HIDE_INPUT_OBJECT Cacher dans la vue les objets en entrée @@ -4988,6 +5032,30 @@ Choisissez une face, une coque ou un solide et essayez de nouveau TOP_POP_HIDE_ALL_DIMENSIONS Afficher toutes les cotations visibles créées sur l'objet + + MEN_POP_SHOW_ALL_ANNOTATIONS + Show all annotations + + + STB_POP_SHOW_ALL_ANNOTATIONS + Show all shape annotations for the object + + + TOP_POP_SHOW_ALL_ANNOTATIONS + Show all shape annotations for the object + + + MEN_POP_HIDE_ALL_ANNOTATIONS + Hide all annotations + + + STB_POP_HIDE_ALL_ANNOTATIONS + Hide all shape annotations for the object + + + TOP_POP_HIDE_ALL_ANNOTATIONS + Hide all shape annotations for the object + TOP_POP_AUTO_COLOR Couleur automatique diff --git a/src/GEOMGUI/GEOM_msg_ja.ts b/src/GEOMGUI/GEOM_msg_ja.ts old mode 100644 new mode 100755 index c0c9cdd24..3ed5307c8 --- a/src/GEOMGUI/GEOM_msg_ja.ts +++ b/src/GEOMGUI/GEOM_msg_ja.ts @@ -3495,6 +3495,50 @@ PREF_DIMENSIONS_USE_TEXT3D 3Dテキストの使用 + + PREF_SHAPE_ANNOTATIONS + Shape annotations + + + PREF_SHAPE_ANNOTATIONS_FONT + Font + + + PREF_SHAPE_ANNOTATIONS_FONT_COLOR + Font color + + + PREF_SHAPE_ANNOTATIONS_LINE_COLOR + Line color + + + PREF_SHAPE_ANNOTATIONS_LINE_WIDTH + Line width + + + PREF_SHAPE_ANNOTATIONS_LINE_STYLE + Line style + + + PREF_SHAPE_ANNOTATIONS_AUTOHIDE + Hide when attachment is invisible + + + PREF_SHAPE_ANNOTATIONS_LINESTYLE_SOLID + Solid + + + PREF_SHAPE_ANNOTATIONS_LINESTYLE_DASH + Dashed + + + PREF_SHAPE_ANNOTATIONS_LINESTYLE_DOT + Dotted + + + PREF_SHAPE_ANNOTATIONS_LINESTYLE_DOTDASH + Mixed + PREF_HIDE_INPUT_OBJECT ビューワから入力したオブジェクトの非表示 @@ -4991,6 +5035,30 @@ TOP_POP_HIDE_ALL_DIMENSIONS オブジェクトのために作成されたすべての見える基準寸法を表示 + + MEN_POP_SHOW_ALL_ANNOTATIONS + Show all annotations + + + STB_POP_SHOW_ALL_ANNOTATIONS + Show all shape annotations for the object + + + TOP_POP_SHOW_ALL_ANNOTATIONS + Show all shape annotations for the object + + + MEN_POP_HIDE_ALL_ANNOTATIONS + Hide all annotations + + + STB_POP_HIDE_ALL_ANNOTATIONS + Hide all shape annotations for the object + + + TOP_POP_HIDE_ALL_ANNOTATIONS + Hide all shape annotations for the object + TOP_POP_AUTO_COLOR 自動色 diff --git a/src/GEOMGUI/GeometryGUI.cxx b/src/GEOMGUI/GeometryGUI.cxx old mode 100644 new mode 100755 index eb9c53f87..49a223a0a --- a/src/GEOMGUI/GeometryGUI.cxx +++ b/src/GEOMGUI/GeometryGUI.cxx @@ -39,6 +39,8 @@ #include "GEOM_Displayer.h" #include "GEOM_AISShape.hxx" #include "GEOMUtils_XmlHandler.hxx" +#include "GEOMGUI_AnnotationMgr.h" +#include "GEOMGUI_TextTreeSelector.h" #include "GEOM_Actor.h" @@ -227,6 +229,7 @@ GeometryGUI::GeometryGUI() : myCreationInfoWdg = 0; myTextTreeWdg = 0; + myAnnotationMgr = 0; connect( Material_ResourceMgr::resourceMgr(), SIGNAL( changed() ), this, SLOT( updateMaterials() ) ); @@ -373,6 +376,26 @@ void GeometryGUI::ActiveWorkingPlane() } } +//======================================================================= +// function : GeometryGUI::SetActiveDialogBox() +// purpose : Set active dialog box +//======================================================================= +GEOMGUI_AnnotationMgr* GeometryGUI::GetAnnotationMgr() +{ + if ( !myAnnotationMgr ) + myAnnotationMgr = new GEOMGUI_AnnotationMgr( getApp() ); + return myAnnotationMgr; +} + +//======================================================================= +// function : GeometryGUI::SetActiveDialogBox() +// purpose : Set active dialog box +//======================================================================= +GEOMGUI_TextTreeWdg* GeometryGUI::GetTextTreeWdg() const +{ + return myTextTreeWdg; +} + //======================================================================= // function : GeometryGUI::SetActiveDialogBox() // purpose : Set active dialog box @@ -661,11 +684,16 @@ void GeometryGUI::OnGUIEvent( int id, const QVariant& theParam ) case GEOMOp::OpCheckSelfInters: // MENU MEASURE - CHECK SELF INTERSECTIONS case GEOMOp::OpFastCheckInters: // MENU MEASURE - FAST CHECK INTERSECTIONS case GEOMOp::OpManageDimensions: // MENU MEASURE - MANAGE DIMENSIONS + case GEOMOp::OpAnnotation: // MENU MEASURE - ANNOTATION + case GEOMOp::OpEditAnnotation: // POPUP MENU - EDIT ANNOTATION + case GEOMOp::OpDeleteAnnotation: // POPUP MENU - DELETE ANNOTATION #ifndef DISABLE_PLOT2DVIEWER case GEOMOp::OpShapeStatistics: // MENU MEASURE - SHAPE STATISTICS #endif case GEOMOp::OpShowAllDimensions: // POPUP MENU - SHOW ALL DIMENSIONS case GEOMOp::OpHideAllDimensions: // POPUP MENU - HIDE ALL DIMENSIONS + case GEOMOp::OpShowAllAnnotations: // POPUP MENU - SHOW ALL ANNOTATIONS + case GEOMOp::OpHideAllAnnotations: // POPUP MENU - HIDE ALL ANNOTATIONS libName = "MeasureGUI"; break; case GEOMOp::OpGroupCreate: // MENU GROUP - CREATE @@ -1042,6 +1070,9 @@ void GeometryGUI::initialize( CAM_Application* app ) createGeomAction( GEOMOp::OpMinDistance, "MIN_DIST" ); createGeomAction( GEOMOp::OpAngle, "MEASURE_ANGLE" ); createGeomAction( GEOMOp::OpManageDimensions, "MANAGE_DIMENSIONS" ); + createGeomAction( GEOMOp::OpAnnotation, "ANNOTATION" ); + createGeomAction( GEOMOp::OpEditAnnotation, "EDIT_ANNOTATION" ); + createGeomAction( GEOMOp::OpDeleteAnnotation, "DELETE_ANNOTATION" ); createGeomAction( GEOMOp::OpTolerance, "TOLERANCE" ); createGeomAction( GEOMOp::OpWhatIs, "WHAT_IS" ); @@ -1115,9 +1146,11 @@ void GeometryGUI::initialize( CAM_Application* app ) #ifndef DISABLE_GRAPHICSVIEW createGeomAction( GEOMOp::OpShowDependencyTree, "POP_SHOW_DEPENDENCY_TREE" ); #endif - createGeomAction( GEOMOp::OpReduceStudy, "POP_REDUCE_STUDY" ); - createGeomAction( GEOMOp::OpShowAllDimensions, "POP_SHOW_ALL_DIMENSIONS" ); - createGeomAction( GEOMOp::OpHideAllDimensions, "POP_HIDE_ALL_DIMENSIONS" ); + createGeomAction( GEOMOp::OpReduceStudy, "POP_REDUCE_STUDY" ); + createGeomAction( GEOMOp::OpShowAllDimensions, "POP_SHOW_ALL_DIMENSIONS" ); + createGeomAction( GEOMOp::OpHideAllDimensions, "POP_HIDE_ALL_DIMENSIONS" ); + createGeomAction( GEOMOp::OpShowAllAnnotations, "POP_SHOW_ALL_ANNOTATIONS" ); + createGeomAction( GEOMOp::OpHideAllAnnotations, "POP_HIDE_ALL_ANNOTATIONS" ); // Create actions for increase/decrease transparency shortcuts createGeomAction( GEOMOp::OpIncrTransparency, "", "", 0, false, @@ -1310,6 +1343,8 @@ void GeometryGUI::initialize( CAM_Application* app ) createMenu( GEOMOp::OpAngle, dimId, -1 ); createMenu( GEOMOp::OpManageDimensions, dimId, -1 ); + createMenu( GEOMOp::OpAnnotation, measurId, -1 ); + createMenu( separator(), measurId, -1 ); createMenu( GEOMOp::OpTolerance, measurId, -1 ); createMenu( separator(), measurId, -1 ); @@ -1466,6 +1501,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createTool( GEOMOp::OpBoundingBox, measureTbId ); createTool( GEOMOp::OpMinDistance, measureTbId ); createTool( GEOMOp::OpAngle, measureTbId ); + createTool( GEOMOp::OpAnnotation, measureTbId ); createTool( GEOMOp::OpTolerance , measureTbId ); createTool( separator(), measureTbId ); createTool( GEOMOp::OpFreeBoundaries, measureTbId ); @@ -1586,6 +1622,12 @@ void GeometryGUI::initialize( CAM_Application* app ) mgr->setRule( action( GEOMOp::OpNoAutoColor ), autoColorPrefix + " and isAutoColor=true", QtxPopupMgr::VisibleRule ); mgr->insert( separator(), -1, -1 ); // ----------- + mgr->insert( action( GEOMOp::OpEditAnnotation ), -1, -1 ); // edit annotation + mgr->setRule( action( GEOMOp::OpEditAnnotation ), clientOCC + " and annotationsCount=1", QtxPopupMgr::VisibleRule ); + mgr->insert( action( GEOMOp::OpDeleteAnnotation ), -1, -1 ); // delete annotation + mgr->setRule( action( GEOMOp::OpDeleteAnnotation ), clientOCC + " and annotationsCount>0", QtxPopupMgr::VisibleRule ); + mgr->insert( separator(), -1, -1 ); // ----------- + QString canDisplay = "($component={'GEOM'}) and (selcount>0) and ({true} in $canBeDisplayed) ", onlyComponent = "((type='Component') and selcount=1)", rule = canDisplay + "and ((($type in {%1}) and( %2 )) or " + onlyComponent + ")", @@ -1640,6 +1682,10 @@ void GeometryGUI::initialize( CAM_Application* app ) mgr->setRule( action( GEOMOp::OpShowAllDimensions ), aDimensionRule.arg( "hasHiddenDimensions" ), QtxPopupMgr::VisibleRule ); mgr->insert( action( GEOMOp::OpHideAllDimensions ), -1, -1 ); // hide all dimensions mgr->setRule( action( GEOMOp::OpHideAllDimensions ), aDimensionRule.arg( "hasVisibleDimensions" ), QtxPopupMgr::VisibleRule ); + mgr->insert( action( GEOMOp::OpShowAllAnnotations ), -1, -1 ); // show all annotations + mgr->setRule( action( GEOMOp::OpShowAllAnnotations ), aDimensionRule.arg( "hasHiddenAnnotations" ), QtxPopupMgr::VisibleRule ); + mgr->insert( action( GEOMOp::OpHideAllAnnotations ), -1, -1 ); // hide all annotations + mgr->setRule( action( GEOMOp::OpHideAllAnnotations ), aDimensionRule.arg( "hasVisibleAnnotations" ), QtxPopupMgr::VisibleRule ); mgr->insert( separator(), -1, -1 ); // ----------- mgr->insert( action( GEOMOp::OpUnpublishObject ), -1, -1 ); // Unpublish object @@ -1821,8 +1867,11 @@ bool GeometryGUI::activateModule( SUIT_Study* study ) getApp()->insertDockWindow( myCreationInfoWdg->getWinID(), myCreationInfoWdg ); getApp()->placeDockWindow( myCreationInfoWdg->getWinID(), Qt::LeftDockWidgetArea ); - if ( !myTextTreeWdg ) + if ( !myTextTreeWdg ) { myTextTreeWdg = new GEOMGUI_TextTreeWdg( getApp() ); + new GEOMGUI_TextTreeSelector( myTextTreeWdg, GetAnnotationMgr(), getApp()->selectionMgr() ); + } + getApp()->insertDockWindow( myTextTreeWdg->getWinID(), myTextTreeWdg ); getApp()->placeDockWindow( myTextTreeWdg->getWinID(), Qt::LeftDockWidgetArea ); @@ -2028,6 +2077,10 @@ void GeometryGUI::onViewManagerRemoved( SUIT_ViewManager* vm ) break; } } + SOCC_Viewer* aSOCCView = dynamic_cast(viewer); + if ( aSOCCView ) { + GetAnnotationMgr()->RemoveView( aSOCCView ); + } } //================================================================================ @@ -2355,6 +2408,10 @@ void GeometryGUI::createPreferences() addPreference( tr( "PREF_AUTO_BRING_TO_FRONT" ), genGroup, LightApp_Preferences::Bool, "Geometry", "auto_bring_to_front" ); + // -------------------------------------------------------------------------- + // Dimensions (Measurements) preferences + // -------------------------------------------------------------------------- + int aDimGroupId = addPreference( tr( "PREF_DIMENSIONS" ), tabId ); setPreferenceProperty( aDimGroupId, "columns", 2 ); @@ -2438,6 +2495,53 @@ void GeometryGUI::createPreferences() addPreference( tr( "PREF_DIMENSIONS_USE_TEXT3D" ), aDimGroupId, LightApp_Preferences::Bool, "Geometry", "dimensions_use_text3d" ); + // -------------------------------------------------------------------------- + // Shape annotation preferences + // -------------------------------------------------------------------------- + + const int aShapeAnnGroupId = addPreference( tr( "PREF_SHAPE_ANNOTATIONS" ), tabId ); + setPreferenceProperty( aShapeAnnGroupId, "columns", 2 ); + + addPreference( tr( "PREF_SHAPE_ANNOTATIONS_FONT_COLOR" ), aShapeAnnGroupId, LightApp_Preferences::Color, "Geometry", "shape_annotation_font_color" ); + addPreference( tr( "PREF_SHAPE_ANNOTATIONS_LINE_COLOR" ), aShapeAnnGroupId, LightApp_Preferences::Color, "Geometry", "shape_annotation_line_color" ); + const int aShapeAnnFont = + addPreference( tr( "PREF_SHAPE_ANNOTATIONS_FONT" ), aShapeAnnGroupId, LightApp_Preferences::Font, "Geometry", "shape_annotation_font" ); + + int aShapeAnnFontFeatures = QtxFontEdit::Family | QtxFontEdit::Size | QtxFontEdit::Bold | QtxFontEdit::Italic; + setPreferenceProperty( aShapeAnnFont, "features", aShapeAnnFontFeatures ); + setPreferenceProperty( aShapeAnnFont, "mode", QtxFontEdit::Custom ); + setPreferenceProperty( aShapeAnnFont, "fonts", anOCCFonts ); + + const int aShapeAnnLineWidth = + addPreference( tr( "PREF_SHAPE_ANNOTATIONS_LINE_WIDTH" ), aShapeAnnGroupId, LightApp_Preferences::IntSpin, "Geometry", "shape_annotation_line_width" ); + + setPreferenceProperty( aShapeAnnLineWidth, "min", 1 ); + setPreferenceProperty( aShapeAnnLineWidth, "max", 5 ); + + addPreference( tr( "PREF_SHAPE_ANNOTATIONS_AUTOHIDE" ), aShapeAnnGroupId, LightApp_Preferences::Bool, "Geometry", "shape_annotation_autohide" ); + + const int aShapeAnnLineStyle = + addPreference( tr( "PREF_SHAPE_ANNOTATIONS_LINE_STYLE" ), aShapeAnnGroupId, LightApp_Preferences::Selector, "Geometry", "shape_annotation_line_style" ); + + QStringList aLineStyleList; + aLineStyleList.append( tr("PREF_SHAPE_ANNOTATIONS_LINESTYLE_SOLID") ); + aLineStyleList.append( tr("PREF_SHAPE_ANNOTATIONS_LINESTYLE_DASH") ); + aLineStyleList.append( tr("PREF_SHAPE_ANNOTATIONS_LINESTYLE_DOT") ); + aLineStyleList.append( tr("PREF_SHAPE_ANNOTATIONS_LINESTYLE_DOTDASH") ); + + QList aLineStyleIds; + aLineStyleIds.append(0); + aLineStyleIds.append(1); + aLineStyleIds.append(2); + aLineStyleIds.append(3); + + setPreferenceProperty( aShapeAnnLineStyle, "strings", aLineStyleList ); + setPreferenceProperty( aShapeAnnLineStyle, "indexes", aLineStyleIds ); + + // -------------------------------------------------------------------------- + // Isoline drawing preferences + // -------------------------------------------------------------------------- + int isoGroup = addPreference( tr( "PREF_ISOS" ), tabId ); setPreferenceProperty( isoGroup, "columns", 2 ); int isoU = addPreference( tr( "PREF_ISOS_U" ), isoGroup, @@ -2703,14 +2807,21 @@ 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") || - param == QString("dimensions_arrow_length") || - param == QString("dimensions_show_units") || - param == QString("dimensions_length_units") || - param == QString("dimensions_angle_units") || - param == QString("dimensions_use_text3d") || + else if ( param == QString("dimensions_color") || + param == QString("dimensions_line_width") || + param == QString("dimensions_font") || + param == QString("dimensions_arrow_length") || + param == QString("dimensions_show_units") || + param == QString("dimensions_length_units") || + param == QString("dimensions_angle_units") || + param == QString("dimensions_use_text3d") || + param == QString("shape_annotation_font_color") || + param == QString("shape_annotation_line_color") || + param == QString("shape_annotation_font") || + param == QString("shape_annotation_line_width") || + param == QString("shape_annotation_autohide") || + param == QString("shape_annotation_line_style") || + param == QString("shape_annotation_line_style") || param == QString("label_color") ) { SalomeApp_Application* anApp = getApp(); @@ -2740,6 +2851,20 @@ void GeometryGUI::preferencesChanged( const QString& section, const QString& par SALOME_ListIO aVisible; aViewer->GetVisible( aVisible ); + + GEOMGUI_AnnotationMgr* anAnnotationMgr = GetAnnotationMgr(); + if ( anAnnotationMgr ) { + SALOME_ListIteratorOfListIO anIter( aVisible ); + while ( anIter.More() ) { + if ( anAnnotationMgr->isAnnotationEntry( anIter.Value()->getEntry() ) ) { + aVisible.Remove( anIter ); + } + else { + anIter.Next(); + } + } + } + aDisplayer.Redisplay( aVisible, false, aViewer ); } if ( param == QString( "label_color" ) ) { @@ -2796,6 +2921,7 @@ void GeometryGUI::storeVisualParameters (int savePoint) SalomeApp_Study* appStudy = dynamic_cast(application()->activeStudy()); if ( !appStudy || !appStudy->studyDS() ) return; + _PTR(Study) studyDS = appStudy->studyDS(); // componentName is used for encoding of entries when storing them in IParameters @@ -2813,12 +2939,17 @@ void GeometryGUI::storeVisualParameters (int savePoint) QList lst; QList::Iterator it; + GEOMGUI_AnnotationMgr* aAnnotationMgr = GetAnnotationMgr(); + // main cycle to store parameters of displayed objects lst.clear(); getApp()->viewManagers(lst); for (it = lst.begin(); it != lst.end(); it++) { SUIT_ViewManager* vman = *it; QString vType = vman->getType(); + SUIT_ViewModel* vmodel = vman->getViewModel(); + SALOME_View* aView = dynamic_cast(vmodel); + int aMgrId = vman->getGlobalId(); // saving VTK actors properties QVector views = vman->getViews(); @@ -2940,28 +3071,41 @@ void GeometryGUI::storeVisualParameters (int savePoint) param = occParam + GEOM::propertyName( GEOM::IsosWidth ); ip->setParameter(entry, param.toStdString(), aProps.value(GEOM::propertyName( GEOM::IsosWidth )).toString().toStdString()); } + + if ( vType == SOCC_Viewer::Type() && aAnnotationMgr ) { + std::string anAnnotationInfo = GetAnnotationMgr()->getDisplayedIndicesInfo( + o_it.key().toLatin1().data(), dynamic_cast(aView) ).toStdString(); + if (!anAnnotationInfo.empty()) { + param = occParam + "ShapeAnnotationVisibleItems"; + ip->setParameter(entry, param.toStdString(), anAnnotationInfo); + } + } } // object iterator } // for (views) } // for (viewManagers) - // store dimension attributes of objects: + // store shape annotation and dimension attributes of objects: // since the displayed object always persists in property map, we remember the object entries // on the passes when we store viewer related properties - to avoid extra iterations on GEOM component tree. - QString aDimensionParam = OCCViewer_Viewer::Type() + GEOM::sectionSeparator() + GEOM::propertyName( GEOM::Dimensions ); + const QString aDimensionParam = OCCViewer_Viewer::Type() + GEOM::sectionSeparator() + GEOM::propertyName( GEOM::Dimensions ); + const QString aAnnotationParam = OCCViewer_Viewer::Type() + GEOM::sectionSeparator() + GEOM::propertyName( GEOM::ShapeAnnotations ); QSet::ConstIterator aEntryIt = anEntriesToStoreShared.constBegin(); for ( ; aEntryIt != anEntriesToStoreShared.constEnd(); ++aEntryIt ) { std::string aStudyEntry = (*aEntryIt).toLatin1().data(); - std::string aStoreEntry = ip->encodeEntry( aStudyEntry, componentName); + std::string aStoreEntry = ip->encodeEntry( aStudyEntry, componentName ); + // store dimension parameters GEOMGUI_DimensionProperty aDimensions( appStudy, aStudyEntry ); - - if ( aDimensions.GetNumber() == 0 ) - { - continue; + if ( aDimensions.GetNumber() != 0 ) { + ip->setParameter( aStoreEntry, aDimensionParam.toStdString(), ((QString)aDimensions).toLatin1().data() ); } - ip->setParameter( aStoreEntry, aDimensionParam.toStdString(), ((QString)aDimensions).toLatin1().data() ); + _PTR(SObject) aObj( studyDS->FindObjectID( aStudyEntry ) ); + const Handle(GEOMGUI_AnnotationAttrs) aShapeAnnAttr = GEOMGUI_AnnotationAttrs::FindAttributes( aObj ); + if ( !aShapeAnnAttr.IsNull() ) { + ip->setParameter( aStoreEntry, aAnnotationParam.toStdString(), aShapeAnnAttr->ExportAsPropertyString().toLatin1().data() ); + } } } @@ -3044,6 +3188,13 @@ void GeometryGUI::restoreVisualParameters (int savePoint) GEOMGUI_DimensionProperty aDimensionProp( aValuesStr ); aDimensionProp.SaveToAttribute( appStudy, entry.toLatin1().data() ); } + else if ( aParamNameStr == GEOM::propertyName( GEOM::ShapeAnnotations ) ) + { + Handle(GEOMGUI_AnnotationAttrs) anAttr = + GEOMGUI_AnnotationAttrs::FindOrCreateAttributes( so, appStudy ); + + anAttr->ImportFromPropertyString( aValuesStr ); + } continue; } @@ -3099,7 +3250,10 @@ void GeometryGUI::restoreVisualParameters (int savePoint) aListOfMap[viewIndex].insert( GEOM::propertyName( GEOM::LineWidth ), val.toInt()); } else if (paramNameStr == GEOM::propertyName( GEOM::IsosWidth )) { aListOfMap[viewIndex].insert( GEOM::propertyName( GEOM::IsosWidth ), val.toInt()); + } else if (paramNameStr == "ShapeAnnotationVisibleItems") { + aListOfMap[viewIndex].insert( "ShapeAnnotationVisibleItems", val); } + } // for names/parameters iterator QList lst = getApp()->viewManagers(); @@ -3111,7 +3265,16 @@ void GeometryGUI::restoreVisualParameters (int savePoint) if (aListOfMap[index].value(GEOM::propertyName( GEOM::Visibility )) == 1) { SUIT_ViewManager* vman = lst.at(index); SUIT_ViewModel* vmodel = vman->getViewModel(); - displayer()->Display(entry, true, dynamic_cast(vmodel)); + SALOME_View* aView = dynamic_cast(vmodel); + displayer()->Display(entry, true, aView); + + if ( vmodel->getType() == SOCC_Viewer::Type() ) { + PropMap& aProps = aListOfMap[index]; + if ( aProps.contains( "ShapeAnnotationVisibleItems" ) ) { + SOCC_Viewer* aSOCCView = dynamic_cast( aView ); + GetAnnotationMgr()->setDisplayedIndicesInfo( entry, aSOCCView, aProps["ShapeAnnotationVisibleItems"].toString() ); + } + } } } } // for entries iterator @@ -3135,6 +3298,10 @@ void GeometryGUI::restoreVisualParameters (int savePoint) occVMod->Repaint(); } } + + if ( myTextTreeWdg ) { + myTextTreeWdg->updateTree(); + } } // Compute current name mode of the viewer @@ -3367,6 +3534,7 @@ bool GeometryGUI::renameObject( const QString& entry, const QString& name) if (!CORBA::is_nil(anObj)) { anObj->SetName( name.toLatin1().data() ); // Rename the corresponding GEOM_Object emit SignalDependencyTreeRenameObject( anObj->GetEntry() ); + emit SignalTextTreeRenameObject( entry ); } result = true; } @@ -3534,3 +3702,8 @@ void GeometryGUI::emitDimensionsUpdated( QString entry ) { emit DimensionsUpdated( entry ); } + +void GeometryGUI::emitAnnotationsUpdated( QString entry ) +{ + emit SignalAnnotationsUpdated( entry ); +} diff --git a/src/GEOMGUI/GeometryGUI.h b/src/GEOMGUI/GeometryGUI.h index f92d92ab7..78a067a67 100644 --- a/src/GEOMGUI/GeometryGUI.h +++ b/src/GEOMGUI/GeometryGUI.h @@ -36,6 +36,7 @@ #include #include #include +#include #include "GEOMGUI.h" #include "GEOMPluginGUI.h" @@ -65,6 +66,7 @@ class SUIT_ViewManager; class SalomeApp_Study; class GEOMGUI_CreationInfoWdg; class GEOMGUI_TextTreeWdg; +class GEOMGUI_AnnotationMgr; //================================================================================= // class : GeometryGUI @@ -98,6 +100,10 @@ public: GEOM_Client& GetShapeReader() { static SHAPE_READER(myShapeReader);return myShapeReader; } + GEOMGUI_AnnotationMgr* GetAnnotationMgr(); + + GEOMGUI_TextTreeWdg* GetTextTreeWdg() const; + // Get active dialog box QDialog* GetActiveDialogBox(){ return myActiveDialogBox; } // Set active dialog box @@ -150,6 +156,7 @@ public: const int row, Qt::DropAction action ); void emitDimensionsUpdated( QString entry ); + void emitAnnotationsUpdated( QString entry ); public slots: virtual bool deactivateModule( SUIT_Study* ); @@ -179,6 +186,8 @@ signals : void SignalDefaultStepValueChanged( double newVal ); void SignalDependencyTreeParamChanged( const QString&, const QString& ); void SignalDependencyTreeRenameObject( const QString& ); + void SignalTextTreeRenameObject( const QString& ); + void SignalAnnotationsUpdated( const QString& ); void DimensionsUpdated( const QString& ); protected: @@ -228,7 +237,8 @@ private: GEOMGUI_CreationInfoWdg* myCreationInfoWdg; - GEOMGUI_TextTreeWdg* myTextTreeWdg; + GEOMGUI_TextTreeWdg* myTextTreeWdg; + GEOMGUI_AnnotationMgr* myAnnotationMgr; SALOME_ListIO myTopLevelIOList; diff --git a/src/GEOMGUI/GeometryGUI_Operations.h b/src/GEOMGUI/GeometryGUI_Operations.h old mode 100644 new mode 100755 index cc44ca9a9..da8ae797e --- a/src/GEOMGUI/GeometryGUI_Operations.h +++ b/src/GEOMGUI/GeometryGUI_Operations.h @@ -207,6 +207,11 @@ namespace GEOMOp { #ifndef DISABLE_PLOT2DVIEWER OpShapeStatistics = 5019, // MENU MEASURES - SHAPE STATISTICS #endif + OpAnnotation = 5020, // MENU MEASURES - ANNOTATION + OpEditAnnotation = 5021, // POPUP MENU - EDIT ANNOTATION + OpShowAllAnnotations = 5022, // POPUP MENU - SHOW ALL ANNOTATIONS + OpHideAllAnnotations = 5023, // POPUP MENU - HIDE ALL ANNOTATIONS + OpDeleteAnnotation = 5024, // POPUP MENU - DELETE ANNOTATION // GroupGUI --------------------//-------------------------------- OpGroupCreate = 6000, // MENU GROUP - CREATE OpGroupEdit = 6001, // MENU GROUP - EDIT diff --git a/src/MeasureGUI/CMakeLists.txt b/src/MeasureGUI/CMakeLists.txt index 5b652b084..7bbd75177 100755 --- a/src/MeasureGUI/CMakeLists.txt +++ b/src/MeasureGUI/CMakeLists.txt @@ -88,6 +88,8 @@ SET(MeasureGUI_HEADERS MeasureGUI_InertiaDlg.h MeasureGUI_BndBoxDlg.h MeasureGUI_DistanceDlg.h + MeasureGUI_AnnotationDlg.h + MeasureGUI_AnnotationInteractor.h MeasureGUI_AngleDlg.h MeasureGUI_MaxToleranceDlg.h MeasureGUI_WhatisDlg.h @@ -116,6 +118,8 @@ SET(_moc_HEADERS MeasureGUI_InertiaDlg.h MeasureGUI_BndBoxDlg.h MeasureGUI_DistanceDlg.h + MeasureGUI_AnnotationDlg.h + MeasureGUI_AnnotationInteractor.h MeasureGUI_AngleDlg.h MeasureGUI_MaxToleranceDlg.h MeasureGUI_WhatisDlg.h @@ -154,6 +158,8 @@ SET(MeasureGUI_SOURCES MeasureGUI_InertiaDlg.cxx MeasureGUI_BndBoxDlg.cxx MeasureGUI_DistanceDlg.cxx + MeasureGUI_AnnotationDlg.cxx + MeasureGUI_AnnotationInteractor.cxx MeasureGUI_AngleDlg.cxx MeasureGUI_MaxToleranceDlg.cxx MeasureGUI_WhatisDlg.cxx diff --git a/src/MeasureGUI/MeasureGUI.cxx b/src/MeasureGUI/MeasureGUI.cxx old mode 100644 new mode 100755 index 38a6f3be7..d50c62cf1 --- a/src/MeasureGUI/MeasureGUI.cxx +++ b/src/MeasureGUI/MeasureGUI.cxx @@ -28,8 +28,11 @@ #include #include "GeometryGUI_Operations.h" +#include #include +#include +#include #include #include @@ -44,6 +47,7 @@ #include "MeasureGUI_BndBoxDlg.h" // Method BNDBOX #include "MeasureGUI_DistanceDlg.h" // Method DISTANCE #include "MeasureGUI_AngleDlg.h" // Method ANGLE +#include "MeasureGUI_AnnotationDlg.h" // Method ANNOTATION #include "MeasureGUI_MaxToleranceDlg.h" // Method MAXTOLERANCE #include "MeasureGUI_WhatisDlg.h" // Method WHATIS #include "MeasureGUI_CheckShapeDlg.h" // Method CHECKSHAPE @@ -111,6 +115,12 @@ bool MeasureGUI::OnGUIEvent( int theCommandID, SUIT_Desktop* parent ) case GEOMOp::OpAngle: dlg = new MeasureGUI_AngleDlg( getGeometryGUI(), parent ); break; // ANGLE + case GEOMOp::OpAnnotation: + dlg = new MeasureGUI_AnnotationDlg( getGeometryGUI(), true, parent ); + break; // ANNOTATION + case GEOMOp::OpEditAnnotation: + dlg = new MeasureGUI_AnnotationDlg( getGeometryGUI(), false, parent ); + break; // ANNOTATION case GEOMOp::OpTolerance: dlg = new MeasureGUI_MaxToleranceDlg( getGeometryGUI(), parent ); break; // MAXTOLERANCE @@ -154,6 +164,15 @@ bool MeasureGUI::OnGUIEvent( int theCommandID, SUIT_Desktop* parent ) case GEOMOp::OpHideAllDimensions: ChangeDimensionsVisibility( false ); break; // HIDE ALL DIMENSIONS + case GEOMOp::OpShowAllAnnotations: + ChangeAnnotationsVisibility( true ); + break; // SHOW ALL ANNOTATIONS + case GEOMOp::OpHideAllAnnotations: + ChangeAnnotationsVisibility( false ); + break; // HIDE ALL ANNOTATIONS + case GEOMOp::OpDeleteAnnotation: + DeleteAnnotation(); + break; // DELETE ANNOTATIOn default: app->putInfo( tr( "GEOM_PRP_COMMAND" ).arg( theCommandID ) ); break; @@ -173,48 +192,161 @@ bool MeasureGUI::OnGUIEvent( int theCommandID, SUIT_Desktop* parent ) void MeasureGUI::ChangeDimensionsVisibility( const bool theIsVisible ) { SalomeApp_Application* anApp = getGeometryGUI()->getApp(); - if (!anApp) - { + if ( !anApp ) return; - } SalomeApp_Study* anActiveStudy = dynamic_cast( anApp->activeStudy() ); if ( !anActiveStudy ) - { return; - } - LightApp_SelectionMgr* aSelMgr = anApp->selectionMgr(); - if ( !aSelMgr ) - { + Handle(SALOME_InteractiveObject) anIObject = getSingleSelectedIO(); + if ( anIObject.IsNull() + || !anIObject->hasEntry() ) return; + + SUIT_OverrideCursor wc; + + GEOMGUI_DimensionProperty aDimensions( anActiveStudy, anIObject->getEntry() ); + + for ( int anIt = 0; anIt < aDimensions.GetNumber(); ++anIt ) { + aDimensions.SetVisible( anIt, theIsVisible ); } - SALOME_ListIO aListIO; - aSelMgr->selectedObjects( aListIO ); - if ( aListIO.Extent() != 1 ) - { + aDimensions.SaveToAttribute( anActiveStudy, anIObject->getEntry() ); + + GEOM_Displayer( anActiveStudy ).Redisplay( anIObject, true ); +} + +//======================================================================= +// function : ChangeAnnotationsVisibility +// purpose : +//======================================================================= +void MeasureGUI::ChangeAnnotationsVisibility( const bool theIsVisible ) +{ + SalomeApp_Application* anApp = getGeometryGUI()->getApp(); + if ( !anApp ) return; - } - Handle(SALOME_InteractiveObject) anIObject = aListIO.First(); - if ( !anIObject->hasEntry() ) - { + SalomeApp_Study* anActiveStudy = dynamic_cast( anApp->activeStudy() ); + if ( !anActiveStudy ) return; + + QString anEntry; + Handle(SALOME_InteractiveObject) anIObject = getSingleSelectedIO(); + if ( !anIObject.IsNull() && anIObject->hasEntry() ) { + anEntry = anIObject->getEntry(); + } + if ( anEntry.isEmpty() ) { + anEntry = getGeometryGUI()->GetTextTreeWdg()->getSingleSelectedObject(); } - SUIT_OverrideCursor wc; + if ( !anEntry.isEmpty() ) { + _PTR(SObject) aSObj = anActiveStudy->studyDS()->FindObjectID( anEntry.toStdString() ); - GEOMGUI_DimensionProperty aDimensions( anActiveStudy, anIObject->getEntry() ); + const Handle(GEOMGUI_AnnotationAttrs) + aShapeAnnotations = GEOMGUI_AnnotationAttrs::FindAttributes( aSObj ); - for ( int anIt = 0; anIt < aDimensions.GetNumber(); ++anIt ) + if ( aShapeAnnotations.IsNull() ) { + return; + } + + const int aCount = aShapeAnnotations->GetNbAnnotation(); + + if ( aCount > 0 ) { + + SUIT_OverrideCursor wc; + + for ( int anI = 0; anI < aCount; ++anI ) { + + if ( !theIsVisible ) { + getGeometryGUI()->GetAnnotationMgr()->Erase( anEntry, anI ); + } + else { + getGeometryGUI()->GetAnnotationMgr()->Display( anEntry , anI ); + } + } + + getGeometryGUI()->emitAnnotationsUpdated( anEntry ); + } + } + else { + if ( theIsVisible ) { + getGeometryGUI()->GetAnnotationMgr()->DisplayAllAnnotations(); + } + else { + getGeometryGUI()->GetAnnotationMgr()->EraseAllAnnotations(); + } + getGeometryGUI()->GetTextTreeWdg()->updateVisibility(); + } +} + +//======================================================================= +// function : DeleteAnnotation +// purpose : +//======================================================================= +void MeasureGUI::DeleteAnnotation() +{ + SalomeApp_Application* anApp = getGeometryGUI()->getApp(); + if ( !anApp ) + return; + + SalomeApp_Study* anActiveStudy = dynamic_cast( anApp->activeStudy() ); + if ( !anActiveStudy ) + return; + + Handle(SALOME_InteractiveObject) anIObject = getSingleSelectedIO(); + if ( anIObject.IsNull() + || !anIObject->hasEntry() ) + return; + + const QString aEntry = anIObject->getEntry(); + + QString aObjEntry; + + int aIndex = 0; + + if ( getGeometryGUI()->GetAnnotationMgr()->getIndexFromEntry( aEntry, aObjEntry, aIndex ) ) { - aDimensions.SetVisible( anIt, theIsVisible ); + _PTR(SObject) aSObj = anActiveStudy->studyDS()->FindObjectID( aObjEntry.toStdString() ); + + const Handle(GEOMGUI_AnnotationAttrs) + aShapeAnnotations = GEOMGUI_AnnotationAttrs::FindAttributes( aSObj ); + + if ( aShapeAnnotations.IsNull() ) { + return; + } + + aShapeAnnotations->Remove( aIndex ); + + getGeometryGUI()->GetAnnotationMgr()->EraseRemovedAnnotation( aObjEntry, aIndex ); + + getGeometryGUI()->emitAnnotationsUpdated( aObjEntry ); } +} - aDimensions.SaveToAttribute( anActiveStudy, anIObject->getEntry() ); +//======================================================================= +// function : getSingleSelectedIO +// purpose : returns selected interactive object for single selection. +//======================================================================= +Handle(SALOME_InteractiveObject) MeasureGUI::getSingleSelectedIO() +{ + SalomeApp_Application* anApp = getGeometryGUI()->getApp(); + if ( !anApp ) { + return Handle(SALOME_InteractiveObject)(); + } - GEOM_Displayer( anActiveStudy ).Redisplay( anIObject, true ); + LightApp_SelectionMgr* aSelMgr = anApp->selectionMgr(); + if ( !aSelMgr ) { + return Handle(SALOME_InteractiveObject)(); + } + + SALOME_ListIO aListIO; + aSelMgr->selectedObjects( aListIO ); + if ( aListIO.Extent() != 1 ) { + return Handle(SALOME_InteractiveObject)(); + } + + return aListIO.First(); } //======================================================================= diff --git a/src/MeasureGUI/MeasureGUI.h b/src/MeasureGUI/MeasureGUI.h old mode 100644 new mode 100755 index 3067bbcc2..524225a39 --- a/src/MeasureGUI/MeasureGUI.h +++ b/src/MeasureGUI/MeasureGUI.h @@ -27,8 +27,12 @@ #ifndef MEASUREGUI_H #define MEASUREGUI_H +// GEOM includes #include +// GUI includes +#include + class QDialog; //================================================================================= @@ -52,6 +56,17 @@ public: // Show/hide all dimension created for object void ChangeDimensionsVisibility( const bool theIsVisible ); + + // Show/hide all shape annotations created for GEOM object + void ChangeAnnotationsVisibility( const bool theIsVisible ); + + // Deletes the selected annotation + void DeleteAnnotation(); + +private: + // Returns selected interactive object for single selection + Handle(SALOME_InteractiveObject) getSingleSelectedIO(); + private: QDialog* myManageDimensionDlg; private slots: diff --git a/src/MeasureGUI/MeasureGUI_AnnotationDlg.cxx b/src/MeasureGUI/MeasureGUI_AnnotationDlg.cxx new file mode 100755 index 000000000..99ee4d658 --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_AnnotationDlg.cxx @@ -0,0 +1,1008 @@ +// Copyright ( C ) 2007-2016 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, or ( at your option ) any later version. +// +// 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 +// + +// File : MeasureGUI_AnnotationDlg.cxx + +#include "MeasureGUI.h" +#include "MeasureGUI_AnnotationDlg.h" +#include "MeasureGUI_AnnotationInteractor.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#ifdef max +#undef max +#endif + +//======================================================================= +//function : MeasureGUI_AnnotationDlg +//purpose : +//======================================================================= + +MeasureGUI_AnnotationDlg::MeasureGUI_AnnotationDlg( GeometryGUI* theGeometryGUI, const bool theIsCreate, + QWidget* parent, bool modal, Qt::WindowFlags fl ) +: GEOMBase_Skeleton( theGeometryGUI, parent, modal, fl ), + myIsCreation( theIsCreate ), myShapeNameModified( false ) +{ + myEditCurrentArgument = 0; + + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + QPixmap iconSelect( resMgr->loadPixmap( "GEOM", tr( "ICON_SELECT" ) ) ); + + setWindowTitle( myIsCreation ? tr( "CREATE_ANNOTATION_TITLE" ) : tr( "EDIT_ANNOTATION_TITLE" ) ); + + // Shape type button group + mainFrame()->GroupBoxName->hide(); + mainFrame()->GroupConstructors->hide(); + + // Field properties + QGroupBox* propGroup = new QGroupBox( tr( "ANNOTATION_PROPERTIES" ), centralWidget() ); + QGridLayout* propLayout = new QGridLayout( propGroup ); + propLayout->setMargin( 9 ); + propLayout->setSpacing( 6 ); + + QLabel* textLabel = new QLabel( tr( "ANNOTATION_TEXT" ), propGroup ); + myTextEdit = new QLineEdit( propGroup ); + propLayout->addWidget( textLabel, 0, 0 ); + propLayout->addWidget( myTextEdit, 0, 1, 1, 2 ); + + // shape + QLabel* shapeLabel = new QLabel( tr( "ANNOTATION_SHAPE" ), propGroup ); + myShapeSelBtn = new QPushButton( propGroup ); + myShapeSelBtn->setIcon( iconSelect ); + myShapeSelBtn->setEnabled( myIsCreation ); + myShapeName = new QLineEdit( propGroup ); + myShapeName->setReadOnly( true ); + myShapeName->setEnabled( myIsCreation ); + + // data type + myIsScreenFixed = new QCheckBox( tr( "ANNOTATION_IS_SCREEN_FIXED" ), propGroup ); + myIsScreenFixed->setChecked( false ); // 3D, not fixed + + propLayout->addWidget( shapeLabel, 1, 0 ); + propLayout->addWidget( myShapeSelBtn, 1, 1 ); + propLayout->addWidget( myShapeName, 1, 2 ); + propLayout->addWidget( myIsScreenFixed, 2, 0, 1, 3 ); + propLayout->setColumnStretch( 2, 5 ); + + QLabel* shapeTypeLabel = new QLabel( tr( "ANNOTATION_SUB_SHAPE" ), propGroup ); + mySubShapeTypeCombo = new QComboBox( propGroup ); + mySubShapeTypeCombo->setEnabled( myIsCreation ); + mySubShapeTypeCombo->addItem( tr( "WHOLE_SHAPE" ), TopAbs_SHAPE ); + mySubShapeTypeCombo->addItem( tr( "GEOM_VERTEX" ), TopAbs_VERTEX ); + mySubShapeTypeCombo->addItem( tr( "GEOM_EDGE" ), TopAbs_EDGE ); + mySubShapeTypeCombo->addItem( tr( "GEOM_FACE" ), TopAbs_FACE ); + mySubShapeTypeCombo->addItem( tr( "GEOM_SOLID" ), TopAbs_SOLID ); + mySubShapeTypeCombo->setCurrentIndex( 0 ); // SHAPE + + propLayout->addWidget( shapeTypeLabel, 3, 0 ); + propLayout->addWidget( mySubShapeTypeCombo, 3, 1, 1, 2 ); + + // sub-shape + mySubShapeSelBtn = new QPushButton( propGroup ); + mySubShapeSelBtn->setIcon( iconSelect ); + mySubShapeSelBtn->setEnabled( myIsCreation ); + mySubShapeName = new QLineEdit( propGroup ); + mySubShapeName->setReadOnly( true ); + mySubShapeName->setEnabled( myIsCreation ); + + propLayout->addWidget( mySubShapeSelBtn, 4, 1 ); + propLayout->addWidget( mySubShapeName, 4, 2 ); + + QVBoxLayout* layout = new QVBoxLayout( centralWidget() ); + layout->setMargin( 0 ); + layout->setSpacing( 6 ); + layout->addWidget( propGroup ); + + setHelpFileName( "annotation_page.html" ); + + LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr(); + connect( aSelMgr, SIGNAL( currentSelectionChanged() ), this, + SLOT( SelectionIntoArgument() ) ); + connect( buttonOk(), SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) ); + connect( buttonApply(), SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) ); + + myInteractor = new MeasureGUI_AnnotationInteractor( theGeometryGUI, parent ); + myInteractor->Enable(); + + connect( myInteractor, SIGNAL( SignalInteractionFinished( Handle_GEOM_Annotation ) ), + this, SLOT( onDragged( Handle_GEOM_Annotation ) ) ); + + Init(); +} + +//======================================================================= +//function : ~MeasureGUI_AnnotationDlg +//purpose : +//======================================================================= + +MeasureGUI_AnnotationDlg::~MeasureGUI_AnnotationDlg() { +} + +//================================================================================= +// function : Init() +// purpose : fills annotation properties with default values( in create mode ) or +// the values of modified object +//================================================================================= +void MeasureGUI_AnnotationDlg::Init() +{ + if ( myIsCreation ) { + + // default presentation values + myIsPositionDefined = false; + myAnnotationProperties.Text = tr( "ANNOTATION_PREFIX" ); + myAnnotationProperties.IsVisible = false; + myAnnotationProperties.IsScreenFixed = false; + myAnnotationProperties.Attach = gp_Pnt( 0, 0, 0 ); + myAnnotationProperties.ShapeIndex = -1; + myAnnotationProperties.ShapeType = ( int ) TopAbs_SHAPE; + + // update internal controls and fields following to default values + activateSelectionArgument( myShapeSelBtn ); + + myTextEdit->setText( myAnnotationProperties.Text ); + myShapeNameModified = false; + myIsScreenFixed->setChecked( myAnnotationProperties.IsScreenFixed ); + + int aSubShapeTypeIndex = -1; + int aTypesCount = aTypesCount = mySubShapeTypeCombo->count(); + for ( int i = 0; i < aTypesCount && aSubShapeTypeIndex < 0; i++ ) { + int aType = mySubShapeTypeCombo->itemData( i ).toInt(); + if ( aType == myAnnotationProperties.ShapeType ) + aSubShapeTypeIndex = i; + } + mySubShapeTypeCombo->setCurrentIndex( aSubShapeTypeIndex ); + + mySelectionMode = ( TopAbs_ShapeEnum ) myAnnotationProperties.ShapeType; + SelectionIntoArgument(); + updateSubShapeEnableState(); + + // connect controls + connect( myShapeSelBtn, SIGNAL( clicked() ), this, + SLOT( SetEditCurrentArgument() ) ); + connect( mySubShapeSelBtn, SIGNAL( clicked() ), this, + SLOT( SetEditCurrentArgument() ) ); + + connect( myTextEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChange() ) ); + connect( myIsScreenFixed, SIGNAL( clicked( bool ) ), this, SLOT( onTypeChange() ) ); + connect( mySubShapeTypeCombo, SIGNAL( currentIndexChanged( int ) ), + this, SLOT( onSubShapeTypeChange() ) ); + + //SelectionIntoArgument(); + + redisplayPreview(); + } else { // edition + myIsPositionDefined = true; + mySelectionMode = TopAbs_SHAPE; + // find annotation + GEOMGUI_TextTreeWdg* aTextTreeWdg = myGeomGUI->GetTextTreeWdg(); + // text tree widget should be not empty + QMap > anAnnotations; + aTextTreeWdg->getSelected( anAnnotations ); + // there is only one annotation selected when edit is started + QMap >::const_iterator anIt = anAnnotations.begin(); + myEditAnnotationEntry = anIt.key(); + myEditAnnotationIndex = anIt.value()[0]; + + SalomeApp_Study* aStudy = getStudy(); + _PTR(SObject) aSObj = aStudy->studyDS()->FindObjectID( myEditAnnotationEntry.toStdString() ); + const Handle(GEOMGUI_AnnotationAttrs) aShapeAnnotations = GEOMGUI_AnnotationAttrs::FindAttributes( aSObj ); + if ( !aShapeAnnotations.IsNull() ) { + aShapeAnnotations->GetProperties( myEditAnnotationIndex, myAnnotationProperties ); + + myShape = GEOM::GEOM_Object::_narrow( GeometryGUI::ClientSObjectToObject(aSObj) ); + } + + /// fill dialog controls + myTextEdit->setText( myAnnotationProperties.Text ); + myShapeNameModified = false; + myIsScreenFixed->setChecked( myAnnotationProperties.IsScreenFixed ); + + int aSubShapeTypeIndex = -1; + int aTypesCount = aTypesCount = mySubShapeTypeCombo->count(); + for ( int i = 0; i < aTypesCount && aSubShapeTypeIndex < 0; i++ ) { + int aType = mySubShapeTypeCombo->itemData( i ).toInt(); + if ( aType == myAnnotationProperties.ShapeType ) + aSubShapeTypeIndex = i; + } + mySubShapeTypeCombo->setCurrentIndex( aSubShapeTypeIndex ); + + QString aShapeName = ""; + _PTR(GenericAttribute) anAttr; + if ( aSObj && aSObj->FindAttribute( anAttr, "AttributeName") ) { + _PTR(AttributeName) aNameAttr( anAttr ); + aNameAttr->Value(); + aShapeName = aNameAttr->Value().c_str(); + } + myShapeName->setText( aShapeName ); + + QString aSubShapeName = ""; + TopAbs_ShapeEnum aShapeType = ( TopAbs_ShapeEnum ) myAnnotationProperties.ShapeType; + if ( aShapeType != TopAbs_SHAPE ) { + aSubShapeName = QString( "%1:%2_%3" ).arg( aShapeName ) + .arg( GEOMBase::TypeName( aShapeType ) ) + .arg( myAnnotationProperties.ShapeIndex ); + } + mySubShapeName->setText( aSubShapeName ); + + mySelectionMode = ( TopAbs_ShapeEnum ) myAnnotationProperties.ShapeType; + //SelectionIntoArgument(); + updateSubShapeEnableState(); + + // connect controls + connect( myTextEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChange() ) ); + connect( myIsScreenFixed, SIGNAL( clicked( bool ) ), this, SLOT( onTypeChange() ) ); + + myGeomGUI->GetAnnotationMgr()->SetPreviewStyle( myEditAnnotationEntry, myEditAnnotationIndex, true ); + + SalomeApp_Application* anApp = myGeomGUI->getApp(); + if ( anApp ) + { + OCCViewer_ViewManager* aVM = (OCCViewer_ViewManager*)anApp->getViewManager( OCCViewer_Viewer::Type(), false ); + OCCViewer_Viewer* aViewer = (OCCViewer_Viewer*)aVM->getViewModel(); + aViewer->unHighlightAll( true, true ); + } + + redisplayPreview(); + } +} + +//================================================================================= +// function : activateSelection +// purpose : Activate local selection +//================================================================================= +void MeasureGUI_AnnotationDlg::activateSelection() +{ + globalSelection( GEOM_ALLOBJECTS ); + if ( !myShape->_is_nil() && mySelectionMode != TopAbs_SHAPE ) { + localSelection( myShape.get(), mySelectionMode ); + } +} + +//================================================================================= +// function : getShapeType() +// purpose : +//================================================================================= +TopAbs_ShapeEnum MeasureGUI_AnnotationDlg::getShapeType() const +{ + return ( TopAbs_ShapeEnum ) mySubShapeTypeCombo->itemData( + mySubShapeTypeCombo->currentIndex() ).toInt(); +} + +//================================================================================= +// function : ClickOnOk() +// purpose : +//================================================================================= +void MeasureGUI_AnnotationDlg::ClickOnOk() +{ + setIsApplyAndClose( true ); + if ( ClickOnApply() ) + ClickOnCancel(); + setIsApplyAndClose( false ); +} + +//================================================================================= +// function : ClickOnApply() +// purpose : +//================================================================================= +bool MeasureGUI_AnnotationDlg::ClickOnApply() +{ + if ( !isApplyAndClose() ) { + setIsDisableBrowsing( true ); + setIsDisplayResult( false ); + } + + QString msg; + if ( !isValid( msg ) ) { + showError( msg ); + return false; + } + + SUIT_OverrideCursor wc; + SUIT_Session::session()->activeApplication()->putInfo( "" ); + + try { + if ( openCommand() ) + if ( !execute( /*isApplyAndClose()*/ ) ) { + abortCommand(); + showError(); + return false; + } + } catch ( const SALOME::SALOME_Exception& e ) { + SalomeApp_Tools::QtCatchCorbaException( e ); + abortCommand(); + return false; + } + commitCommand(); + + if ( !isApplyAndClose() ) { + setIsDisableBrowsing( false ); + setIsDisplayResult( true ); + } + + if ( !myShape->_is_nil() ) { + redisplay( myShape.get() ); + } + + if ( myIsCreation ) { + + if ( !isApplyAndClose() ) + Init(); + } + + return true; +} + +//================================================================================= +// function : SetEditCurrentArgument() +// purpose : process click on shape/sub-shape button. It stores as current edit argument +// the corresponded line edit, set focus in it and unpress other button if it was pressed +//================================================================================= +void MeasureGUI_AnnotationDlg::SetEditCurrentArgument() +{ + QPushButton* aSelectButton = ( QPushButton* ) sender(); + + activateSelectionArgument( aSelectButton ); + + SelectionIntoArgument(); +} + +//================================================================================= +// function : activateSelectionArgument() +// purpose : it stores as current edit argument the corresponded line edit, +// sets the focus on it and unpresses other button if it was pressed +//================================================================================= +void MeasureGUI_AnnotationDlg::activateSelectionArgument +( + QPushButton* theSelectionButton ) { + QPushButton* anOtherButton = 0; + if ( theSelectionButton == myShapeSelBtn ) { + myEditCurrentArgument = myShapeName; + anOtherButton = mySubShapeSelBtn; + // throw down current sub-shape selection + TopAbs_ShapeEnum aShapeType = TopAbs_SHAPE; + + mySubShapeTypeCombo->setCurrentIndex( 0 ); + mySubShapeName->setText( "" ); + + myAnnotationProperties.ShapeType = aShapeType; + myAnnotationProperties.ShapeIndex = -1; + + mySelectionMode = aShapeType; + + updateSubShapeEnableState(); + } else if ( theSelectionButton == mySubShapeSelBtn ) { + myEditCurrentArgument = mySubShapeName; + anOtherButton = myShapeSelBtn; + } else + myEditCurrentArgument = 0; + + if ( myEditCurrentArgument ) + myEditCurrentArgument->setFocus(); + + theSelectionButton->setDown( true ); + anOtherButton->setDown( false ); +} + +//================================================================================= +// function : SelectionIntoArgument() +// purpose : Called when selection has changed. Sets the current selection in the +// annotation property and redisplays presentation +//================================================================================= +void MeasureGUI_AnnotationDlg::SelectionIntoArgument() +{ + if ( myIsCreation && myEditCurrentArgument ) + { + myEditCurrentArgument->setText( "" ); + + GEOM::GeomObjPtr anObj = getSelected( mySelectionMode ); + + bool hasAttachPoint = false; + gp_Pnt anAttachPoint( 0, 0, 0 ); + int aSubShapeIndex = -1; + if ( myEditCurrentArgument == myShapeName ) { // Selection of a shape is active + if ( anObj->_is_nil() || mySelectionMode != TopAbs_SHAPE ) { + myShape = GEOM::GEOM_Object::_nil(); + } else { + myShape = anObj; + QString aName = GEOMBase::GetName( anObj.get() ); + myEditCurrentArgument->setText( aName ); + if ( !myShapeNameModified ) { + myTextEdit->setText( aName ); + onTextChange(); + // modified state should not be changed as modification was performed not manually + myShapeNameModified = false; + } + } + + bool aNullShape = myShape->_is_nil(); + mySubShapeTypeCombo->setEnabled( !aNullShape ); + updateSubShapeEnableState(); + + activateSelection(); + + if ( !aNullShape ) { + + TopoDS_Shape aShape; + GEOMBase::GetShape( myShape.get(), aShape ); + + hasAttachPoint = getPickedPoint( anAttachPoint, aShape ); + if ( !hasAttachPoint ) { + + anAttachPoint = getAttachPoint( aShape, hasAttachPoint ); + } + } + } else if ( myEditCurrentArgument == mySubShapeName ) { + if ( !myShape->_is_nil() ) { + + if ( anObj->_is_nil() ) { + myEditCurrentArgument->setText( QString() ); + } + else { + + QString aName = GEOMBase::GetName( anObj.get() ); + myEditCurrentArgument->setText( aName ); + + TopTools_IndexedMapOfShape aMainMap; + TopoDS_Shape aMainShape; + TopoDS_Shape aSubShape; + GEOMBase::GetShape( myShape.get(), aMainShape ); + GEOMBase::GetShape( anObj.get(), aSubShape ); + TopExp::MapShapes( aMainShape, getShapeType(), aMainMap ); + + if ( aMainMap.Contains( aSubShape ) ) { + aSubShapeIndex = aMainMap.FindIndex( aSubShape ); + } + + if ( !aSubShape.IsNull() ) { + + TopoDS_Shape aShape; + GEOMBase::GetShape( myShape.get(), aShape ); + + hasAttachPoint = getPickedPoint( anAttachPoint, aSubShape ); + if ( !hasAttachPoint ) { + + anAttachPoint = getAttachPoint( aSubShape, hasAttachPoint ); + } + } + } + } + myAnnotationProperties.ShapeIndex = aSubShapeIndex; + } + + gp_Trsf aToShapeLCS; + if ( !myShape->_is_nil() ) { + + TopoDS_Shape aShape; + GEOMBase::GetShape( myShape.get(), aShape ); + gp_Ax3 aShapeLCS = gp_Ax3().Transformed( aShape.Location().Transformation() ); + aToShapeLCS.SetTransformation( gp_Ax3(), aShapeLCS ); + } + + myAnnotationProperties.Attach = anAttachPoint.Transformed( aToShapeLCS ); + + if ( hasAttachPoint && !myIsPositionDefined ) { + + gp_Pnt aPosition = getDefaultPosition( anAttachPoint ); + + myAnnotationProperties.Position = ( !myAnnotationProperties.IsScreenFixed ) ? + aPosition.Transformed( aToShapeLCS ) : aPosition; + + myIsPositionDefined = true; + } + else if ( !hasAttachPoint ) { + + myIsPositionDefined = false; + } + } + redisplayPreview(); +} + +//======================================================================= +//function : closeEvent +//purpose : +//======================================================================= +void MeasureGUI_AnnotationDlg::closeEvent( QCloseEvent* theEv ) +{ + if ( myInteractor ) { + myInteractor->Disable(); + } + GEOMBase_Skeleton::closeEvent( theEv ); +} + +//======================================================================= +//function : onTextChange +//purpose : change annotation text +//======================================================================= +void MeasureGUI_AnnotationDlg::onTextChange() +{ + myAnnotationProperties.Text = myTextEdit->text(); + if ( !myShapeNameModified ) + myShapeNameModified = true; + redisplayPreview(); +} + +//======================================================================= +//function : onTypeChange +//purpose : change annotation type: 2D or 3D +//======================================================================= +void MeasureGUI_AnnotationDlg::onTypeChange() +{ + const bool isScreenFixedBefore = myAnnotationProperties.IsScreenFixed; + + myAnnotationProperties.IsScreenFixed = myIsScreenFixed->isChecked(); + + // convert point position from screen space to 3D space + if ( myIsPositionDefined ) { + + SUIT_ViewWindow* anActiveView = GEOMBase_Helper::getActiveView(); + OCCViewer_ViewWindow* anOccView = NULL; + if ( anActiveView ) { + + anOccView = qobject_cast( anActiveView ); + } + + if ( anOccView ) { + + TopoDS_Shape aShape; + GEOMBase::GetShape( myShape.get(), aShape ); + const gp_Ax3 aShapeLCS = gp_Ax3().Transformed( aShape.Location().Transformation() ); + + gp_Trsf aToShapeLCS, aFrShapeLCS; + aFrShapeLCS.SetTransformation( aShapeLCS, gp_Ax3() ); + aToShapeLCS.SetTransformation( gp_Ax3(), aShapeLCS ); + + const Handle(V3d_View) aView3d = anOccView->getViewPort()->getView(); + const gp_Pnt aPosition = myAnnotationProperties.Position; + const gp_Pnt aAttach3d = myAnnotationProperties.Attach.Transformed( aFrShapeLCS ); + if ( !isScreenFixedBefore ) { + + gp_Pnt aPosition3d = aPosition.Transformed( aFrShapeLCS ); + gp_Pnt aPosition2d = GEOM_Annotation::ConvertPosition2d( aPosition3d, aAttach3d, aView3d ); + myAnnotationProperties.Position = aPosition2d; + } + else { + + gp_Pnt aPosition3d = GEOM_Annotation::ConvertPosition3d( aPosition, aAttach3d, aView3d ); + aPosition3d = aPosition3d.Transformed( aToShapeLCS ); + myAnnotationProperties.Position = aPosition3d; + } + } + } + + redisplayPreview(); +} + +//======================================================================= +//function : onSubShapeTypeChange +//purpose : +//======================================================================= +void MeasureGUI_AnnotationDlg::onSubShapeTypeChange() +{ + const TopAbs_ShapeEnum aShapeType = getShapeType(); + + activateSelectionArgument( aShapeType == TopAbs_SHAPE ? myShapeSelBtn : mySubShapeSelBtn ); + + myAnnotationProperties.ShapeType = aShapeType; + + if ( aShapeType != mySelectionMode ) { + mySubShapeName->setText( "" ); + myAnnotationProperties.ShapeIndex = -1; + mySelectionMode = aShapeType; + } + + updateSubShapeEnableState(); + + activateSelection(); + redisplayPreview(); +} + +//================================================================================= +// function : onDragged +// purpose : +//================================================================================= +void MeasureGUI_AnnotationDlg::onDragged( Handle_GEOM_Annotation theAnnotation ) +{ + TopoDS_Shape aShape; + GEOMBase::GetShape( myShape.get(), aShape ); + gp_Ax3 aShapeLCS = gp_Ax3().Transformed( aShape.Location().Transformation() ); + gp_Trsf aToShapeLCS; + aToShapeLCS.SetTransformation( gp_Ax3(), aShapeLCS ); + + if ( !myAnnotationProperties.IsScreenFixed ) { + myAnnotationProperties.Position = theAnnotation->GetPosition().Transformed( aToShapeLCS ); + + if ( !myIsCreation ) { + myGeomGUI->GetAnnotationMgr()->storeFixedPosition( myEditAnnotationEntry, 0 ); + } + } + else { + myAnnotationProperties.Position = theAnnotation->GetPosition(); + } +} + +#define RETURN_WITH_MSG( a, b ) \ + if ( ( a ) ) { \ + theMessage += ( b ); \ + return false; \ + } + +//================================================================================= +// function : createOperation +// purpose : +//================================================================================= +GEOM::GEOM_IOperations_ptr MeasureGUI_AnnotationDlg::createOperation() +{ + return getGeomEngine()->GetILocalOperations( getStudyId() ); +} + +//================================================================================= +// function : isValid() +// purpose : Verify validity of input data +//================================================================================= +bool MeasureGUI_AnnotationDlg::isValid( QString& theMessage ) +{ + SalomeApp_Study* study = getStudy(); + RETURN_WITH_MSG( !study, tr( "GEOM_NO_STUDY" ) ) + RETURN_WITH_MSG( study->studyDS()->GetProperties()->IsLocked(), + tr( "GEOM_STUDY_LOCKED" ) ) + + if ( myIsCreation ) { + RETURN_WITH_MSG( myShape->_is_nil(), tr( "NO_SHAPE" ) ) + } else { + //RETURN_WITH_MSG( CORBA::is_nil( myShape ), tr( "NO_FIELD" ) ) + } + + if ( getShapeType() != TopAbs_SHAPE ) { + if ( myIsCreation ) { + RETURN_WITH_MSG( myAnnotationProperties.ShapeIndex < 0, tr( "NO_SUB_SHAPE" ) ) + } else { + //RETURN_WITH_MSG( CORBA::is_nil( myShape ), tr( "NO_FIELD" ) ) + } + } + + if ( myIsCreation ) { + RETURN_WITH_MSG( !myIsPositionDefined, tr( "NO_POSITION" ) ) + } + + return true; +} + +//================================================================================= +// function : execute +// purpose : +//================================================================================= +bool MeasureGUI_AnnotationDlg::execute() +{ + QString anError; + if ( !isValid( anError ) ) + return false; + + SalomeApp_Study* aStudy = getStudy(); + _PTR(SObject) aSObj = aStudy->studyDS()->FindObjectID( myShape->GetStudyEntry() ); + + Handle(GEOMGUI_AnnotationAttrs) aShapeAnnotations = + GEOMGUI_AnnotationAttrs::FindOrCreateAttributes( aSObj, aStudy ); + + if ( myIsCreation ) { + myAnnotationProperties.IsVisible = true; // initially created annotation is hidden + + aShapeAnnotations->Append( myAnnotationProperties ); + + myGeomGUI->emitAnnotationsUpdated( QString( myShape->GetStudyEntry() ) ); + + erasePreview( true ); + + globalSelection( myGeomGUI->getLocalSelectionMode() , true ); + + myGeomGUI->GetAnnotationMgr()->Display( myShape->GetStudyEntry(), aShapeAnnotations->GetNbAnnotation()-1 ); + } + else { + + aShapeAnnotations->SetProperties( myEditAnnotationIndex, myAnnotationProperties ); + myGeomGUI->emitAnnotationsUpdated( QString( myShape->GetStudyEntry() ) ); + } + return true; +} + +//================================================================================= +// function : buildPrs +// purpose : creates annotation presentation object and corresponded SALOME presentation +//================================================================================= +SALOME_Prs* MeasureGUI_AnnotationDlg::buildPrs() +{ + QString aEntry = myIsCreation ? + myGeomGUI->GetAnnotationMgr()->makeAnnotationEntry( myShape->GetStudyEntry(), - 1 ) : + myGeomGUI->GetAnnotationMgr()->makeAnnotationEntry( myEditAnnotationEntry, myEditAnnotationIndex ); + + SALOME_Prs* aPrs = myGeomGUI->GetAnnotationMgr()->CreatePresentation( + myAnnotationProperties, myShape.get(), 0, aEntry ); + + // set preview style for the created presentation + AIS_ListOfInteractive aIObjects; + ((SOCC_Prs*)aPrs)->GetObjects( aIObjects ); + AIS_ListOfInteractive::Iterator aIOIt( aIObjects ); + for ( ; aIOIt.More(); aIOIt.Next() ) { + + Handle( GEOM_Annotation ) aPresentation = Handle( GEOM_Annotation )::DownCast( aIOIt.Value() ); + aPresentation->SetTextColor( Quantity_NOC_VIOLET ); + aPresentation->SetLineColor( Quantity_NOC_VIOLET ); + aPresentation->SetDepthCulling( Standard_False ); + } + + return aPrs; +} + +//================================================================================= +// function : updateSubShapeEnableState +// purpose : creates annotation presentation object and corresponded SALOME presentation +//================================================================================= +void MeasureGUI_AnnotationDlg::updateSubShapeEnableState() +{ + if ( !myIsCreation ) + return; + + bool isWholeShape = getShapeType() == TopAbs_SHAPE; + bool aNullShape = myShape->_is_nil(); + mySubShapeSelBtn->setEnabled( !aNullShape && !isWholeShape ); + mySubShapeName->setEnabled( !aNullShape && !isWholeShape ); +} + +//================================================================================= +// function : redisplayPreview +// purpose : creates annotation presentation object and corresponded SALOME presentation +//================================================================================= +void MeasureGUI_AnnotationDlg::redisplayPreview() +{ + if ( myIsCreation ) { + + QString aMess; + if ( !isValid( aMess ) ) { + erasePreview( true ); + return; + } + + erasePreview( false ); + + try { + SUIT_OverrideCursor wc; + getDisplayer()->SetToActivate( true ); + + if ( SALOME_Prs* aPrs = buildPrs() ) + displayPreview( aPrs ); + } catch ( const SALOME::SALOME_Exception& e ) { + SalomeApp_Tools::QtCatchCorbaException( e ); + } catch ( ... ) { + } + } + else { + myGeomGUI->GetAnnotationMgr()->Redisplay( myEditAnnotationEntry, myEditAnnotationIndex, + myAnnotationProperties ); + } + + QString anEntry; + if ( myIsCreation && !myShape->_is_nil() ) { + anEntry = myGeomGUI->GetAnnotationMgr()->makeAnnotationEntry( myShape->GetStudyEntry(), -1 ); + } + else if ( !myIsCreation ) { + anEntry = myGeomGUI->GetAnnotationMgr()->makeAnnotationEntry( myEditAnnotationEntry, myEditAnnotationIndex ); + } + + myInteractor->SetEditEntry( anEntry ); +} + +//================================================================================= +// function : getPickedPoint +// purpose : finds picked point in active viewer on the selected shape +//================================================================================= +bool MeasureGUI_AnnotationDlg::getPickedPoint( gp_Pnt& thePnt, const TopoDS_Shape& theShape ) +{ + if ( theShape.ShapeType() == TopAbs_VERTEX ) + { + bool isOk = false; + thePnt = getAttachPoint( theShape, isOk ); + return isOk; + } + + const SUIT_ViewWindow* anActiveView = GEOMBase_Helper::getActiveView(); + if ( !anActiveView ) + return false; + + const OCCViewer_ViewWindow* anOccView = qobject_cast( anActiveView ); + if ( !anOccView || !anOccView->underMouse() ) + return false; + + OCCViewer_ViewManager* aVM = ( OCCViewer_ViewManager* )anOccView->getViewManager(); + OCCViewer_Viewer* aViewer = aVM->getOCCViewer(); + + Handle(AIS_InteractiveContext) anAISContext = aViewer->getAISContext(); + Handle(SelectMgr_ViewerSelector) aSelector; + if ( anAISContext->HasOpenedContext() ) + aSelector = anAISContext->LocalSelector(); + else + aSelector = anAISContext->MainSelector(); + + if ( aSelector->NbPicked() < 1 ) + return false; + + thePnt = aSelector->PickedPoint( 1 ); + return true; +} + +//================================================================================= +// function : getAttachPoint +// purpose : computes default attachment point on the shape +//================================================================================= +gp_Pnt MeasureGUI_AnnotationDlg::getAttachPoint( const TopoDS_Shape& theShape, bool& theIsOk ) +{ + gp_Pnt aPnt( 0.0, 0.0, 0.0 ); + theIsOk = true; + if ( theShape.ShapeType() == TopAbs_COMPSOLID + || theShape.ShapeType() == TopAbs_SOLID + || theShape.ShapeType() == TopAbs_SHELL ) + { + Bnd_Box aBox; + BRepBndLib::Add( theShape, aBox ); + const gp_Pnt aMin = aBox.CornerMin(); + const gp_Pnt aMax = aBox.CornerMax(); + aPnt = gp_Pnt( (aMin.X() + aMax.X()) / 2.0, + (aMin.Y() + aMax.Y()) / 2.0, + (aMin.Z() + aMax.Z()) / 2.0 ); + } + else if ( theShape.ShapeType() == TopAbs_FACE ) + { + BRepAdaptor_Surface aFace( TopoDS::Face( theShape ) ); + const Standard_Real aU1 = aFace.FirstUParameter(); + const Standard_Real aU2 = aFace.LastUParameter(); + const Standard_Real aV1 = aFace.FirstVParameter(); + const Standard_Real aV2 = aFace.LastVParameter(); + aPnt = aFace.Value( ( aU1 + aU2 ) / 2.0, ( aV1 + aV2 ) / 2.0 ); + } + else if ( theShape.ShapeType() == TopAbs_WIRE ) + { + BRepAdaptor_CompCurve aWire( TopoDS::Wire( theShape ) ); + const Standard_Real aP1 = aWire.FirstParameter(); + const Standard_Real aP2 = aWire.LastParameter(); + aPnt = aWire.Value( ( aP1 + aP2 ) / 2.0 ); + } + else if ( theShape.ShapeType() == TopAbs_EDGE ) + { + BRepAdaptor_Curve aEdge( TopoDS::Edge( theShape ) ); + const Standard_Real aP1 = aEdge.FirstParameter(); + const Standard_Real aP2 = aEdge.LastParameter(); + aPnt = aEdge.Value( ( aP1 + aP2 ) / 2.0 ); + } + else if ( theShape.ShapeType() == TopAbs_VERTEX ) + { + aPnt = BRep_Tool::Pnt( TopoDS::Vertex( theShape ) ); + } + else + { + theIsOk = false; + } + + return aPnt; +} + +//================================================================================= +// function : getDefaultPosition +// purpose : computes default position for the given attachment point +//================================================================================= +gp_Pnt MeasureGUI_AnnotationDlg::getDefaultPosition( const gp_Pnt& theAttach ) +{ + SUIT_ViewWindow* anActiveView = GEOMBase_Helper::getActiveView(); + if ( !anActiveView ) { + + return myAnnotationProperties.IsScreenFixed ? gp::Origin() : theAttach; + } + + OCCViewer_ViewWindow* anOccView = qobject_cast( anActiveView ); + if ( !anOccView ) { + + return myAnnotationProperties.IsScreenFixed ? gp::Origin() : theAttach; + } + + OCCViewer_ViewPort3d* aViewPort = anOccView->getViewPort(); + + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + + const QFont aFont = aResMgr->fontValue( "Geometry", "shape_annotation_font", QFont( "Y14.5M-2009", 24 ) ); + + const Handle(V3d_View) aView3d = aViewPort->getView(); + + const Standard_Real aFontHeight =( aFont.pixelSize() != -1 ) ? aFont.pixelSize() : aFont.pointSize(); + + return GEOM_Annotation::GetDefaultPosition( myAnnotationProperties.IsScreenFixed, + theAttach, aFontHeight * 1.5, aView3d ); +} diff --git a/src/MeasureGUI/MeasureGUI_AnnotationDlg.h b/src/MeasureGUI/MeasureGUI_AnnotationDlg.h new file mode 100755 index 000000000..75ef0dafe --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_AnnotationDlg.h @@ -0,0 +1,129 @@ +// Copyright (C) 2007-2016 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, or (at your option) any later version. +// +// 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_AnnotationDlg.h + +#ifndef MeasureGUI_AnnotationDlg_H +#define MeasureGUI_AnnotationDlg_H + +#include + +#include +#include +#include + +#include +//#include +//#include +//#include + +//#include +//#include +//#include +//#include + +class QGroupBox; +class QLineEdit; +class QPushButton; +class QComboBox; +class QCheckBox; +class SalomeApp_IntSpinBox; +class MeasureGUI_AnnotationInteractor; + +//================================================================================= +// class : MeasureGUI_AnnotationDlg +// purpose : +//================================================================================= +class MeasureGUI_AnnotationDlg : public GEOMBase_Skeleton +{ + Q_OBJECT + +public: + MeasureGUI_AnnotationDlg ( GeometryGUI* theGeometryGUI, + const bool theIsCreate, + QWidget* parent=0, + bool modal=false, Qt::WindowFlags fl=0 ); + ~MeasureGUI_AnnotationDlg(); + +protected: + // redefined from GEOMBase_Helper + virtual GEOM::GEOM_IOperations_ptr createOperation(); + virtual bool isValid ( QString& ); + virtual bool execute (); + + SALOME_Prs* buildPrs(); + void updateSubShapeEnableState(); + void redisplayPreview(); + + void closeEvent( QCloseEvent* theEv ); + +private slots: + void ClickOnOk(); + bool ClickOnApply(); + void SelectionIntoArgument(); + void SetEditCurrentArgument(); + + void onTextChange(); + void onTypeChange(); + void onSubShapeTypeChange(); + + void onDragged( Handle_GEOM_Annotation theAnnotation ); + +private: + void Init(); + + void activateSelectionArgument( QPushButton* theSelectionButton ); + void activateSelection(); + TopAbs_ShapeEnum getShapeType() const; + + bool getPickedPoint( gp_Pnt& thePnt, const TopoDS_Shape& theShape ); + gp_Pnt getAttachPoint( const TopoDS_Shape& theShape, bool& theIsOk ); + gp_Pnt getDefaultPosition( const gp_Pnt& theAttach ); + +private: + TopAbs_ShapeEnum mySelectionMode; + QString myEditAnnotationEntry; + int myEditAnnotationIndex; + GEOMGUI_AnnotationAttrs::Properties myAnnotationProperties; + bool myIsPositionDefined; + /// an index of edited annotation in the list shape annotations, -1 in create operation + bool myIsCreation; + GEOM::GeomObjPtr myShape; + + QLineEdit* myTextEdit; + + QPushButton* myShapeSelBtn; + // update shape name by shape selection if it has not been manually modified yet + bool myShapeNameModified; + QLineEdit* myShapeName; + QCheckBox* myIsScreenFixed; + + QComboBox* mySubShapeTypeCombo; + + QPushButton* mySubShapeSelBtn; + QLineEdit* mySubShapeName; + + MeasureGUI_AnnotationInteractor* myInteractor; +}; + +#endif diff --git a/src/MeasureGUI/MeasureGUI_AnnotationInteractor.cxx b/src/MeasureGUI/MeasureGUI_AnnotationInteractor.cxx new file mode 100755 index 000000000..2d0cd204a --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_AnnotationInteractor.cxx @@ -0,0 +1,333 @@ +// Copyright (C) 2007-2016 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, or (at your option) any later version. +// +// 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_AnnotationInteractor.cxx +// Author : Anton POLETAEV, Open CASCADE S.A.S. + +#include "MeasureGUI_AnnotationInteractor.h" + +// SALOME includes +#include +#include +#include +#include +#include +#include +#include +#include + +// Qt includes +#include + +// OCCT includes +#include + +//================================================================================= +// function : Constructor +// purpose : +//================================================================================= +MeasureGUI_AnnotationInteractor::MeasureGUI_AnnotationInteractor( GeometryGUI* theGUI, + QObject* theParent ) +: QObject( theParent ), + myGeomGUI( theGUI ), + myIsEnabled( false ), + myVM( NULL ), + myViewer( NULL ), + myActiveViewPort( NULL ) +{ +} + +//================================================================================= +// function : Deactivate +// purpose : +//================================================================================= +MeasureGUI_AnnotationInteractor::~MeasureGUI_AnnotationInteractor() +{ + if ( myActiveViewPort ) + { + myActiveViewPort->releaseMouse(); + myActiveViewPort = NULL; + } + + Disable(); +} + +//================================================================================= +// function : Enable +// purpose : Enables event processing and interaction handlers. +//================================================================================= +void MeasureGUI_AnnotationInteractor::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 aViews = myVM->getViews(); + QVector::iterator aViewIt = aViews.begin(); + for ( ; aViewIt != aViews.end(); ++aViewIt ) + { + ConnectView( *aViewIt ); + } +} + +//================================================================================= +// function : Disable +// purpose : Disables event processing and interaction handlers. +//================================================================================= +void MeasureGUI_AnnotationInteractor::Disable() +{ + if ( !myIsEnabled ) + { + return; + } + + myIsEnabled = false; + + // remove event filtering from viewer windows + QVector aViews = myVM->getViews(); + QVector::iterator aViewIt = aViews.begin(); + for ( ; aViewIt != aViews.end(); ++aViewIt ) + { + DisconnectView( *aViewIt ); + } + + if ( myActiveViewPort ) + { + myActiveViewPort->releaseMouse(); + myActiveViewPort = NULL; + } + + if ( !myActiveIO.IsNull() ) + { + emit SignalInteractionFinished( myActiveIO ); + myActiveIO.Nullify(); + } +} + +//================================================================================= +// function : ConnectView +// purpose : Connect interactor's event handler to the view window given. +//================================================================================= +void MeasureGUI_AnnotationInteractor::ConnectView( SUIT_ViewWindow* theView ) +{ + ( (OCCViewer_ViewWindow*) theView )->getViewPort()->installEventFilter( this ); +} + +//================================================================================= +// function : DisconnectView +// purpose : Disconnect interactor's event handler from the view window given. +//================================================================================= +void MeasureGUI_AnnotationInteractor::DisconnectView( SUIT_ViewWindow* theView ) +{ + ( (OCCViewer_ViewWindow*) theView )->getViewPort()->removeEventFilter( this ); +} + +//================================================================================= +// function : OnViewCreated +// purpose : Handler for signal coming from GUI layer. +//================================================================================= +void MeasureGUI_AnnotationInteractor::OnViewCreated( SUIT_ViewWindow* theView ) +{ + ConnectView( theView ); +} + +//================================================================================= +// function : OnViewRemoved +// purpose : Handler for signal coming from GUI layer. +//================================================================================= +void MeasureGUI_AnnotationInteractor::OnViewRemoved( SUIT_ViewWindow* theView ) +{ + DisconnectView( theView ); +} + +//================================================================================= +// function : eventFilter +// purpose : Hooks and process events from OCCT viewer prior to their coming into the base viewer class. +//================================================================================= +bool MeasureGUI_AnnotationInteractor::eventFilter( QObject* theObject, QEvent* theEvent ) +{ + OCCViewer_ViewPort3d* aViewPort = (OCCViewer_ViewPort3d*)theObject; + + const Handle(V3d_View) aView3d = aViewPort->getView(); + + switch( theEvent->type() ) + { + // ------------------------------------------------------------------------ + // Start dragging ("grab") event + // ------------------------------------------------------------------------ + case QEvent::MouseButtonPress : + { + QMouseEvent* aMouseEv = dynamic_cast( theEvent ); + + if ( myEditEntry.isEmpty() ) + { + return false; + } + + if ( !( aMouseEv->buttons() & Qt::LeftButton ) ) + { + return false; + } + + const Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext(); + + anAISContext->MoveTo( aMouseEv->x(), aMouseEv->y(), aView3d ); + + if ( !anAISContext->HasDetected() ) + { + return false; + } + + const Handle(SelectMgr_EntityOwner) aDetected = anAISContext->DetectedOwner(); + + if( aDetected.IsNull() ) + { + return false; + } + + const Handle(GEOM_Annotation) aAnnotation = + Handle(GEOM_Annotation)::DownCast( aDetected->Selectable() ); + + if ( aAnnotation.IsNull() ) + { + return false; + } + + const Handle(SALOME_InteractiveObject) anIO = + Handle(SALOME_InteractiveObject)::DownCast( aAnnotation->GetOwner() ); + + if ( anIO.IsNull() || anIO->getEntry() != myEditEntry ) + { + return false; + } + + myStartPoint = aMouseEv->pos(); + mySelection.Clear(); + + for ( anAISContext->InitSelected(); anAISContext->MoreSelected(); anAISContext->NextSelected() ) + { + mySelection.Append( anAISContext->SelectedOwner() ); + } + + anAISContext->ClearSelected( Standard_False ); + anAISContext->Unhilight( myActiveIO, Standard_True ); + + myActiveViewPort = aViewPort; + myActiveViewPort->grabMouse(); + myActiveIO = aAnnotation; + myActiveIO->BeginDrag(); + + emit SignalInteractionStarted( myActiveIO ); + + return true; + } + + // ------------------------------------------------------------------------ + // Perform dragging operation + // ------------------------------------------------------------------------ + case QEvent::MouseMove : + { + QMouseEvent* aMouseEv = (QMouseEvent*) theEvent; + + if ( !myActiveIO.IsNull() ) + { + const Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext(); + + if ( anAISContext->IsHilighted( myActiveIO ) ) + { + anAISContext->Unhilight( myActiveIO, Standard_False ); + } + + const QPoint aDelta = aMouseEv->pos() - myStartPoint; + myActiveIO->Drag( aDelta.x(), (-aDelta.y()), aView3d ); + anAISContext->Update( myActiveIO, Standard_False ); + anAISContext->UpdateCurrentViewer(); + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Stop dragging operation + // ------------------------------------------------------------------------ + case QEvent::FocusOut : + case QEvent::MouseButtonRelease : + { + QMouseEvent* aMouseEv = (QMouseEvent*) theEvent; + + if ( myActiveViewPort ) + { + myActiveViewPort->releaseMouse(); + myActiveViewPort = NULL; + } + if ( !myActiveIO.IsNull() ) + { + myActiveIO->EndDrag(); + + const Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext(); + + anAISContext->ClearSelected( Standard_False ); + SelectMgr_SequenceOfOwner::Iterator anIt( mySelection ); + for( ; anIt.More(); anIt.Next() ) + { + anAISContext->AddOrRemoveSelected( anIt.Value(), Standard_False ); + } + + anAISContext->Update( myActiveIO, Standard_False ); + anAISContext->UpdateCurrentViewer(); + anAISContext->MoveTo( aMouseEv->pos().x(), aMouseEv->pos().y(), aView3d ); + + emit SignalInteractionFinished( myActiveIO ); + + mySelection.Clear(); + myActiveIO.Nullify(); + return (theEvent->type() == QEvent::MouseButtonRelease); + } + + return false; + } + + default: return false; + } +} diff --git a/src/MeasureGUI/MeasureGUI_AnnotationInteractor.h b/src/MeasureGUI/MeasureGUI_AnnotationInteractor.h new file mode 100755 index 000000000..21875cc48 --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_AnnotationInteractor.h @@ -0,0 +1,122 @@ +// Copyright (C) 2007-2016 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, or (at your option) any later version. +// +// 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_AnnotationInteractor.h +// Author : Anton POLETAEV, Open CASCADE S.A.S. +// +#ifndef MEASUREGUI_ANNOTATIONINTERACTOR_H +#define MEASUREGUI_ANNOTATIONINTERACTOR_H + +#include +#include +#include +#include +#include + +class GeometryGUI; +class OCCViewer_Viewer; +class OCCViewer_ViewManager; +class OCCViewer_ViewPort3d; +class SUIT_ViewWindow; + +/*! + * \class MeasureGUI_AnnotationInteractor + * \brief Class implementing logical layer for interactive dragging of annotation + * labels. It includes two components: listener for GUI events occuring + * inside of OCCT 3D viewer and processor for hooked events to perform + * interactive modification of the selected annotation within current + * AIS context. + */ +class MeasureGUI_AnnotationInteractor : public QObject +{ + Q_OBJECT + +public: + + //! Constructor. + //! Connects to existing viewer/view windows to process events. + //! \param theGUI [in] the geometry module's GUI interface. + //! \param theOwner [in] the owner of the instance. + MeasureGUI_AnnotationInteractor( GeometryGUI* theGUI, QObject* theOwner ); + + //! Destructor. + virtual ~MeasureGUI_AnnotationInteractor(); + +public: + + //! Enables event processing and interaction handlers. + void Enable(); + + //! Disables event processing and interaction handlers. + void Disable(); + + //! Set entry of allowed annotation presentations. + void SetEditEntry( const QString& theEntry ) { myEditEntry = theEntry; } + +protected: + + //! Connect interactor's event handler to the view window given. + void ConnectView( SUIT_ViewWindow* theWindow ); + + //! Disconnect interactor's event handler from the view window given. + void DisconnectView( SUIT_ViewWindow* theWindow ); + +signals: + + //! Emitted when interactor begins modification of the interactive object. + void SignalInteractionStarted( Handle_GEOM_Annotation theIO ); + + //! Emitted when interactor finished modification of the interactive object. + void SignalInteractionFinished( Handle_GEOM_Annotation theIO ); + +protected slots: + + //! Handler for signal coming from GUI layer. + void OnViewCreated( SUIT_ViewWindow* ); + + //! Handler for signal coming from GUI layer. + void OnViewRemoved( SUIT_ViewWindow* ); + +protected: + + //! Hooks and process events from OCCT viewer prior to their coming into the base viewer class. + //! It handles the events coming to viewport and identifies whether the events can + //! invoke an interaction operation or not. If yes, the operation is performed within the + //! interactor class and events are "accepted". Otherwise, the events are passed to + //! viewer's subroutines. + virtual bool eventFilter( QObject*, QEvent* ); + +private: + + GeometryGUI* myGeomGUI; + bool myIsEnabled; + OCCViewer_ViewManager* myVM; + OCCViewer_Viewer* myViewer; + OCCViewer_ViewPort3d* myActiveViewPort; + Handle(GEOM_Annotation) myActiveIO; + SelectMgr_SequenceOfOwner mySelection; + QPoint myStartPoint; + QString myEditEntry; +}; + +#endif diff --git a/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.cxx b/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.cxx index b0e199d3d..fa53c1aa0 100644 --- a/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.cxx +++ b/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.cxx @@ -228,9 +228,9 @@ void MeasureGUI_ManageDimensionsDlg::StartSelection( const Selection theSelectio myDimensionInteractor->Enable(); connect( myDimensionInteractor, - SIGNAL( InteractionFinished( Handle(AIS_InteractiveObject) ) ), + SIGNAL( InteractionFinished( Handle_AIS_InteractiveObject ) ), this, - SLOT( OnInteractionFinished( Handle(AIS_InteractiveObject) ) ) ); + SLOT( OnInteractionFinished( Handle_AIS_InteractiveObject ) ) ); anAISContext->UpdateCurrentViewer(); } @@ -290,9 +290,9 @@ void MeasureGUI_ManageDimensionsDlg::StopSelection() myDimensionInteractor->Disable(); disconnect( myDimensionInteractor, - SIGNAL( InteractionFinished( Handle(AIS_InteractiveObject) ) ), + SIGNAL( InteractionFinished( Handle_AIS_InteractiveObject ) ), this, - SLOT( OnInteractionFinished( Handle(AIS_InteractiveObject) ) ) ); + SLOT( OnInteractionFinished( Handle_AIS_InteractiveObject ) ) ); } myCurrentSelection = Selection_None; @@ -628,7 +628,7 @@ void MeasureGUI_ManageDimensionsDlg::OnHideAll() // function : OnInteractionFinished // purpose : //================================================================================= -void MeasureGUI_ManageDimensionsDlg::OnInteractionFinished( Handle(AIS_InteractiveObject) theIO ) +void MeasureGUI_ManageDimensionsDlg::OnInteractionFinished( Handle_AIS_InteractiveObject theIO ) { // update property data SalomeApp_Application* anApp = myGeomGUI->getApp(); diff --git a/src/OBJECT/CMakeLists.txt b/src/OBJECT/CMakeLists.txt index 900552cb6..2bc3e3f81 100755 --- a/src/OBJECT/CMakeLists.txt +++ b/src/OBJECT/CMakeLists.txt @@ -76,6 +76,7 @@ SET(OBJECT_HEADERS GEOM_DeviceActor.h GEOM_Constants.h GEOM_AISDimension.hxx + GEOM_Annotation.hxx ) # --- sources --- @@ -93,6 +94,7 @@ SET(OBJECT_SOURCES GEOM_DeviceActor.cxx GEOM_Constants.cxx GEOM_AISDimension.cxx + GEOM_Annotation.cxx ) # --- rules --- diff --git a/src/OBJECT/GEOM_Annotation.cxx b/src/OBJECT/GEOM_Annotation.cxx new file mode 100755 index 000000000..1d966bb3d --- /dev/null +++ b/src/OBJECT/GEOM_Annotation.cxx @@ -0,0 +1,943 @@ +// Copyright (C) 2007-2016 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, or (at your option) any later version. +// +// 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_Annotation.hxx +// Module : GEOM +// +#include + +// OCCT includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +IMPLEMENT_STANDARD_RTTIEXT( GEOM_Annotation, AIS_InteractiveObject ) + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= +GEOM_Annotation::GEOM_Annotation() : AIS_InteractiveObject() +{ + SetPosition( gp_Pnt( 0.0, 0.0, 0.0 ) ); + SetIsScreenFixed( Standard_False ); + SetAttachPoint( gp_Pnt( 0.0, 0.0, 0.0 ) ); + SetDisplayMode( 0 ); + SetZLayer( Graphic3d_ZLayerId_Default ); + SetAutoHide( Standard_True ); + SetHilightMode( HighlightAll ); + SetMutable( Standard_True ); + SetDepthCulling( Standard_True ); + + Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect(); + aTextAspect->SetHeight( 20.0 ); + aTextAspect->SetColor( Quantity_Color( 1.0, 1.0, 1.0, Quantity_TOC_RGB ) ); + myDrawer->SetTextAspect( aTextAspect ); + + Handle(Prs3d_LineAspect) aLineAspect = + new Prs3d_LineAspect( Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0 ); + myDrawer->SetLineAspect( aLineAspect ); + + Handle(Prs3d_LineAspect) aHiddenLineAspect = + new Prs3d_LineAspect( Quantity_NOC_WHITE, Aspect_TOL_DOT, 1.0 ); + myDrawer->SetHiddenLineAspect( aHiddenLineAspect ); + + Handle(Prs3d_PointAspect) aPointAspect = + new Prs3d_PointAspect( Aspect_TOM_POINT, Quantity_NOC_WHITE, 4.0 ); + myDrawer->SetPointAspect( aPointAspect ); +} + +// ======================================================================= +// function : SetText +// purpose : +// ======================================================================= +void GEOM_Annotation::SetText( const TCollection_ExtendedString& theText ) +{ + if (myText != theText) + { + SetToUpdate(); + } + + myText = theText; +} + +// ======================================================================= +// function : SetPosition +// purpose : +// ======================================================================= +void GEOM_Annotation::SetPosition( const gp_Pnt& thePosition ) +{ + SetPosition( thePosition, Standard_True ); +} + +// ======================================================================= +// function : SetPosition +// purpose : +// ======================================================================= +void GEOM_Annotation::SetPosition( const gp_Pnt& thePosition, const Standard_Boolean theUpdateSelection ) +{ + myPosition = thePosition; + + if ( !myIsScreenFixed ) + { + Handle(Graphic3d_TransformPers) aPersistence = + new Graphic3d_TransformPers( Graphic3d_TMF_ZoomRotatePers, thePosition ); + + AIS_InteractiveObject::SetTransformPersistence( aPersistence ); + } + + SetToUpdate(); + + if( theUpdateSelection ) + { + UpdateSelection(); + } +} + +// ======================================================================= +// function : SetIsScreenFixed +// purpose : +// ======================================================================= +void GEOM_Annotation::SetIsScreenFixed( const Standard_Boolean theIsFixed ) +{ + myIsScreenFixed = theIsFixed; + + Handle(Graphic3d_TransformPers) aPersistence; + + if (!myIsScreenFixed) + { + aPersistence = new Graphic3d_TransformPers( Graphic3d_TMF_ZoomRotatePers, myPosition ); + } + else + { + aPersistence = new Graphic3d_TransformPers( Graphic3d_TMF_2d, Aspect_TOTP_CENTER ); + } + + AIS_InteractiveObject::SetTransformPersistence( aPersistence ); + + SetZLayer( myIsScreenFixed ? Graphic3d_ZLayerId_Topmost : Graphic3d_ZLayerId_Default ); + + SetToUpdate(); + + UpdateSelection(); +} + +// ======================================================================= +// function : Set2dPosition +// purpose : +// ======================================================================= +void GEOM_Annotation::Set2dPosition( const Handle(V3d_View)& theView ) +{ + if ( myIsScreenFixed ) + { + return; + } + + gp_Pnt aPosition2d = ConvertPosition2d( myPosition, myAttach, theView ); + + SetIsScreenFixed( Standard_True ); + + SetPosition( aPosition2d ); +} + +// ======================================================================= +// function : Set3dPosition +// purpose : +// ======================================================================= +void GEOM_Annotation::Set3dPosition( const Handle(V3d_View)& theView ) +{ + if ( !myIsScreenFixed ) + { + return; + } + + gp_Pnt aPosition3d = ConvertPosition3d( myPosition, myAttach, theView ); + + SetIsScreenFixed( Standard_False ); + + SetPosition( aPosition3d ); +} + +// ======================================================================= +// function : SetAttachPoint +// purpose : +// ======================================================================= +void GEOM_Annotation::SetAttachPoint( const gp_Pnt& thePoint ) +{ + myAttach = thePoint; +} + +// ======================================================================= +// function : SetHilightShape +// purpose : Sets shape (annotated shape) that will be used for hilighting. +// ======================================================================= +void GEOM_Annotation::SetHilightShape( const TopoDS_Shape& theShape ) +{ + if ( myShape.IsEqual( theShape ) ) + { + return; + } + + myShape = theShape; + SetToUpdate(); + UpdateSelection(); +} + +// ======================================================================= +// function : SetColor +// purpose : +// ======================================================================= +void GEOM_Annotation::SetColor( const Quantity_Color& theColor ) +{ + SetTextColor( theColor ); + SetLineColor( theColor ); +} + +// ======================================================================= +// function : SetTextColor +// purpose : +// ======================================================================= +void GEOM_Annotation::SetTextColor( const Quantity_Color& theColor ) +{ + myDrawer->TextAspect()->SetColor( theColor ); + + SetToUpdate(); +} + +// ======================================================================= +// function : SetLineColor +// purpose : +// ======================================================================= +void GEOM_Annotation::SetLineColor( const Quantity_Color& theColor ) +{ + myDrawer->LineAspect()->SetColor( theColor ); + myDrawer->HiddenLineAspect()->SetColor( theColor ); + myDrawer->PointAspect()->SetColor( theColor ); + + SetToUpdate(); +} + +// ======================================================================= +// function : SetLineWidth +// purpose : +// ======================================================================= +void GEOM_Annotation::SetLineWidth( const Standard_Real theLineWidth ) +{ + if ( GetLineWidth() != theLineWidth ) + { + myDrawer->LineAspect()->SetWidth( theLineWidth ); + myDrawer->HiddenLineAspect()->SetWidth( theLineWidth ); + + SetToUpdate(); + } +} + +// ======================================================================= +// function : SetLineStyle +// purpose : +// ======================================================================= +void GEOM_Annotation::SetLineStyle( const Aspect_TypeOfLine theStyle ) +{ + if ( GetLineStyle() != theStyle ) + { + myDrawer->LineAspect()->SetTypeOfLine( theStyle ); + + SetToUpdate(); + } +} + +// ======================================================================= +// function : SetHiddenLineStyle +// purpose : +// ======================================================================= +void GEOM_Annotation::SetHiddenLineStyle( const Aspect_TypeOfLine theStyle ) +{ + if ( GetHiddenLineStyle() != theStyle ) + { + myDrawer->HiddenLineAspect()->SetTypeOfLine( theStyle ); + + SetToUpdate(); + } +} + +// ======================================================================= +// function : SetTextHeight +// purpose : +// ======================================================================= +void GEOM_Annotation::SetTextHeight( const Standard_Real theHeight ) +{ + if ( GetTextHeight() != theHeight ) + { + myDrawer->TextAspect()->SetHeight( theHeight ); + + SetToUpdate(); + } +} + +// ======================================================================= +// function : SetFontAspect +// purpose : +// ======================================================================= +void GEOM_Annotation::SetFontAspect( const Font_FontAspect theFontAspect ) +{ + if ( GetFontAspect() != theFontAspect ) + { + myDrawer->TextAspect()->Aspect()->SetTextFontAspect( theFontAspect ); + + SetToUpdate(); + } +} + +// ======================================================================= +// function : SetFont +// purpose : +// ======================================================================= +void GEOM_Annotation::SetFont( const TCollection_AsciiString& theFont ) +{ + if ( GetFont() != theFont ) + { + myDrawer->TextAspect()->Aspect()->SetFont( theFont ); + + SetToUpdate(); + } +} + +// ======================================================================= +// function : SetDepthCulling +// purpose : +// ======================================================================= +void GEOM_Annotation::SetDepthCulling( const Standard_Boolean theToEnable ) +{ + if ( GetDepthCulling() != theToEnable ) + { + myIsDepthCulling = theToEnable; + + SetToUpdate(); + } +} + +// ======================================================================= +// function : SetDefaultZLayer +// purpose : +// ======================================================================= +void GEOM_Annotation::SetDefaultZLayer() +{ + SetZLayer( myIsScreenFixed ? Graphic3d_ZLayerId_Topmost : Graphic3d_ZLayerId_Default ); + + SetToUpdate(); +} + +// ======================================================================= +// function : GetDefaultPosition +// purpose : +// ======================================================================= +gp_Pnt GEOM_Annotation::GetDefaultPosition( const Standard_Boolean theIsScreenFixed, + const gp_Pnt& theAttachPnt, + const Standard_Real theOffset, + const Handle(V3d_View)& theView ) +{ + Standard_Integer aWinWidth = 0; + Standard_Integer aWinHeight = 0; + theView->Window()->Size( aWinWidth, aWinHeight ); + + gp_Pnt aPositionProj = theView->Camera()->Project( theAttachPnt ); + aPositionProj.SetX( (aPositionProj.X() / 2.) * aWinWidth + theOffset ); + aPositionProj.SetY( (aPositionProj.Y() / 2.) * aWinHeight + theOffset ); + aPositionProj.SetZ( 0.0 ); + + if ( theIsScreenFixed ) + { + return aPositionProj; + } + + gp_Pnt aAttachProj = theView->Camera()->Project ( theAttachPnt ); + gp_Pnt aPosition3d = theView->Camera()->UnProject ( gp_Pnt ( aPositionProj.X() / aWinWidth * 2., + aPositionProj.Y() / aWinHeight * 2., + aAttachProj.Z() )); + + return aPosition3d; +} + +// ======================================================================= +// function : ConvertPosition2d +// purpose : +// ======================================================================= +gp_Pnt GEOM_Annotation::ConvertPosition2d( const gp_Pnt& thePosition, + const gp_Pnt& /*theAttach*/, + const Handle(V3d_View)& theView ) +{ + Standard_Integer aWinWidth = 0; + Standard_Integer aWinHeight = 0; + theView->Window()->Size( aWinWidth, aWinHeight ); + + gp_Pnt aPositionProj = theView->Camera()->Project( thePosition ); + aPositionProj.SetX( (aPositionProj.X() / 2.) * aWinWidth ); + aPositionProj.SetY( (aPositionProj.Y() / 2.) * aWinHeight ); + aPositionProj.SetZ( 0.0 ); + return aPositionProj; +} + +// ======================================================================= +// function : ConvertPosition3d +// purpose : +// ======================================================================= +gp_Pnt GEOM_Annotation::ConvertPosition3d( const gp_Pnt& thePosition, + const gp_Pnt& theAttach, + const Handle(V3d_View)& theView ) +{ + Standard_Integer aWinWidth = 0; + Standard_Integer aWinHeight = 0; + theView->Window()->Size( aWinWidth, aWinHeight ); + + gp_Pnt aAttachProj = theView->Camera()->Project( theAttach ); + gp_Pnt aPosition3d = theView->Camera()->UnProject( + gp_Pnt ( thePosition.X() / aWinWidth * 2., thePosition.Y() / aWinHeight * 2., aAttachProj.Z() ) ); + + return aPosition3d; +} + +// ======================================================================= +// function : Compute +// purpose : +// ======================================================================= +void GEOM_Annotation::Compute( const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/, + const Handle(Prs3d_Presentation)& thePresentation, + const Standard_Integer theMode ) +{ + thePresentation->Clear(); + + if (theMode < 0) + { + return; + } + + Handle(OpenGl_Group) aGroup = Handle(OpenGl_Group)::DownCast( Prs3d_Root::NewGroup( thePresentation ) ); + if (aGroup.IsNull()) + { + return; + } + + Handle(Prs3d_TextAspect) anAsp = myDrawer->TextAspect(); + NCollection_String aUtfText( myText.ToExtString() ); + OpenGl_Annotation* aAnnotationDraw = + new OpenGl_Annotation( this, static_cast( anAsp->Height() ), aGroup->GlStruct()->GlDriver() ); + + aAnnotationDraw->SetDepthMode( 0 ); + aGroup->SetGroupPrimitivesAspect( myDrawer->TextAspect()->Aspect() ); + aGroup->SetGroupPrimitivesAspect( myDrawer->LineAspect()->Aspect() ); + aGroup->SetGroupPrimitivesAspect( myDrawer->PointAspect()->Aspect() ); + aGroup->AddElement( aAnnotationDraw ); + + if ( !myIsDepthCulling ) + { + OpenGl_Annotation* aAnnotationDraw = + new OpenGl_Annotation( this, static_cast( anAsp->Height() ), aGroup->GlStruct()->GlDriver() ); + + aAnnotationDraw->SetDepthMode( GL_GREATER ); + aGroup->SetPrimitivesAspect( myDrawer->TextAspect()->Aspect() ); + aGroup->SetPrimitivesAspect( myDrawer->HiddenLineAspect()->Aspect() ); + aGroup->SetPrimitivesAspect( myDrawer->PointAspect()->Aspect() ); + aGroup->AddElement( aAnnotationDraw ); + } + + Bnd_Box aBox = TextBoundingBox(); + if ( myIsScreenFixed ) + { + gp_Trsf aOffset2d; + aOffset2d.SetTranslation( gp_Vec( myPosition.X(), myPosition.Y(), 0.0 ) ); + aBox = aBox.Transformed( aOffset2d ); + } + + const gp_Pnt aBoxMin = aBox.CornerMin(); + const gp_Pnt aBoxMax = aBox.CornerMax(); + aGroup->ChangeBoundingBox() = Graphic3d_BndBox4f ( + Graphic3d_Vec4( static_cast( aBoxMin.X() ), + static_cast( aBoxMin.Y() ), + static_cast( aBoxMin.Z() ), 1.0F ), + Graphic3d_Vec4( static_cast( aBoxMax.X() ), + static_cast( aBoxMax.Y() ), + static_cast( aBoxMax.Z() ), 1.0F ) ); +} + +// ======================================================================= +// function : ComputeSelection +// purpose : +// ======================================================================= +void GEOM_Annotation::ComputeSelection( const Handle(SelectMgr_Selection)& theSelection, + const Standard_Integer theMode ) +{ + if (theMode != GlobalSelectionMode()) + { + return; + } + + theSelection->Clear(); + + Bnd_Box aBox = TextBoundingBox(); + if ( myIsScreenFixed ) + { + gp_Trsf aOffset2d; + aOffset2d.SetTranslation( gp_Vec( myPosition.X(), myPosition.Y(), 0.0 ) ); + aBox = aBox.Transformed( aOffset2d ); + } + + const Handle(GEOM_AnnotationOwner) anEntityOwner = new GEOM_AnnotationOwner( myShape, this, 10 ); + const Handle(GEOM_AnnotationSensEntity) aSensitive = + new GEOM_AnnotationSensEntity( anEntityOwner, aBox, myIsDepthCulling ); + + theSelection->Add( aSensitive ); +} + +// ======================================================================= +// function : TextBoundingBox +// purpose : +// ======================================================================= +Bnd_Box GEOM_Annotation::TextBoundingBox() const +{ + Handle(Prs3d_TextAspect) anAsp = myDrawer->TextAspect(); + Font_FTFont aFont; + unsigned int aResolution = GetContext()->CurrentViewer()->DefaultRenderingParams().Resolution; + if ( aFont.Init( anAsp->Aspect()->Font().ToCString(), + anAsp->Aspect()->GetTextFontAspect(), + (unsigned int)anAsp->Height(), + aResolution ) ) + { + const NCollection_String aText( (Standard_Utf16Char* )myText.ToExtString() ); + const Font_Rect aFontRect = aFont.BoundingBox( aText, Graphic3d_HTA_CENTER, Graphic3d_VTA_CENTER ); + Bnd_Box aBox; + aBox.Add( gp_Pnt( aFontRect.Left, aFontRect.Bottom, 0.0 ) ); + aBox.Add( gp_Pnt( aFontRect.Right, aFontRect.Top, 0.0 ) ); + return aBox; + } + + return Bnd_Box(); +} + +// ======================================================================= +// function : BeginDrag +// purpose : +// ======================================================================= +void GEOM_Annotation::BeginDrag() +{ + myStartPosition = myPosition; +} + +// ======================================================================= +// function : Drag +// purpose : +// ======================================================================= +void GEOM_Annotation::Drag( const Standard_Integer theDx, + const Standard_Integer theDy, + const Handle(V3d_View)& theView ) +{ + if (myIsScreenFixed) + { + SetPosition( myStartPosition.Translated( gp_Vec( theDx, theDy, 0.0 ) ), Standard_False ); + } + else + { + Standard_Integer aWidth, aHeight; + theView->Window()->Size( aWidth, aHeight ); + gp_Pnt aNormalized = theView->Camera()->Project( myStartPosition ); + gp_Pnt aNormalizedDrag = + aNormalized.Translated( gp_Vec( static_cast(theDx) * 2.0 / aWidth, + static_cast(theDy) * 2.0 / aHeight, + 0.0 ) ); + + SetPosition( theView->Camera()->UnProject( aNormalizedDrag ), Standard_False ); + } +} + +// ======================================================================= +// function : EndDrag +// purpose : +// ======================================================================= +void GEOM_Annotation::EndDrag() +{ + UpdateSelection(); +} + +// ======================================================================= +// function : UndoDrag +// purpose : +// ======================================================================= +void GEOM_Annotation::UndoDrag() +{ + SetPosition( myStartPosition, Standard_True ); +} + +// ======================================================================= +// subclass : OpenGl_Annotation +// function : Constructor +// purpose : +// ======================================================================= +GEOM_Annotation::OpenGl_Annotation::OpenGl_Annotation( GEOM_Annotation* theAnnotation, + const Standard_Integer theTextHeight, + const OpenGl_GraphicDriver* theDriver ) +: OpenGl_Element(), + myDepthMode( 0 ), + myAISObject( theAnnotation ), + myText( theAnnotation->myText.ToExtString() ), + myTextLineY( 0.f ), + myTextDPI( 0 ) +{ + // graphical resources for drawing text and underline + myTextParams.Height = theTextHeight; + myTextParams.HAlign = Graphic3d_HTA_CENTER; + myTextParams.VAlign = Graphic3d_VTA_CENTER; + myTextDraw = new OpenGl_Text( myText.ToCString(), OpenGl_Vec3(), myTextParams ); + myTextLineDraw = new OpenGl_PrimitiveArray( theDriver ); + + // graphical resources for drawing extension line and marker + Handle(Graphic3d_ArrayOfSegments) + aExtVertexArray = new Graphic3d_ArrayOfSegments( 2 ); + aExtVertexArray->AddVertex( 0.0, 0.0, 0.0 ); + aExtVertexArray->AddVertex( 0.0, 0.0, 1.0 ); + myExtLineDraw = new OpenGl_PrimitiveArray( theDriver, Graphic3d_TOPA_SEGMENTS, + aExtVertexArray->Indices(), aExtVertexArray->Attributes(), aExtVertexArray->Bounds() ); + + Handle(Graphic3d_ArrayOfPoints) + aExtMakerArray = new Graphic3d_ArrayOfPoints( 1 ); + aExtMakerArray->AddVertex( 0.0, 0.0, 1.0 ); + myExtMarkerDraw = new OpenGl_PrimitiveArray( theDriver, Graphic3d_TOPA_POINTS, + aExtMakerArray->Indices(), aExtMakerArray->Attributes(), aExtMakerArray->Bounds() ); +} + +// ======================================================================= +// subclass : OpenGl_Annotation +// function : Destructor +// purpose : +// ======================================================================= +GEOM_Annotation::OpenGl_Annotation::~OpenGl_Annotation() +{ + Release( NULL ); +} + +// ======================================================================= +// subclass : OpenGl_Annotation +// function : Release +// purpose : Releases GL resources with the given GL context. +// ======================================================================= +void GEOM_Annotation::OpenGl_Annotation::Release( OpenGl_Context* theCtx ) +{ + if (myTextDraw) + { + myTextDraw->Release( theCtx ); + myTextLineDraw->Release( theCtx ); + myExtLineDraw->Release( theCtx ); + myExtMarkerDraw->Release( theCtx ); + } + myTextDraw = NULL; + myTextLineDraw = NULL; + myExtLineDraw = NULL; + myExtMarkerDraw = NULL; +} + +// ======================================================================= +// subclass : OpenGl_Annotation +// function : Render +// purpose : Renders the annotation graphical elements. +// ======================================================================= +void GEOM_Annotation::OpenGl_Annotation::Render( const Handle(OpenGl_Workspace)& theWorkspace ) const +{ + const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext(); + + // --------------------------------------------------------------------- + // initialize text's font and configure some properties when DPI changes + // --------------------------------------------------------------------- + + const unsigned int aDPI = theWorkspace->View()->RenderingParams().Resolution; + if (myTextDPI != aDPI) + { + const OpenGl_AspectText* anAspect = theWorkspace->AspectText(); + + // getting string size will also initialize font library + myTextDraw->StringSize( aContext, + myText, *anAspect, myTextParams, aDPI, + myTextSize.x, myTextSize.a, myTextSize.d ); + + myTextDPI = aDPI; + myTextSize.y = myTextSize.a - myTextSize.d; + switch (myTextParams.HAlign) + { + case Graphic3d_HTA_LEFT: myTextUnderline.x() = 0.f; break; + case Graphic3d_HTA_CENTER: myTextUnderline.x() = -myTextSize.x / 2.f; break; + case Graphic3d_HTA_RIGHT: myTextUnderline.x() = -myTextSize.x; break; + default: + break; + } + switch (myTextParams.VAlign) + { + case Graphic3d_VTA_TOPFIRSTLINE: + case Graphic3d_VTA_TOP: myTextUnderline.y() = -myTextSize.y; break; + case Graphic3d_VTA_CENTER: myTextUnderline.y() = -myTextSize.y / 2.f; break; + case Graphic3d_VTA_BOTTOM: myTextUnderline.y() = myTextSize.d; break; + default: + break; + } + + Handle(Graphic3d_ArrayOfSegments) + aVertexArray = new Graphic3d_ArrayOfSegments( 2 ); + aVertexArray->AddVertex( myTextUnderline.x(), myTextUnderline.y(), 0.0f ); + aVertexArray->AddVertex( myTextUnderline.x() + myTextSize.x, myTextUnderline.y(), 0.0f ); + myTextLineDraw->InitBuffers( aContext, Graphic3d_TOPA_SEGMENTS, + aVertexArray->Indices(), aVertexArray->Attributes(), aVertexArray->Bounds() ); + } + + // --------------------------------------------- + // perform view culling test by attachment point + // --------------------------------------------- + + const OpenGl_Vec4 aAttach( static_cast( myAISObject->myAttach.X() ), + static_cast( myAISObject->myAttach.Y() ), + static_cast( myAISObject->myAttach.Z() ), 1.F ); + + const Handle(Graphic3d_Camera) aCamera = theWorkspace->View()->Camera(); + const OpenGl_Mat4& aCameraProjMat = aCamera->ProjectionMatrixF(); + const OpenGl_Mat4& aCameraViewMat = aCamera->OrientationMatrixF(); + const OpenGl_Vec4 aAttachView = aCameraViewMat * aAttach; + if (myAISObject->myIsAutoHide) + { + const OpenGl_Vec4 aAttachClip = aCameraProjMat * aAttachView; + if (Abs( aAttachClip.x() ) > aAttachClip.w() + || Abs( aAttachClip.y() ) > aAttachClip.w() + || Abs( aAttachClip.z() ) > aAttachClip.w()) + { + return; + } + } + + const bool toHighlight = theWorkspace->ToHighlight(); + + if (toHighlight && myAISObject->myHilightMode == HighlightLabel) + { + theWorkspace->SetHighlight( false ); + theWorkspace->ApplyAspectLine(); + } + + GLint myOldDepthMode = 0; + + if ( myDepthMode ) + { + aContext->core11fwd->glGetIntegerv( GL_DEPTH_FUNC, &myOldDepthMode ); + aContext->core11fwd->glDepthFunc( myDepthMode ); + } + + // ------------------------------------------------------------- + // render text label in current persistence matrix and underline + // ------------------------------------------------------------- + + if ( myAISObject->myIsScreenFixed ) + { + // use text position property instead of matrix setup + // to avoid jittering when dragging text + myTextDraw->SetPosition( OpenGl_Vec3( static_cast( myAISObject->myPosition.X() ), + static_cast( myAISObject->myPosition.Y() ), + static_cast( myAISObject->myPosition.Z() ) ) ); + } + + myTextDraw->Render( theWorkspace ); + + // ------------------------------------------------------------ + // render annotation text's underline + // ------------------------------------------------------------ + + if ( myAISObject->myIsScreenFixed ) + { + // setup local transformation (in 2D persistence reference) + // to represent position of annotation label on screen + const OpenGl_Mat4& aViewMat = aContext->WorldViewState.Current(); + OpenGl_Mat4 aPositionMat; + aPositionMat.SetValue( 0, 3, static_cast( myAISObject->myPosition.X() ) ); + aPositionMat.SetValue( 1, 3, static_cast( myAISObject->myPosition.Y() ) ); + aPositionMat.SetValue( 2, 3, static_cast( myAISObject->myPosition.Z() ) ); + OpenGl_Mat4 aPosViewMat = aViewMat * aPositionMat; + aContext->WorldViewState.Push(); + aContext->WorldViewState.SetCurrent( aPosViewMat ); + aContext->ApplyModelViewMatrix(); + } + + myTextLineDraw->Render( theWorkspace ); + + // ------------------------------------------------------------ + // render dynamic extension line using synthetic transformation + // ------------------------------------------------------------ + + OpenGl_Vec4 aCenter (0.f, 0.f, 0.f, 1.f); + switch (myTextParams.HAlign) + { + case Graphic3d_HTA_LEFT: aCenter.x() = myTextSize.x / 2.f; break; + case Graphic3d_HTA_CENTER: aCenter.x() = 0.f; break; + case Graphic3d_HTA_RIGHT: aCenter.x() = -myTextSize.x / 2.f; break; + default: break; + } + switch (myTextParams.VAlign) + { + case Graphic3d_VTA_TOPFIRSTLINE: + case Graphic3d_VTA_TOP: aCenter.y() = -myTextSize.y / 2.f; break; + case Graphic3d_VTA_CENTER: aCenter.y() = 0.f; break; + case Graphic3d_VTA_BOTTOM: aCenter.y() = myTextSize.y / 2.f; break; + default: break; + } + + // compute label's center in view coordinate space + const OpenGl_Mat4& aViewMat = aContext->WorldViewState.Current(); + const OpenGl_Vec4 aCenterView = aViewMat * aCenter; + + // the value below defines whether the extension line should be hanging + // on the left side of the label or on the right + const bool isLeftHanded = aAttachView.x() < aCenterView.x(); + + // compute extension line point at the text label in view coordinate space + const OpenGl_Vec4 aHingeView = aViewMat * OpenGl_Vec4( + ( isLeftHanded ? myTextUnderline.x() : myTextUnderline.x() + myTextSize.x ), myTextUnderline.y(), 0.0f, 1.0f ); + + // prepare matrix to specify geometry of extension line in view space + // by multiplication of unit z coordinate vector on given matrix. + OpenGl_Mat4 aExtGeometryMat; + aExtGeometryMat.SetColumn( 2, aAttachView - aHingeView ); + aExtGeometryMat.SetColumn( 3, aHingeView ); + + // setup and draw + aContext->ModelWorldState.Push(); + aContext->ModelWorldState.SetIdentity(); + aContext->WorldViewState.Push(); + aContext->WorldViewState.SetCurrent( aExtGeometryMat ); + aContext->ApplyModelViewMatrix(); + + myExtLineDraw->Render( theWorkspace ); + myExtMarkerDraw->Render( theWorkspace ); + + // ------------------------------------------------------------ + // restore original state + // ------------------------------------------------------------ + + aContext->ModelWorldState.Pop(); + aContext->WorldViewState.Pop(); + + if ( myOldDepthMode ) + { + aContext->core11fwd->glDepthFunc( myOldDepthMode ); + } + + if ( myAISObject->myIsScreenFixed ) + { + aContext->WorldViewState.Pop(); + } + + aContext->ApplyModelViewMatrix(); + + if ( toHighlight != theWorkspace->ToHighlight() ) + { + theWorkspace->SetHighlight( toHighlight ); + } +} + +// ======================================================================= +// subclass : GEOM_AnnotationOwner +// function : HilightWithColor +// purpose : Perform highlighting of the presentation. +// ======================================================================= +void GEOM_Annotation::GEOM_AnnotationOwner::HilightWithColor( const Handle(PrsMgr_PresentationManager3d)& thePM, + const Handle(Graphic3d_HighlightStyle)& theStyle, + const Standard_Integer theMode ) +{ + if ( myPrsSh.IsNull() ) + { + Handle(Prs3d_Drawer) aDrawer = new Prs3d_Drawer; + aDrawer->Link( Selectable()->HilightAttributes() ); + + Handle(Prs3d_IsoAspect) aUIsoAspect = new Prs3d_IsoAspect( + aDrawer->UIsoAspect()->Aspect()->Color(), + aDrawer->UIsoAspect()->Aspect()->Type(), + aDrawer->UIsoAspect()->Aspect()->Width(), 0 ); + + Handle(Prs3d_IsoAspect) aVIsoAspect = new Prs3d_IsoAspect( + aDrawer->UIsoAspect()->Aspect()->Color(), + aDrawer->UIsoAspect()->Aspect()->Type(), + aDrawer->UIsoAspect()->Aspect()->Width(), 0 ); + + aDrawer->SetIsoOnPlane( Standard_False ); + aDrawer->SetUIsoAspect( aUIsoAspect ); + aDrawer->SetVIsoAspect( aVIsoAspect ); + myPrsSh = new StdSelect_Shape( myShape, aDrawer ); + } + + myPrsSh->SetZLayer ( Selectable()->ZLayer() ); + + thePM->Color( Selectable(), theStyle, theMode, NULL, Graphic3d_ZLayerId_Topmost ); + + thePM->Color( myPrsSh, theStyle, theMode, Selectable(), Graphic3d_ZLayerId_Topmost ); +} + +// ======================================================================= +// subclass : GEOM_AnnotationOwner +// function : Unhilight +// purpose : Removes highlighting from the type of shape. +// ======================================================================= +void GEOM_Annotation::GEOM_AnnotationOwner::Unhilight ( const Handle(PrsMgr_PresentationManager)& thePM, + const Standard_Integer theMode ) +{ + SelectMgr_EntityOwner::Unhilight( thePM, theMode ); + + thePM->Unhighlight( myPrsSh, theMode ); +} + +// ======================================================================= +// subclass : GEOM_AnnotationOwner +// function : Clear +// purpose : Clears the presentation manager object aPM of all shapes +// with the given selection mode. +// ======================================================================= +void GEOM_Annotation::GEOM_AnnotationOwner::Clear ( const Handle(PrsMgr_PresentationManager)& thePM, + const Standard_Integer theMode ) +{ + SelectMgr_EntityOwner::Clear( thePM, theMode ); + + if ( !myPrsSh.IsNull() ) { + thePM->Clear( myPrsSh, theMode ); + } + + myPrsSh.Nullify(); +} diff --git a/src/OBJECT/GEOM_Annotation.hxx b/src/OBJECT/GEOM_Annotation.hxx new file mode 100755 index 000000000..ac8bf3a2f --- /dev/null +++ b/src/OBJECT/GEOM_Annotation.hxx @@ -0,0 +1,417 @@ +// Copyright (C) 2007-2016 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, or (at your option) any later version. +// +// 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_Annotation.hxx +// Module : GEOM +// +#ifndef GEOM_Annotation_HeaderFile +#define GEOM_Annotation_HeaderFile + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class OpenGl_GraphicDriver; +class OpenGl_PrimitiveArray; +class OpenGl_Text; +class V3d_View; + +/*! + * \class GEOM_Annotation + * \brief Interactive object, representating annotation entity + */ +class GEOM_Annotation : public AIS_InteractiveObject +{ +public: + + DEFINE_STANDARD_RTTIEXT( GEOM_Annotation, AIS_InteractiveObject ) + + //! Enumerates supported highlighting modes. + //! - HighlightAll : all elements of the annotation are highlighted. + //! - HighlightLabel : only annotation label is highlighted. + enum HighlightMode + { + HighlightAll = 0, + HighlightLabel = 1 + }; + +public: + + //! Constructor. + Standard_EXPORT GEOM_Annotation(); + + //! Destructor. + virtual ~GEOM_Annotation() {} + + //! Sets annotation text string. + //! \param theText [in] the string displayed in annotation label. + Standard_EXPORT void SetText( const TCollection_ExtendedString& theText ); + + //! Returns annotation text string. + const TCollection_ExtendedString& GetText() const { return myText; } + + //! Sets position of the annotation text label. + //! \param thePosition [in] the cartesian point defining the position of lower left + //! corner of the text label. When displayed in fixed screen position mode + //! (\sa SetScreenFixed) the position is defined as {x,y} pixel coordinate + //! of window space, otherwise 3D point defined in world's coordinate system + //! is used. + Standard_EXPORT void SetPosition( const gp_Pnt& thePosition ); + + //! Returns position of the annotation text label. + const gp_Pnt& GetPosition() const { return myPosition; } + + //! Sets or disables "2D screen fixed" positioning mode. In this mode the annotation + //! is fixed at predefined pixel location in the window coordinate space. Other mode + //! is "3D screen aligned" positioning, when the label is aligned in plane of the + //! screen, while its position is a 3D point defined in world's coordinate system. + Standard_EXPORT void SetIsScreenFixed( const Standard_Boolean theIsFixed ); + + //! Retuns value of "screen fixed" positioning mode. + Standard_Boolean GetIsScreenFixed() const { return myIsScreenFixed; } + + //! Converts annotation position to screen fixed coordinates and + //! modifies its "2D screen fixed" flag correspondingly. + //! @param theView [in] the view to perform projection of coordinates. + Standard_EXPORT void Set2dPosition( const Handle(V3d_View)& theView ); + + //! Converts annotation position from screen fixed coordinates + //! to 3D position and modifies its "2D screen fixed" flag + //! correspondingly. + //! @param theView [in] the view to perform projection of coordinates. + Standard_EXPORT void Set3dPosition( const Handle(V3d_View)& theView ); + + //! Sets attachment point of extension line. + //! \param thePoint [in] the 3D cartesian point defined in world's coordinate system + //! (a point on annotated geometry). + Standard_EXPORT void SetAttachPoint( const gp_Pnt& thePoint ); + + //! Returns attachment point of extension line. + const gp_Pnt& GetAttachPoint() const { return myAttach; } + + //! Sets shape (annotated shape) that will be used for hilighting. + Standard_EXPORT void SetHilightShape( const TopoDS_Shape& theShape ); + + //! Returns the hilighting shape. + const TopoDS_Shape HilightShape() const { return myShape; } + +public: + + //! Sets color for the presentation. + Standard_EXPORT virtual void SetColor( const Quantity_Color& theColor ) Standard_OVERRIDE; + + //! Sets text color. + Standard_EXPORT void SetTextColor( const Quantity_Color& theColor ); + + //! Returns color for the text's label. + Quantity_Color GetTextColor() const { return myDrawer->TextAspect()->Aspect()->Color(); } + + //! Sets line's color. + Standard_EXPORT void SetLineColor( const Quantity_Color& theColor); + + //! Returns color for the connection line. + Quantity_Color GetLineColor() const { return myDrawer->LineAspect()->Aspect()->Color(); } + + //! Sets line width to be used for drawing the annotation's extension line and underline. + Standard_EXPORT void SetLineWidth( const Standard_Real theLineWidth ); + + //! Returns line width for drawing the annotation's extension line and underline. + Standard_Real GetLineWidth() const { return myDrawer->LineAspect()->Aspect()->Width(); } + + //! Sets style of connection line. + Standard_EXPORT void SetLineStyle( const Aspect_TypeOfLine theStyle ); + + //! Retusn style of connection line. + Aspect_TypeOfLine GetLineStyle() const { return myDrawer->LineAspect()->Aspect()->Type(); } + + //! Sets style of hidden connection line. + Standard_EXPORT void SetHiddenLineStyle( const Aspect_TypeOfLine theStyle ); + + //! Retusn style of hidden connection line. + Aspect_TypeOfLine GetHiddenLineStyle() const { return myDrawer->HiddenLineAspect()->Aspect()->Type(); } + + //! Sets text height in pixels. + Standard_EXPORT void SetTextHeight( const Standard_Real theHeight ); + + //! Returns text's height in pixels. + Standard_Real GetTextHeight() const { return myDrawer->TextAspect()->Height(); } + + //! Sets font aspect for label. + Standard_EXPORT void SetFontAspect( const Font_FontAspect theFontAspect ); + + //! Returns label's font aspect. + Font_FontAspect GetFontAspect() const { return myDrawer->TextAspect()->Aspect()->GetTextFontAspect(); } + + //! Sets font used for drawing the label. + Standard_EXPORT void SetFont( const TCollection_AsciiString& theFont ); + + //! Returns font used for drawing the label. + TCollection_AsciiString GetFont() const { return myDrawer->TextAspect()->Aspect()->Font(); } + + //! Sets annotation auto-hiding option. + //! \param theIsEnable [in] the option flag. If passed true, the annotation + //! will be automatically hidden in the view if the attachment point + //! goes outside of the view. + void SetAutoHide( const Standard_Boolean theIsEnable ) { myIsAutoHide = theIsEnable; } + + //! Returns current state of the auto-hiding option. + Standard_Boolean GetAutoHide() const { return myIsAutoHide; } + + //! Sets highlight mode used for display of presentation. + //! \param theMode [in] the one of the supported highlight modes. + void SetHighlightMode( const HighlightMode theMode ) { myHilightMode = theMode; } + + //! Returns highlight mode + HighlightMode GetHilightMode() const { return myHilightMode; } + + //! Sets special flag that allows disabling depth testing when rendering + //! the graphical presentation. When disable the hidden parts such as + //! lines and text become visible and a rendered with another drawing + //! aspect. This mode should be explicitly used with setting top layer + //! for the presentation. Otherwise the behavior is undefined. + Standard_EXPORT void SetDepthCulling( const Standard_Boolean theToEnable ); + + //! Returns depth culling state. + Standard_Boolean GetDepthCulling() const { return myIsDepthCulling; } + +// Helper tools: +public: + + //! Restores default z-layer for this presentation. + Standard_EXPORT void SetDefaultZLayer(); + + //! Returns default position for placing annotation when its attachment point + //! has been determined. + //! @param theIsScreenFixed [in] the state of annotation's "2D screen fixed" mode. + //! @param theAttachPnt [in] the attachment point. + //! @param theOffset [in] the offset value for placing the position relative to attachment.s + //! @param theView [in] the view for projecting coordinates. + Standard_EXPORT static gp_Pnt GetDefaultPosition( const Standard_Boolean theIsScreenFixed, + const gp_Pnt& theAttachPnt, + const Standard_Real theOffset, + const Handle(V3d_View)& theView ); + + //! Converts 3d position to 2d on screen point. + //! @param thePosition [in] the 3d position. + //! @param theAttach [in] the attachment point. + //! @param theView [in] the view for projecting coordinates. + Standard_EXPORT static gp_Pnt ConvertPosition2d( const gp_Pnt& thePosition, + const gp_Pnt& theAttach, + const Handle(V3d_View)& theView ); + + //! Converts 2d position to 3d point. + //! @param thePosition [in] the 2d position. + //! @param theAttach [in] the attachment point. + //! @param theView [in] the view for projecting coordinates. + Standard_EXPORT static gp_Pnt ConvertPosition3d( const gp_Pnt& thePosition, + const gp_Pnt& theAttach, + const Handle(V3d_View)& theView ); + +// Interactive dragging: +public: + + //! Prepares necessary data to perform dragging. + Standard_EXPORT void BeginDrag(); + + //! Drags annotation presentation in the screen plane using the given pixel delta. + //! \param theDx, theDy [in] the drag offset in pixels (from beginning of dragging). + //! \param theView [in] the current view for evaluating drag with 3D position mode. + Standard_EXPORT void Drag( const Standard_Integer theDx, + const Standard_Integer theDy, + const Handle(V3d_View)& theView ); + + //! Perform necessary update when dragging is finished. + Standard_EXPORT void EndDrag(); + + //! Perform necessary update when dragging need undo. + Standard_EXPORT void UndoDrag(); + +private: + + virtual void Compute( const Handle(PrsMgr_PresentationManager3d)& thePresentationManager, + const Handle(Prs3d_Presentation)& thePresentation, + const Standard_Integer theMode = 0 ) Standard_OVERRIDE; + + virtual void ComputeSelection( const Handle(SelectMgr_Selection)& theSelection, + const Standard_Integer theMode ) Standard_OVERRIDE; + + virtual void setLocalTransformation( const Handle(Geom_Transformation)& /*theTransformation*/ ) Standard_OVERRIDE {} + + virtual void SetTransformPersistence( const Handle(Graphic3d_TransformPers)& /*theTrsfPers*/ ) Standard_OVERRIDE {} + + Bnd_Box TextBoundingBox() const; + + void SetPosition( const gp_Pnt& thePosition, const Standard_Boolean theUpdateSelection ); + +private: + + gp_Pnt myAttach; //!< Attachment point of extension line. + gp_Pnt myPosition; //!< Position of text label. + gp_Pnt myStartPosition; //!< Position before starting dragging operation. + Standard_Boolean myIsScreenFixed; //!< Flag indicating whether "screen fixed" positioning mode is turned on or off. + Standard_Boolean myIsAutoHide; //!< Flag indicating whether "auto-hiding" option is turned on. + Standard_Boolean myIsDepthCulling; //!< Flag indiciating whether the "depth culling" is turned on. + HighlightMode myHilightMode; //!< Highlight mode for presentation. + TCollection_ExtendedString myText; //!< Text string of the label presentation. + TopoDS_Shape myShape; //!< Hilighting shape. + +private: + + //! Custom element implementing dynamic rendering of 3D annotation + //! and invoking dynamic callback in presentation class. + class OpenGl_Annotation : public OpenGl_Element + { + public: + + //! Constructor. Some of the input properties are assigned by reference for dynamic draw + //! (it is not likely that GL element will ever outlive the interactive object). + //! \param theAnnotation [in] the instance of interactive presentation class. + //! \param theTextHeight [in] the height of the text label. + //! \param theDriver [in] the instance of graphical driver required for initialization. + OpenGl_Annotation( GEOM_Annotation* theAnnotation, + const Standard_Integer theTextHeight, + const OpenGl_GraphicDriver* theDriver ); + + //! Destructor. Releases GL resources with NULL context. + virtual ~OpenGl_Annotation(); + + //! Releases GL resources with the given GL context. + virtual void Release( OpenGl_Context* theCtx ) Standard_OVERRIDE; + + //! Renders the annotation graphical elements. + virtual void Render( const Handle(OpenGl_Workspace)& theWorkspace ) const Standard_OVERRIDE; + + void SetDepthMode( const int theMode ) { myDepthMode = theMode; } + + private: + + struct TextSize { + float x; // width + float y; // height + float a; // ascent + float d; // descent + }; + + GEOM_Annotation* myAISObject; //!< Instance of presentation class. + NCollection_String myText; //!< Text string of annotation label. + OpenGl_TextParam myTextParams; //!< Text draw parameters. + OpenGl_Text* myTextDraw; //!< Text draw element. + OpenGl_PrimitiveArray* myTextLineDraw; //!< Text underline draw element. + OpenGl_PrimitiveArray* myExtLineDraw; //!< Extension line draw element. + OpenGl_PrimitiveArray* myExtMarkerDraw; //!< Extension marker draw element. + int myDepthMode; //!< Depth mode for drawing hidden line presentation. + mutable float myTextLineY; //!< Text's underlines relative position. + mutable TextSize myTextSize; //!< Text's size parameters + mutable Graphic3d_Vec2 myTextUnderline; //!< Text's underline position. + mutable unsigned int myTextDPI; //!< Text's DPI scale used for last rendering. + }; + + friend class OpenGl_Annotation; // allow opengl element to get private data and invoke callback methods + +public: + + //! Custom entity owner implementing correct highlight for topmost mode. + class GEOM_AnnotationOwner : public SelectMgr_EntityOwner + { + public: + + //! Constructor. + GEOM_AnnotationOwner( const TopoDS_Shape& theShape, + const Handle(SelectMgr_SelectableObject)& theSelectable, + const Standard_Integer thePriority ) + : SelectMgr_EntityOwner( theSelectable, thePriority ), + myShape( theShape ) {} + + //! Perform highlighting of the presentation. + //! \param thePresentationMgr [in] the presentation manager. + //! \param theColor [in] the highlighting color. + //! \param theMode [in] the display mode. + virtual void + HilightWithColor( const Handle(PrsMgr_PresentationManager3d)& thePM, + const Handle(Graphic3d_HighlightStyle)& theStyle, + const Standard_Integer theMode = 0 ) Standard_OVERRIDE; + + //! Removes highlighting from the type of shape. + virtual void + Unhilight ( const Handle(PrsMgr_PresentationManager)& thePM, + const Standard_Integer theMode = 0 ) Standard_OVERRIDE; + + //! Clears the presentation manager object aPM of all shapes + //! with the given selection mode. + virtual void + Clear ( const Handle(PrsMgr_PresentationManager)& thePM, + const Standard_Integer theMode = 0 ) Standard_OVERRIDE; + + private: + + TopoDS_Shape myShape; + Handle(StdSelect_Shape) myPrsSh; + }; + + //! Custom sensitive entity with implementing option to support selection + //! with depth culling flag turned off. + class GEOM_AnnotationSensEntity : public Select3D_SensitiveBox + { + public: + + //! Constructor. + GEOM_AnnotationSensEntity( const Handle(SelectMgr_EntityOwner)& theOwner, + const Bnd_Box& theBox, + const Standard_Boolean theIsDepthCulling ) + : Select3D_SensitiveBox( theOwner, theBox ), + myIsDepthCulling( theIsDepthCulling ) {} + + //! Checks whether the box overlaps current selecting volume. + virtual Standard_Boolean Matches( SelectBasics_SelectingVolumeManager& theMgr, + SelectBasics_PickResult& thePickResult ) Standard_OVERRIDE + { + const Standard_Boolean isMatches = Select3D_SensitiveBox::Matches( theMgr, thePickResult ); + if ( !myIsDepthCulling ) + { + thePickResult = SelectBasics_PickResult( -DBL_MAX, thePickResult.DistToGeomCenter() ); + } + return isMatches; + } + + private: + + Standard_Boolean myIsDepthCulling; + }; +}; + +DEFINE_STANDARD_HANDLE( GEOM_Annotation, AIS_InteractiveObject ) + +#endif diff --git a/src/OBJECT/GEOM_Constants.cxx b/src/OBJECT/GEOM_Constants.cxx index 17b91bade..957753d48 100644 --- a/src/OBJECT/GEOM_Constants.cxx +++ b/src/OBJECT/GEOM_Constants.cxx @@ -104,7 +104,9 @@ namespace GEOM // texture "Texture", // - // dimensions - "Dimensions" // - + "Dimensions", // - + // shape annotations + "ShapeAnnotations" // - }; return ( type >= GEOM::Visibility && type <= GEOM::LastProperty ) ? names[type] : QString(); } diff --git a/src/OBJECT/GEOM_Constants.h b/src/OBJECT/GEOM_Constants.h index 873f6b2a5..de6c72909 100644 --- a/src/OBJECT/GEOM_Constants.h +++ b/src/OBJECT/GEOM_Constants.h @@ -58,7 +58,8 @@ namespace GEOM OutlineColor, Texture, Dimensions, - LastProperty = Dimensions, + ShapeAnnotations, + LastProperty = ShapeAnnotations, }; GEOM_OBJECT_EXPORT double minDeflection(); -- 2.39.2