1 // Copyright (C) 2016-2019 CEA/DEN, EDF R&D, OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File : MeasureGUI_AnnotationDlg.cxx
22 #include "MeasureGUI.h"
23 #include "MeasureGUI_AnnotationDlg.h"
24 #include "MeasureGUI_AnnotationInteractor.h"
28 #include <GEOMBase_Skeleton.h>
29 #include <GEOM_Displayer.h>
30 #include <GeometryGUI.h>
31 #include <GEOMGUI_AnnotationMgr.h>
32 #include <GEOMGUI_TextTreeWdg.h>
35 #include <SOCC_ViewModel.h>
37 #include <SalomeApp_Application.h>
38 #include <SalomeApp_Study.h>
39 #include <SalomeApp_Tools.h>
40 #include <SalomeApp_IntSpinBox.h>
41 #include <SalomeApp_DoubleSpinBox.h>
43 #include <LightApp_SelectionMgr.h>
45 #include <OCCViewer_ViewModel.h>
46 #include <OCCViewer_ViewManager.h>
47 #include <OCCViewer_ViewWindow.h>
48 #include <OCCViewer_ViewPort3d.h>
49 #include <SVTK_ViewModel.h>
50 #include <SALOME_Prs.h>
51 #include <SALOME_ListIO.hxx>
53 #include <SUIT_Desktop.h>
54 #include <SUIT_MessageBox.h>
55 #include <SUIT_OverrideCursor.h>
56 #include <SUIT_ResourceMgr.h>
57 #include <SUIT_Session.h>
58 #include <SUIT_ViewWindow.h>
59 #include <SUIT_ViewManager.h>
62 #include <QGridLayout>
64 #include <QHeaderView>
65 #include <QInputDialog>
68 #include <QPushButton>
70 #include <QTableWidget>
71 #include <QVBoxLayout>
73 #include <AIS_InteractiveContext.hxx>
74 #include <AIS_ListOfInteractive.hxx>
75 #include <AIS_ListIteratorOfListOfInteractive.hxx>
77 #include <Bnd_Box.hxx>
78 #include <BRepAdaptor_CompCurve.hxx>
79 #include <BRepAdaptor_Curve.hxx>
80 #include <BRepAdaptor_Surface.hxx>
81 #include <BRepBndLib.hxx>
82 #include <BRep_Tool.hxx>
84 #include <SelectMgr_ViewerSelector.hxx>
88 #include <TopExp_Explorer.hxx>
89 #include <TopTools_IndexedMapOfShape.hxx>
90 #include <TColStd_IndexedMapOfInteger.hxx>
91 #include <TColStd_MapOfInteger.hxx>
92 #include <TColStd_DataMapIteratorOfDataMapOfIntegerInteger.hxx>
94 #include <NCollection_Handle.hxx>
98 #include <SALOMEDS_wrap.hxx>
99 #include <GEOMImpl_Types.hxx>
105 //=======================================================================
106 //function : MeasureGUI_AnnotationDlg
108 //=======================================================================
110 MeasureGUI_AnnotationDlg::MeasureGUI_AnnotationDlg( GeometryGUI* theGeometryGUI, const bool theIsCreate,
111 QWidget* parent, bool modal, Qt::WindowFlags fl )
112 : GEOMBase_Skeleton( theGeometryGUI, parent, modal, fl ),
113 myIsCreation( theIsCreate ), myShapeNameModified( false )
115 myEditCurrentArgument = 0;
117 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
118 QPixmap iconSelect( resMgr->loadPixmap( "GEOM", tr( "ICON_SELECT" ) ) );
120 setWindowTitle( myIsCreation ? tr( "CREATE_ANNOTATION_TITLE" ) : tr( "EDIT_ANNOTATION_TITLE" ) );
122 // Shape type button group
123 mainFrame()->GroupBoxName->hide();
124 mainFrame()->GroupConstructors->hide();
127 QGroupBox* propGroup = new QGroupBox( tr( "ANNOTATION_PROPERTIES" ), centralWidget() );
128 QGridLayout* propLayout = new QGridLayout( propGroup );
129 propLayout->setMargin( 9 );
130 propLayout->setSpacing( 6 );
132 QLabel* textLabel = new QLabel( tr( "ANNOTATION_TEXT" ), propGroup );
133 myTextEdit = new QLineEdit( propGroup );
134 propLayout->addWidget( textLabel, 0, 0 );
135 propLayout->addWidget( myTextEdit, 0, 1, 1, 2 );
138 QLabel* shapeLabel = new QLabel( tr( "ANNOTATION_SHAPE" ), propGroup );
139 myShapeSelBtn = new QPushButton( propGroup );
140 myShapeSelBtn->setIcon( iconSelect );
141 myShapeSelBtn->setEnabled( myIsCreation );
142 myShapeName = new QLineEdit( propGroup );
143 myShapeName->setReadOnly( true );
144 myShapeName->setEnabled( myIsCreation );
147 myIsScreenFixed = new QCheckBox( tr( "ANNOTATION_IS_SCREEN_FIXED" ), propGroup );
148 myIsScreenFixed->setChecked( false ); // 3D, not fixed
150 propLayout->addWidget( shapeLabel, 1, 0 );
151 propLayout->addWidget( myShapeSelBtn, 1, 1 );
152 propLayout->addWidget( myShapeName, 1, 2 );
153 propLayout->addWidget( myIsScreenFixed, 2, 0, 1, 3 );
154 propLayout->setColumnStretch( 2, 5 );
156 QLabel* shapeTypeLabel = new QLabel( tr( "ANNOTATION_SUB_SHAPE" ), propGroup );
157 mySubShapeTypeCombo = new QComboBox( propGroup );
158 mySubShapeTypeCombo->setEnabled( myIsCreation );
159 mySubShapeTypeCombo->addItem( tr( "WHOLE_SHAPE" ), TopAbs_SHAPE );
160 mySubShapeTypeCombo->addItem( tr( "GEOM_VERTEX" ), TopAbs_VERTEX );
161 mySubShapeTypeCombo->addItem( tr( "GEOM_EDGE" ), TopAbs_EDGE );
162 mySubShapeTypeCombo->addItem( tr( "GEOM_FACE" ), TopAbs_FACE );
163 mySubShapeTypeCombo->addItem( tr( "GEOM_SOLID" ), TopAbs_SOLID );
164 mySubShapeTypeCombo->setCurrentIndex( 0 ); // SHAPE
166 propLayout->addWidget( shapeTypeLabel, 3, 0 );
167 propLayout->addWidget( mySubShapeTypeCombo, 3, 1, 1, 2 );
170 mySubShapeSelBtn = new QPushButton( propGroup );
171 mySubShapeSelBtn->setIcon( iconSelect );
172 mySubShapeSelBtn->setEnabled( myIsCreation );
173 mySubShapeName = new QLineEdit( propGroup );
174 mySubShapeName->setReadOnly( true );
175 mySubShapeName->setEnabled( myIsCreation );
177 propLayout->addWidget( mySubShapeSelBtn, 4, 1 );
178 propLayout->addWidget( mySubShapeName, 4, 2 );
180 QVBoxLayout* layout = new QVBoxLayout( centralWidget() );
181 layout->setMargin( 0 );
182 layout->setSpacing( 6 );
183 layout->addWidget( propGroup );
185 setHelpFileName( "annotation_page.html" );
187 LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
188 connect( aSelMgr, SIGNAL( currentSelectionChanged() ), this,
189 SLOT( SelectionIntoArgument() ) );
190 connect( buttonOk(), SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) );
191 connect( buttonApply(), SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) );
193 myInteractor = new MeasureGUI_AnnotationInteractor( theGeometryGUI, parent );
194 myInteractor->Enable();
196 connect( myInteractor, SIGNAL( SignalInteractionFinished( Handle_GEOM_Annotation ) ),
197 this, SLOT( onDragged( Handle_GEOM_Annotation ) ) );
202 //=======================================================================
203 //function : ~MeasureGUI_AnnotationDlg
205 //=======================================================================
207 MeasureGUI_AnnotationDlg::~MeasureGUI_AnnotationDlg() {
210 //=================================================================================
212 // purpose : fills annotation properties with default values( in create mode ) or
213 // the values of modified object
214 //=================================================================================
215 void MeasureGUI_AnnotationDlg::Init()
217 if ( myIsCreation ) {
219 // default presentation values
220 myIsPositionDefined = false;
221 myAnnotationProperties.Text = tr( "ANNOTATION_PREFIX" );
222 myAnnotationProperties.IsVisible = false;
223 myAnnotationProperties.IsScreenFixed = false;
224 myAnnotationProperties.Attach = gp_Pnt( 0, 0, 0 );
225 myAnnotationProperties.ShapeIndex = -1;
226 myAnnotationProperties.ShapeType = ( int ) TopAbs_SHAPE;
228 // update internal controls and fields following to default values
229 activateSelectionArgument( myShapeSelBtn );
231 myTextEdit->setText( myAnnotationProperties.Text );
232 myShapeNameModified = false;
233 myIsScreenFixed->setChecked( myAnnotationProperties.IsScreenFixed );
235 int aSubShapeTypeIndex = -1;
236 int aTypesCount = mySubShapeTypeCombo->count();
237 for ( int i = 0; i < aTypesCount && aSubShapeTypeIndex < 0; i++ ) {
238 int aType = mySubShapeTypeCombo->itemData( i ).toInt();
239 if ( aType == myAnnotationProperties.ShapeType )
240 aSubShapeTypeIndex = i;
242 mySubShapeTypeCombo->setCurrentIndex( aSubShapeTypeIndex );
244 mySelectionMode = ( TopAbs_ShapeEnum ) myAnnotationProperties.ShapeType;
245 SelectionIntoArgument();
246 updateSubShapeEnableState();
249 connect( myShapeSelBtn, SIGNAL( clicked() ), this,
250 SLOT( SetEditCurrentArgument() ) );
251 connect( mySubShapeSelBtn, SIGNAL( clicked() ), this,
252 SLOT( SetEditCurrentArgument() ) );
254 connect( myTextEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChange() ) );
255 connect( myIsScreenFixed, SIGNAL( clicked( bool ) ), this, SLOT( onTypeChange() ) );
256 connect( mySubShapeTypeCombo, SIGNAL( currentIndexChanged( int ) ),
257 this, SLOT( onSubShapeTypeChange() ) );
259 //SelectionIntoArgument();
263 myIsPositionDefined = true;
264 mySelectionMode = TopAbs_SHAPE;
266 GEOMGUI_TextTreeWdg* aTextTreeWdg = myGeomGUI->GetTextTreeWdg();
267 // text tree widget should be not empty
268 QMap<QString, QList<int> > anAnnotations;
269 aTextTreeWdg->getSelected( anAnnotations );
270 // there is only one annotation selected when edit is started
271 QMap<QString, QList<int> >::const_iterator anIt = anAnnotations.begin();
272 myEditAnnotationEntry = anIt.key();
273 myEditAnnotationIndex = anIt.value()[0];
275 SalomeApp_Study* aStudy = getStudy();
276 _PTR(SObject) aSObj = aStudy->studyDS()->FindObjectID( myEditAnnotationEntry.toStdString() );
277 const Handle(GEOMGUI_AnnotationAttrs) aShapeAnnotations = GEOMGUI_AnnotationAttrs::FindAttributes( aSObj );
278 if ( !aShapeAnnotations.IsNull() ) {
279 aShapeAnnotations->GetProperties( myEditAnnotationIndex, myAnnotationProperties );
281 myShape = GEOM::GEOM_Object::_narrow( GeometryGUI::ClientSObjectToObject(aSObj) );
284 /// fill dialog controls
285 myTextEdit->setText( myAnnotationProperties.Text );
286 myShapeNameModified = false;
287 myIsScreenFixed->setChecked( myAnnotationProperties.IsScreenFixed );
289 int aSubShapeTypeIndex = -1;
290 int aTypesCount = mySubShapeTypeCombo->count();
291 for ( int i = 0; i < aTypesCount && aSubShapeTypeIndex < 0; i++ ) {
292 int aType = mySubShapeTypeCombo->itemData( i ).toInt();
293 if ( aType == myAnnotationProperties.ShapeType )
294 aSubShapeTypeIndex = i;
296 mySubShapeTypeCombo->setCurrentIndex( aSubShapeTypeIndex );
298 QString aShapeName = "";
299 _PTR(GenericAttribute) anAttr;
300 if ( aSObj && aSObj->FindAttribute( anAttr, "AttributeName") ) {
301 _PTR(AttributeName) aNameAttr( anAttr );
303 aShapeName = aNameAttr->Value().c_str();
305 myShapeName->setText( aShapeName );
307 QString aSubShapeName = "";
308 TopAbs_ShapeEnum aShapeType = ( TopAbs_ShapeEnum ) myAnnotationProperties.ShapeType;
309 if ( aShapeType != TopAbs_SHAPE ) {
310 aSubShapeName = QString( "%1:%2_%3" ).arg( aShapeName )
311 .arg( GEOMBase::TypeName( aShapeType ) )
312 .arg( myAnnotationProperties.ShapeIndex );
314 mySubShapeName->setText( aSubShapeName );
316 mySelectionMode = ( TopAbs_ShapeEnum ) myAnnotationProperties.ShapeType;
317 //SelectionIntoArgument();
318 updateSubShapeEnableState();
321 connect( myTextEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChange() ) );
322 connect( myIsScreenFixed, SIGNAL( clicked( bool ) ), this, SLOT( onTypeChange() ) );
324 myGeomGUI->GetAnnotationMgr()->SetPreviewStyle( myEditAnnotationEntry, myEditAnnotationIndex, true );
326 SalomeApp_Application* anApp = myGeomGUI->getApp();
329 OCCViewer_ViewManager* aVM = (OCCViewer_ViewManager*)anApp->getViewManager( OCCViewer_Viewer::Type(), false );
330 OCCViewer_Viewer* aViewer = (OCCViewer_Viewer*)aVM->getViewModel();
331 aViewer->unHighlightAll( true, true );
338 //=================================================================================
339 // function : activateSelection
340 // purpose : Activate local selection
341 //=================================================================================
342 void MeasureGUI_AnnotationDlg::activateSelection()
344 globalSelection( GEOM_ALLOBJECTS );
345 if ( !myShape->_is_nil() && mySelectionMode != TopAbs_SHAPE ) {
346 localSelection( myShape.get(), mySelectionMode );
350 //=================================================================================
351 // function : getShapeType()
353 //=================================================================================
354 TopAbs_ShapeEnum MeasureGUI_AnnotationDlg::getShapeType() const
356 return ( TopAbs_ShapeEnum ) mySubShapeTypeCombo->itemData(
357 mySubShapeTypeCombo->currentIndex() ).toInt();
360 //=================================================================================
361 // function : ClickOnOk()
363 //=================================================================================
364 void MeasureGUI_AnnotationDlg::ClickOnOk()
366 setIsApplyAndClose( true );
367 if ( ClickOnApply() )
369 setIsApplyAndClose( false );
372 //=================================================================================
373 // function : ClickOnApply()
375 //=================================================================================
376 bool MeasureGUI_AnnotationDlg::ClickOnApply()
378 if ( !isApplyAndClose() ) {
379 setIsDisableBrowsing( true );
380 setIsDisplayResult( false );
384 if ( !isValid( msg ) ) {
389 SUIT_OverrideCursor wc;
390 SUIT_Session::session()->activeApplication()->putInfo( "" );
394 if ( !execute( /*isApplyAndClose()*/ ) ) {
399 } catch ( const SALOME::SALOME_Exception& e ) {
400 SalomeApp_Tools::QtCatchCorbaException( e );
406 if ( !isApplyAndClose() ) {
407 setIsDisableBrowsing( false );
408 setIsDisplayResult( true );
411 if ( !myShape->_is_nil() ) {
412 redisplay( myShape.get() );
415 if ( myIsCreation ) {
417 if ( !isApplyAndClose() )
424 //=================================================================================
425 // function : SetEditCurrentArgument()
426 // purpose : process click on shape/sub-shape button. It stores as current edit argument
427 // the corresponded line edit, set focus in it and unpress other button if it was pressed
428 //=================================================================================
429 void MeasureGUI_AnnotationDlg::SetEditCurrentArgument()
431 QPushButton* aSelectButton = ( QPushButton* ) sender();
433 activateSelectionArgument( aSelectButton );
435 SelectionIntoArgument();
438 //=================================================================================
439 // function : activateSelectionArgument()
440 // purpose : it stores as current edit argument the corresponded line edit,
441 // sets the focus on it and unpresses other button if it was pressed
442 //=================================================================================
443 void MeasureGUI_AnnotationDlg::activateSelectionArgument
445 QPushButton* theSelectionButton ) {
446 QPushButton* anOtherButton = 0;
447 if ( theSelectionButton == myShapeSelBtn ) {
448 myEditCurrentArgument = myShapeName;
449 anOtherButton = mySubShapeSelBtn;
450 // throw down current sub-shape selection
451 TopAbs_ShapeEnum aShapeType = TopAbs_SHAPE;
453 mySubShapeTypeCombo->setCurrentIndex( 0 );
454 mySubShapeName->setText( "" );
456 myAnnotationProperties.ShapeType = aShapeType;
457 myAnnotationProperties.ShapeIndex = -1;
459 mySelectionMode = aShapeType;
461 updateSubShapeEnableState();
462 } else if ( theSelectionButton == mySubShapeSelBtn ) {
463 myEditCurrentArgument = mySubShapeName;
464 anOtherButton = myShapeSelBtn;
466 myEditCurrentArgument = 0;
468 if ( myEditCurrentArgument )
469 myEditCurrentArgument->setFocus();
471 theSelectionButton->setDown( true );
472 anOtherButton->setDown( false );
475 //=================================================================================
476 // function : SelectionIntoArgument()
477 // purpose : Called when selection has changed. Sets the current selection in the
478 // annotation property and redisplays presentation
479 //=================================================================================
480 void MeasureGUI_AnnotationDlg::SelectionIntoArgument()
482 if ( myIsCreation && myEditCurrentArgument )
484 myEditCurrentArgument->setText( "" );
486 GEOM::GeomObjPtr anObj = getSelected( mySelectionMode );
488 bool hasAttachPoint = false;
489 gp_Pnt anAttachPoint( 0, 0, 0 );
490 int aSubShapeIndex = -1;
491 if ( myEditCurrentArgument == myShapeName ) { // Selection of a shape is active
492 if ( anObj->_is_nil() || mySelectionMode != TopAbs_SHAPE ) {
493 myShape = GEOM::GEOM_Object::_nil();
496 QString aName = GEOMBase::GetName( anObj.get() );
497 myEditCurrentArgument->setText( aName );
498 if ( !myShapeNameModified ) {
499 myTextEdit->setText( aName );
501 // modified state should not be changed as modification was performed not manually
502 myShapeNameModified = false;
506 bool aNullShape = myShape->_is_nil();
507 mySubShapeTypeCombo->setEnabled( !aNullShape );
508 updateSubShapeEnableState();
515 GEOMBase::GetShape( myShape.get(), aShape );
517 hasAttachPoint = getPickedPoint( anAttachPoint, aShape );
518 if ( !hasAttachPoint ) {
520 anAttachPoint = getAttachPoint( aShape, hasAttachPoint );
523 } else if ( myEditCurrentArgument == mySubShapeName ) {
524 if ( !myShape->_is_nil() ) {
526 if ( anObj->_is_nil() ) {
527 myEditCurrentArgument->setText( QString() );
531 QString aName = GEOMBase::GetName( anObj.get() );
532 myEditCurrentArgument->setText( aName );
534 TopTools_IndexedMapOfShape aMainMap;
535 TopoDS_Shape aMainShape;
536 TopoDS_Shape aSubShape;
537 GEOMBase::GetShape( myShape.get(), aMainShape );
538 GEOMBase::GetShape( anObj.get(), aSubShape );
539 TopExp::MapShapes( aMainShape, getShapeType(), aMainMap );
541 if ( aMainMap.Contains( aSubShape ) ) {
542 aSubShapeIndex = aMainMap.FindIndex( aSubShape );
545 if ( !aSubShape.IsNull() ) {
548 GEOMBase::GetShape( myShape.get(), aShape );
550 hasAttachPoint = getPickedPoint( anAttachPoint, aSubShape );
551 if ( !hasAttachPoint ) {
553 anAttachPoint = getAttachPoint( aSubShape, hasAttachPoint );
558 myAnnotationProperties.ShapeIndex = aSubShapeIndex;
562 if ( !myShape->_is_nil() ) {
565 GEOMBase::GetShape( myShape.get(), aShape );
566 gp_Ax3 aShapeLCS = gp_Ax3().Transformed( aShape.Location().Transformation() );
567 aToShapeLCS.SetTransformation( gp_Ax3(), aShapeLCS );
570 myAnnotationProperties.Attach = anAttachPoint.Transformed( aToShapeLCS );
572 if ( hasAttachPoint && !myIsPositionDefined ) {
574 gp_Pnt aPosition = getDefaultPosition( anAttachPoint );
576 myAnnotationProperties.Position = ( !myAnnotationProperties.IsScreenFixed ) ?
577 aPosition.Transformed( aToShapeLCS ) : aPosition;
579 myIsPositionDefined = true;
581 else if ( !hasAttachPoint ) {
583 myIsPositionDefined = false;
589 //=======================================================================
590 //function : closeEvent
592 //=======================================================================
593 void MeasureGUI_AnnotationDlg::closeEvent( QCloseEvent* theEv )
595 if ( myInteractor ) {
596 myInteractor->Disable();
598 GEOMBase_Skeleton::closeEvent( theEv );
601 //=======================================================================
602 //function : onTextChange
603 //purpose : change annotation text
604 //=======================================================================
605 void MeasureGUI_AnnotationDlg::onTextChange()
607 myAnnotationProperties.Text = myTextEdit->text();
608 if ( !myShapeNameModified )
609 myShapeNameModified = true;
613 //=======================================================================
614 //function : onTypeChange
615 //purpose : change annotation type: 2D or 3D
616 //=======================================================================
617 void MeasureGUI_AnnotationDlg::onTypeChange()
619 const bool isScreenFixedBefore = myAnnotationProperties.IsScreenFixed;
621 myAnnotationProperties.IsScreenFixed = myIsScreenFixed->isChecked();
623 // convert point position from screen space to 3D space
624 if ( myIsPositionDefined ) {
626 SUIT_ViewWindow* anActiveView = GEOMBase_Helper::getActiveView();
627 OCCViewer_ViewWindow* anOccView = NULL;
628 if ( anActiveView ) {
630 anOccView = qobject_cast<OCCViewer_ViewWindow*>( anActiveView );
636 GEOMBase::GetShape( myShape.get(), aShape );
637 const gp_Ax3 aShapeLCS = gp_Ax3().Transformed( aShape.Location().Transformation() );
639 gp_Trsf aToShapeLCS, aFrShapeLCS;
640 aFrShapeLCS.SetTransformation( aShapeLCS, gp_Ax3() );
641 aToShapeLCS.SetTransformation( gp_Ax3(), aShapeLCS );
643 const Handle(V3d_View) aView3d = anOccView->getViewPort()->getView();
644 const gp_Pnt aPosition = myAnnotationProperties.Position;
645 const gp_Pnt aAttach3d = myAnnotationProperties.Attach.Transformed( aFrShapeLCS );
646 if ( !isScreenFixedBefore ) {
648 gp_Pnt aPosition3d = aPosition.Transformed( aFrShapeLCS );
649 gp_Pnt aPosition2d = GEOM_Annotation::ConvertPosition2d( aPosition3d, aAttach3d, aView3d );
650 myAnnotationProperties.Position = aPosition2d;
654 gp_Pnt aPosition3d = GEOM_Annotation::ConvertPosition3d( aPosition, aAttach3d, aView3d );
655 aPosition3d = aPosition3d.Transformed( aToShapeLCS );
656 myAnnotationProperties.Position = aPosition3d;
664 //=======================================================================
665 //function : onSubShapeTypeChange
667 //=======================================================================
668 void MeasureGUI_AnnotationDlg::onSubShapeTypeChange()
670 const TopAbs_ShapeEnum aShapeType = getShapeType();
672 activateSelectionArgument( aShapeType == TopAbs_SHAPE ? myShapeSelBtn : mySubShapeSelBtn );
674 myAnnotationProperties.ShapeType = aShapeType;
676 if ( aShapeType != mySelectionMode ) {
677 mySubShapeName->setText( "" );
678 myAnnotationProperties.ShapeIndex = -1;
679 mySelectionMode = aShapeType;
682 updateSubShapeEnableState();
688 //=================================================================================
689 // function : onDragged
691 //=================================================================================
692 void MeasureGUI_AnnotationDlg::onDragged( Handle_GEOM_Annotation theAnnotation )
695 GEOMBase::GetShape( myShape.get(), aShape );
696 gp_Ax3 aShapeLCS = gp_Ax3().Transformed( aShape.Location().Transformation() );
698 aToShapeLCS.SetTransformation( gp_Ax3(), aShapeLCS );
700 if ( !myAnnotationProperties.IsScreenFixed ) {
701 myAnnotationProperties.Position = theAnnotation->GetPosition().Transformed( aToShapeLCS );
703 if ( !myIsCreation ) {
704 myGeomGUI->GetAnnotationMgr()->storeFixedPosition( myEditAnnotationEntry, 0 );
708 myAnnotationProperties.Position = theAnnotation->GetPosition();
712 #define RETURN_WITH_MSG( a, b ) \
714 theMessage += ( b ); \
718 //=================================================================================
719 // function : createOperation
721 //=================================================================================
722 GEOM::GEOM_IOperations_ptr MeasureGUI_AnnotationDlg::createOperation()
724 return getGeomEngine()->GetILocalOperations( );
727 //=================================================================================
728 // function : isValid()
729 // purpose : Verify validity of input data
730 //=================================================================================
731 bool MeasureGUI_AnnotationDlg::isValid( QString& theMessage )
733 SalomeApp_Study* study = getStudy();
734 RETURN_WITH_MSG( !study, tr( "GEOM_NO_STUDY" ) )
735 RETURN_WITH_MSG( study->studyDS()->GetProperties()->IsLocked(),
736 tr( "GEOM_STUDY_LOCKED" ) )
738 if ( myIsCreation ) {
739 RETURN_WITH_MSG( myShape->_is_nil(), tr( "NO_SHAPE" ) )
741 //RETURN_WITH_MSG( CORBA::is_nil( myShape ), tr( "NO_FIELD" ) )
744 if ( getShapeType() != TopAbs_SHAPE ) {
745 if ( myIsCreation ) {
746 RETURN_WITH_MSG( myAnnotationProperties.ShapeIndex < 0, tr( "NO_SUB_SHAPE" ) )
748 //RETURN_WITH_MSG( CORBA::is_nil( myShape ), tr( "NO_FIELD" ) )
752 if ( myIsCreation ) {
753 RETURN_WITH_MSG( !myIsPositionDefined, tr( "NO_POSITION" ) )
759 //=================================================================================
760 // function : execute
762 //=================================================================================
763 bool MeasureGUI_AnnotationDlg::execute()
766 if ( !isValid( anError ) )
769 SalomeApp_Study* aStudy = getStudy();
770 _PTR(SObject) aSObj = aStudy->studyDS()->FindObjectID( myShape->GetStudyEntry() );
772 Handle(GEOMGUI_AnnotationAttrs) aShapeAnnotations =
773 GEOMGUI_AnnotationAttrs::FindOrCreateAttributes( aSObj, aStudy );
775 if ( myIsCreation ) {
776 myAnnotationProperties.IsVisible = true; // initially created annotation is hidden
778 aShapeAnnotations->Append( myAnnotationProperties );
780 myGeomGUI->emitAnnotationsUpdated( QString( myShape->GetStudyEntry() ) );
782 erasePreview( true );
784 globalSelection( myGeomGUI->getLocalSelectionMode() , true );
786 myGeomGUI->GetAnnotationMgr()->Display( myShape->GetStudyEntry(), aShapeAnnotations->GetNbAnnotation()-1 );
790 aShapeAnnotations->SetProperties( myEditAnnotationIndex, myAnnotationProperties );
791 myGeomGUI->emitAnnotationsUpdated( QString( myShape->GetStudyEntry() ) );
796 //=================================================================================
797 // function : buildPrs
798 // purpose : creates annotation presentation object and corresponded SALOME presentation
799 //=================================================================================
800 SALOME_Prs* MeasureGUI_AnnotationDlg::buildPrs()
802 QString aEntry = myIsCreation ?
803 myGeomGUI->GetAnnotationMgr()->makeAnnotationEntry( myShape->GetStudyEntry(), - 1 ) :
804 myGeomGUI->GetAnnotationMgr()->makeAnnotationEntry( myEditAnnotationEntry, myEditAnnotationIndex );
806 SALOME_Prs* aPrs = myGeomGUI->GetAnnotationMgr()->CreatePresentation(
807 myAnnotationProperties, myShape.get(), 0, aEntry );
809 // set preview style for the created presentation
810 AIS_ListOfInteractive aIObjects;
811 ((SOCC_Prs*)aPrs)->GetObjects( aIObjects );
812 AIS_ListOfInteractive::Iterator aIOIt( aIObjects );
813 for ( ; aIOIt.More(); aIOIt.Next() ) {
815 Handle( GEOM_Annotation ) aPresentation = Handle( GEOM_Annotation )::DownCast( aIOIt.Value() );
816 aPresentation->SetTextColor( Quantity_NOC_VIOLET );
817 aPresentation->SetLineColor( Quantity_NOC_VIOLET );
818 aPresentation->SetDepthCulling( Standard_False );
824 //=================================================================================
825 // function : updateSubShapeEnableState
826 // purpose : creates annotation presentation object and corresponded SALOME presentation
827 //=================================================================================
828 void MeasureGUI_AnnotationDlg::updateSubShapeEnableState()
833 bool isWholeShape = getShapeType() == TopAbs_SHAPE;
834 bool aNullShape = myShape->_is_nil();
835 mySubShapeSelBtn->setEnabled( !aNullShape && !isWholeShape );
836 mySubShapeName->setEnabled( !aNullShape && !isWholeShape );
839 //=================================================================================
840 // function : redisplayPreview
841 // purpose : creates annotation presentation object and corresponded SALOME presentation
842 //=================================================================================
843 void MeasureGUI_AnnotationDlg::redisplayPreview()
845 if ( myIsCreation ) {
848 if ( !isValid( aMess ) ) {
849 erasePreview( true );
853 erasePreview( false );
856 SUIT_OverrideCursor wc;
857 getDisplayer()->SetToActivate( true );
859 if ( SALOME_Prs* aPrs = buildPrs() )
860 displayPreview( aPrs );
861 } catch ( const SALOME::SALOME_Exception& e ) {
862 SalomeApp_Tools::QtCatchCorbaException( e );
867 myGeomGUI->GetAnnotationMgr()->Redisplay( myEditAnnotationEntry, myEditAnnotationIndex,
868 myAnnotationProperties );
872 if ( myIsCreation && !myShape->_is_nil() ) {
873 anEntry = myGeomGUI->GetAnnotationMgr()->makeAnnotationEntry( myShape->GetStudyEntry(), -1 );
875 else if ( !myIsCreation ) {
876 anEntry = myGeomGUI->GetAnnotationMgr()->makeAnnotationEntry( myEditAnnotationEntry, myEditAnnotationIndex );
879 myInteractor->SetEditEntry( anEntry );
882 //=================================================================================
883 // function : getPickedPoint
884 // purpose : finds picked point in active viewer on the selected shape
885 //=================================================================================
886 bool MeasureGUI_AnnotationDlg::getPickedPoint( gp_Pnt& thePnt, const TopoDS_Shape& theShape )
888 if ( theShape.ShapeType() == TopAbs_VERTEX )
891 thePnt = getAttachPoint( theShape, isOk );
895 const SUIT_ViewWindow* anActiveView = GEOMBase_Helper::getActiveView();
899 const OCCViewer_ViewWindow* anOccView = qobject_cast<const OCCViewer_ViewWindow*>( anActiveView );
900 if ( !anOccView || !anOccView->underMouse() )
903 OCCViewer_ViewManager* aVM = ( OCCViewer_ViewManager* )anOccView->getViewManager();
904 OCCViewer_Viewer* aViewer = aVM->getOCCViewer();
906 Handle(AIS_InteractiveContext) anAISContext = aViewer->getAISContext();
907 Handle(SelectMgr_ViewerSelector) aSelector;
908 if ( anAISContext->HasOpenedContext() )
909 aSelector = anAISContext->LocalSelector();
911 aSelector = anAISContext->MainSelector();
913 if ( aSelector->NbPicked() < 1 )
916 thePnt = aSelector->PickedPoint( 1 );
920 //=================================================================================
921 // function : getAttachPoint
922 // purpose : computes default attachment point on the shape
923 //=================================================================================
924 gp_Pnt MeasureGUI_AnnotationDlg::getAttachPoint( const TopoDS_Shape& theShape, bool& theIsOk )
926 gp_Pnt aPnt( 0.0, 0.0, 0.0 );
928 if ( theShape.ShapeType() == TopAbs_COMPSOLID
929 || theShape.ShapeType() == TopAbs_SOLID
930 || theShape.ShapeType() == TopAbs_SHELL )
933 BRepBndLib::Add( theShape, aBox );
934 const gp_Pnt aMin = aBox.CornerMin();
935 const gp_Pnt aMax = aBox.CornerMax();
936 aPnt = gp_Pnt( (aMin.X() + aMax.X()) / 2.0,
937 (aMin.Y() + aMax.Y()) / 2.0,
938 (aMin.Z() + aMax.Z()) / 2.0 );
940 else if ( theShape.ShapeType() == TopAbs_FACE )
942 BRepAdaptor_Surface aFace( TopoDS::Face( theShape ) );
943 const Standard_Real aU1 = aFace.FirstUParameter();
944 const Standard_Real aU2 = aFace.LastUParameter();
945 const Standard_Real aV1 = aFace.FirstVParameter();
946 const Standard_Real aV2 = aFace.LastVParameter();
947 aPnt = aFace.Value( ( aU1 + aU2 ) / 2.0, ( aV1 + aV2 ) / 2.0 );
949 else if ( theShape.ShapeType() == TopAbs_WIRE )
951 BRepAdaptor_CompCurve aWire( TopoDS::Wire( theShape ) );
952 const Standard_Real aP1 = aWire.FirstParameter();
953 const Standard_Real aP2 = aWire.LastParameter();
954 aPnt = aWire.Value( ( aP1 + aP2 ) / 2.0 );
956 else if ( theShape.ShapeType() == TopAbs_EDGE )
958 BRepAdaptor_Curve aEdge( TopoDS::Edge( theShape ) );
959 const Standard_Real aP1 = aEdge.FirstParameter();
960 const Standard_Real aP2 = aEdge.LastParameter();
961 aPnt = aEdge.Value( ( aP1 + aP2 ) / 2.0 );
963 else if ( theShape.ShapeType() == TopAbs_VERTEX )
965 aPnt = BRep_Tool::Pnt( TopoDS::Vertex( theShape ) );
975 //=================================================================================
976 // function : getDefaultPosition
977 // purpose : computes default position for the given attachment point
978 //=================================================================================
979 gp_Pnt MeasureGUI_AnnotationDlg::getDefaultPosition( const gp_Pnt& theAttach )
981 SUIT_ViewWindow* anActiveView = GEOMBase_Helper::getActiveView();
982 if ( !anActiveView ) {
984 return myAnnotationProperties.IsScreenFixed ? gp::Origin() : theAttach;
987 OCCViewer_ViewWindow* anOccView = qobject_cast<OCCViewer_ViewWindow*>( anActiveView );
990 return myAnnotationProperties.IsScreenFixed ? gp::Origin() : theAttach;
993 OCCViewer_ViewPort3d* aViewPort = anOccView->getViewPort();
995 SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
997 const QFont aFont = aResMgr->fontValue( "Geometry", "shape_annotation_font", QFont( "Y14.5M-2009", 24 ) );
999 const Handle(V3d_View) aView3d = aViewPort->getView();
1001 const Standard_Real aFontHeight =( aFont.pixelSize() != -1 ) ? aFont.pixelSize() : aFont.pointSize();
1003 return GEOM_Annotation::GetDefaultPosition( myAnnotationProperties.IsScreenFixed,
1004 theAttach, aFontHeight * 1.5, aView3d );