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>
101 #include <Basics_OCCTVersion.hxx>
107 //=======================================================================
108 //function : MeasureGUI_AnnotationDlg
110 //=======================================================================
112 MeasureGUI_AnnotationDlg::MeasureGUI_AnnotationDlg( GeometryGUI* theGeometryGUI, const bool theIsCreate,
113 QWidget* parent, bool modal, Qt::WindowFlags fl )
114 : GEOMBase_Skeleton( theGeometryGUI, parent, modal, fl ),
115 myIsCreation( theIsCreate ), myShapeNameModified( false )
117 myEditCurrentArgument = 0;
119 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
120 QPixmap iconSelect( resMgr->loadPixmap( "GEOM", tr( "ICON_SELECT" ) ) );
122 setWindowTitle( myIsCreation ? tr( "CREATE_ANNOTATION_TITLE" ) : tr( "EDIT_ANNOTATION_TITLE" ) );
124 // Shape type button group
125 mainFrame()->GroupBoxName->hide();
126 mainFrame()->GroupConstructors->hide();
129 QGroupBox* propGroup = new QGroupBox( tr( "ANNOTATION_PROPERTIES" ), centralWidget() );
130 QGridLayout* propLayout = new QGridLayout( propGroup );
131 propLayout->setMargin( 9 );
132 propLayout->setSpacing( 6 );
134 QLabel* textLabel = new QLabel( tr( "ANNOTATION_TEXT" ), propGroup );
135 myTextEdit = new QLineEdit( propGroup );
136 propLayout->addWidget( textLabel, 0, 0 );
137 propLayout->addWidget( myTextEdit, 0, 1, 1, 2 );
140 QLabel* shapeLabel = new QLabel( tr( "ANNOTATION_SHAPE" ), propGroup );
141 myShapeSelBtn = new QPushButton( propGroup );
142 myShapeSelBtn->setIcon( iconSelect );
143 myShapeSelBtn->setEnabled( myIsCreation );
144 myShapeName = new QLineEdit( propGroup );
145 myShapeName->setReadOnly( true );
146 myShapeName->setEnabled( myIsCreation );
149 myIsScreenFixed = new QCheckBox( tr( "ANNOTATION_IS_SCREEN_FIXED" ), propGroup );
150 myIsScreenFixed->setChecked( false ); // 3D, not fixed
152 propLayout->addWidget( shapeLabel, 1, 0 );
153 propLayout->addWidget( myShapeSelBtn, 1, 1 );
154 propLayout->addWidget( myShapeName, 1, 2 );
155 propLayout->addWidget( myIsScreenFixed, 2, 0, 1, 3 );
156 propLayout->setColumnStretch( 2, 5 );
158 QLabel* shapeTypeLabel = new QLabel( tr( "ANNOTATION_SUB_SHAPE" ), propGroup );
159 mySubShapeTypeCombo = new QComboBox( propGroup );
160 mySubShapeTypeCombo->setEnabled( myIsCreation );
161 mySubShapeTypeCombo->addItem( tr( "WHOLE_SHAPE" ), TopAbs_SHAPE );
162 mySubShapeTypeCombo->addItem( tr( "GEOM_VERTEX" ), TopAbs_VERTEX );
163 mySubShapeTypeCombo->addItem( tr( "GEOM_EDGE" ), TopAbs_EDGE );
164 mySubShapeTypeCombo->addItem( tr( "GEOM_FACE" ), TopAbs_FACE );
165 mySubShapeTypeCombo->addItem( tr( "GEOM_SOLID" ), TopAbs_SOLID );
166 mySubShapeTypeCombo->setCurrentIndex( 0 ); // SHAPE
168 propLayout->addWidget( shapeTypeLabel, 3, 0 );
169 propLayout->addWidget( mySubShapeTypeCombo, 3, 1, 1, 2 );
172 mySubShapeSelBtn = new QPushButton( propGroup );
173 mySubShapeSelBtn->setIcon( iconSelect );
174 mySubShapeSelBtn->setEnabled( myIsCreation );
175 mySubShapeName = new QLineEdit( propGroup );
176 mySubShapeName->setReadOnly( true );
177 mySubShapeName->setEnabled( myIsCreation );
179 propLayout->addWidget( mySubShapeSelBtn, 4, 1 );
180 propLayout->addWidget( mySubShapeName, 4, 2 );
182 QVBoxLayout* layout = new QVBoxLayout( centralWidget() );
183 layout->setMargin( 0 );
184 layout->setSpacing( 6 );
185 layout->addWidget( propGroup );
187 setHelpFileName( "annotation_page.html" );
189 LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
190 connect( aSelMgr, SIGNAL( currentSelectionChanged() ), this,
191 SLOT( SelectionIntoArgument() ) );
192 connect( buttonOk(), SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) );
193 connect( buttonApply(), SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) );
195 myInteractor = new MeasureGUI_AnnotationInteractor( theGeometryGUI, parent );
196 myInteractor->Enable();
198 connect( myInteractor, SIGNAL( SignalInteractionFinished( Handle_GEOM_Annotation ) ),
199 this, SLOT( onDragged( Handle_GEOM_Annotation ) ) );
204 //=======================================================================
205 //function : ~MeasureGUI_AnnotationDlg
207 //=======================================================================
209 MeasureGUI_AnnotationDlg::~MeasureGUI_AnnotationDlg() {
212 //=================================================================================
214 // purpose : fills annotation properties with default values( in create mode ) or
215 // the values of modified object
216 //=================================================================================
217 void MeasureGUI_AnnotationDlg::Init()
219 if ( myIsCreation ) {
221 // default presentation values
222 myIsPositionDefined = false;
223 myAnnotationProperties.Text = tr( "ANNOTATION_PREFIX" );
224 myAnnotationProperties.IsVisible = false;
225 myAnnotationProperties.IsScreenFixed = false;
226 myAnnotationProperties.Attach = gp_Pnt( 0, 0, 0 );
227 myAnnotationProperties.ShapeIndex = -1;
228 myAnnotationProperties.ShapeType = ( int ) TopAbs_SHAPE;
230 // update internal controls and fields following to default values
231 activateSelectionArgument( myShapeSelBtn );
233 myTextEdit->setText( myAnnotationProperties.Text );
234 myShapeNameModified = false;
235 myIsScreenFixed->setChecked( myAnnotationProperties.IsScreenFixed );
237 int aSubShapeTypeIndex = -1;
238 int aTypesCount = mySubShapeTypeCombo->count();
239 for ( int i = 0; i < aTypesCount && aSubShapeTypeIndex < 0; i++ ) {
240 int aType = mySubShapeTypeCombo->itemData( i ).toInt();
241 if ( aType == myAnnotationProperties.ShapeType )
242 aSubShapeTypeIndex = i;
244 mySubShapeTypeCombo->setCurrentIndex( aSubShapeTypeIndex );
246 mySelectionMode = ( TopAbs_ShapeEnum ) myAnnotationProperties.ShapeType;
247 SelectionIntoArgument();
248 updateSubShapeEnableState();
251 connect( myShapeSelBtn, SIGNAL( clicked() ), this,
252 SLOT( SetEditCurrentArgument() ) );
253 connect( mySubShapeSelBtn, SIGNAL( clicked() ), this,
254 SLOT( SetEditCurrentArgument() ) );
256 connect( myTextEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChange() ) );
257 connect( myIsScreenFixed, SIGNAL( clicked( bool ) ), this, SLOT( onTypeChange() ) );
258 connect( mySubShapeTypeCombo, SIGNAL( currentIndexChanged( int ) ),
259 this, SLOT( onSubShapeTypeChange() ) );
261 //SelectionIntoArgument();
265 myIsPositionDefined = true;
266 mySelectionMode = TopAbs_SHAPE;
268 GEOMGUI_TextTreeWdg* aTextTreeWdg = myGeomGUI->GetTextTreeWdg();
269 // text tree widget should be not empty
270 QMap<QString, QList<int> > anAnnotations;
271 aTextTreeWdg->getSelected( anAnnotations );
272 // there is only one annotation selected when edit is started
273 QMap<QString, QList<int> >::const_iterator anIt = anAnnotations.begin();
274 myEditAnnotationEntry = anIt.key();
275 myEditAnnotationIndex = anIt.value()[0];
277 SalomeApp_Study* aStudy = getStudy();
278 _PTR(SObject) aSObj = aStudy->studyDS()->FindObjectID( myEditAnnotationEntry.toStdString() );
279 const Handle(GEOMGUI_AnnotationAttrs) aShapeAnnotations = GEOMGUI_AnnotationAttrs::FindAttributes( aSObj );
280 if ( !aShapeAnnotations.IsNull() ) {
281 aShapeAnnotations->GetProperties( myEditAnnotationIndex, myAnnotationProperties );
283 myShape = GEOM::GEOM_Object::_narrow( GeometryGUI::ClientSObjectToObject(aSObj) );
286 /// fill dialog controls
287 myTextEdit->setText( myAnnotationProperties.Text );
288 myShapeNameModified = false;
289 myIsScreenFixed->setChecked( myAnnotationProperties.IsScreenFixed );
291 int aSubShapeTypeIndex = -1;
292 int aTypesCount = mySubShapeTypeCombo->count();
293 for ( int i = 0; i < aTypesCount && aSubShapeTypeIndex < 0; i++ ) {
294 int aType = mySubShapeTypeCombo->itemData( i ).toInt();
295 if ( aType == myAnnotationProperties.ShapeType )
296 aSubShapeTypeIndex = i;
298 mySubShapeTypeCombo->setCurrentIndex( aSubShapeTypeIndex );
300 QString aShapeName = "";
301 _PTR(GenericAttribute) anAttr;
302 if ( aSObj && aSObj->FindAttribute( anAttr, "AttributeName") ) {
303 _PTR(AttributeName) aNameAttr( anAttr );
305 aShapeName = aNameAttr->Value().c_str();
307 myShapeName->setText( aShapeName );
309 QString aSubShapeName = "";
310 TopAbs_ShapeEnum aShapeType = ( TopAbs_ShapeEnum ) myAnnotationProperties.ShapeType;
311 if ( aShapeType != TopAbs_SHAPE ) {
312 aSubShapeName = QString( "%1:%2_%3" ).arg( aShapeName )
313 .arg( GEOMBase::TypeName( aShapeType ) )
314 .arg( myAnnotationProperties.ShapeIndex );
316 mySubShapeName->setText( aSubShapeName );
318 mySelectionMode = ( TopAbs_ShapeEnum ) myAnnotationProperties.ShapeType;
319 //SelectionIntoArgument();
320 updateSubShapeEnableState();
323 connect( myTextEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChange() ) );
324 connect( myIsScreenFixed, SIGNAL( clicked( bool ) ), this, SLOT( onTypeChange() ) );
326 myGeomGUI->GetAnnotationMgr()->SetPreviewStyle( myEditAnnotationEntry, myEditAnnotationIndex, true );
328 SalomeApp_Application* anApp = myGeomGUI->getApp();
331 OCCViewer_ViewManager* aVM = (OCCViewer_ViewManager*)anApp->getViewManager( OCCViewer_Viewer::Type(), false );
332 OCCViewer_Viewer* aViewer = (OCCViewer_Viewer*)aVM->getViewModel();
333 aViewer->unHighlightAll( true, true );
340 //=================================================================================
341 // function : activateSelection
342 // purpose : Activate local selection
343 //=================================================================================
344 void MeasureGUI_AnnotationDlg::activateSelection()
346 globalSelection( GEOM_ALLOBJECTS );
347 if ( !myShape->_is_nil() && mySelectionMode != TopAbs_SHAPE ) {
348 localSelection( myShape.get(), mySelectionMode );
352 //=================================================================================
353 // function : getShapeType()
355 //=================================================================================
356 TopAbs_ShapeEnum MeasureGUI_AnnotationDlg::getShapeType() const
358 return ( TopAbs_ShapeEnum ) mySubShapeTypeCombo->itemData(
359 mySubShapeTypeCombo->currentIndex() ).toInt();
362 //=================================================================================
363 // function : ClickOnOk()
365 //=================================================================================
366 void MeasureGUI_AnnotationDlg::ClickOnOk()
368 setIsApplyAndClose( true );
369 if ( ClickOnApply() )
371 setIsApplyAndClose( false );
374 //=================================================================================
375 // function : ClickOnApply()
377 //=================================================================================
378 bool MeasureGUI_AnnotationDlg::ClickOnApply()
380 if ( !isApplyAndClose() ) {
381 setIsDisableBrowsing( true );
382 setIsDisplayResult( false );
386 if ( !isValid( msg ) ) {
391 SUIT_OverrideCursor wc;
392 SUIT_Session::session()->activeApplication()->putInfo( "" );
396 if ( !execute( /*isApplyAndClose()*/ ) ) {
401 } catch ( const SALOME::SALOME_Exception& e ) {
402 SalomeApp_Tools::QtCatchCorbaException( e );
408 if ( !isApplyAndClose() ) {
409 setIsDisableBrowsing( false );
410 setIsDisplayResult( true );
413 if ( !myShape->_is_nil() ) {
414 redisplay( myShape.get() );
417 if ( myIsCreation ) {
419 if ( !isApplyAndClose() )
426 //=================================================================================
427 // function : SetEditCurrentArgument()
428 // purpose : process click on shape/sub-shape button. It stores as current edit argument
429 // the corresponded line edit, set focus in it and unpress other button if it was pressed
430 //=================================================================================
431 void MeasureGUI_AnnotationDlg::SetEditCurrentArgument()
433 QPushButton* aSelectButton = ( QPushButton* ) sender();
435 activateSelectionArgument( aSelectButton );
437 SelectionIntoArgument();
440 //=================================================================================
441 // function : activateSelectionArgument()
442 // purpose : it stores as current edit argument the corresponded line edit,
443 // sets the focus on it and unpresses other button if it was pressed
444 //=================================================================================
445 void MeasureGUI_AnnotationDlg::activateSelectionArgument
447 QPushButton* theSelectionButton ) {
448 QPushButton* anOtherButton = 0;
449 if ( theSelectionButton == myShapeSelBtn ) {
450 myEditCurrentArgument = myShapeName;
451 anOtherButton = mySubShapeSelBtn;
452 // throw down current sub-shape selection
453 TopAbs_ShapeEnum aShapeType = TopAbs_SHAPE;
455 mySubShapeTypeCombo->setCurrentIndex( 0 );
456 mySubShapeName->setText( "" );
458 myAnnotationProperties.ShapeType = aShapeType;
459 myAnnotationProperties.ShapeIndex = -1;
461 mySelectionMode = aShapeType;
463 updateSubShapeEnableState();
464 } else if ( theSelectionButton == mySubShapeSelBtn ) {
465 myEditCurrentArgument = mySubShapeName;
466 anOtherButton = myShapeSelBtn;
468 myEditCurrentArgument = 0;
470 if ( myEditCurrentArgument )
471 myEditCurrentArgument->setFocus();
473 theSelectionButton->setDown( true );
474 anOtherButton->setDown( false );
477 //=================================================================================
478 // function : SelectionIntoArgument()
479 // purpose : Called when selection has changed. Sets the current selection in the
480 // annotation property and redisplays presentation
481 //=================================================================================
482 void MeasureGUI_AnnotationDlg::SelectionIntoArgument()
484 if ( myIsCreation && myEditCurrentArgument )
486 myEditCurrentArgument->setText( "" );
488 GEOM::GeomObjPtr anObj = getSelected( mySelectionMode );
490 bool hasAttachPoint = false;
491 gp_Pnt anAttachPoint( 0, 0, 0 );
492 int aSubShapeIndex = -1;
493 if ( myEditCurrentArgument == myShapeName ) { // Selection of a shape is active
494 if ( anObj->_is_nil() || mySelectionMode != TopAbs_SHAPE ) {
495 myShape = GEOM::GEOM_Object::_nil();
498 QString aName = GEOMBase::GetName( anObj.get() );
499 myEditCurrentArgument->setText( aName );
500 if ( !myShapeNameModified ) {
501 myTextEdit->setText( aName );
503 // modified state should not be changed as modification was performed not manually
504 myShapeNameModified = false;
508 bool aNullShape = myShape->_is_nil();
509 mySubShapeTypeCombo->setEnabled( !aNullShape );
510 updateSubShapeEnableState();
517 GEOMBase::GetShape( myShape.get(), aShape );
519 hasAttachPoint = getPickedPoint( anAttachPoint, aShape );
520 if ( !hasAttachPoint ) {
522 anAttachPoint = getAttachPoint( aShape, hasAttachPoint );
525 } else if ( myEditCurrentArgument == mySubShapeName ) {
526 if ( !myShape->_is_nil() ) {
528 if ( anObj->_is_nil() ) {
529 myEditCurrentArgument->setText( QString() );
533 QString aName = GEOMBase::GetName( anObj.get() );
534 myEditCurrentArgument->setText( aName );
536 TopTools_IndexedMapOfShape aMainMap;
537 TopoDS_Shape aMainShape;
538 TopoDS_Shape aSubShape;
539 GEOMBase::GetShape( myShape.get(), aMainShape );
540 GEOMBase::GetShape( anObj.get(), aSubShape );
541 TopExp::MapShapes( aMainShape, getShapeType(), aMainMap );
543 if ( aMainMap.Contains( aSubShape ) ) {
544 aSubShapeIndex = aMainMap.FindIndex( aSubShape );
547 if ( !aSubShape.IsNull() ) {
550 GEOMBase::GetShape( myShape.get(), aShape );
552 hasAttachPoint = getPickedPoint( anAttachPoint, aSubShape );
553 if ( !hasAttachPoint ) {
555 anAttachPoint = getAttachPoint( aSubShape, hasAttachPoint );
560 myAnnotationProperties.ShapeIndex = aSubShapeIndex;
564 if ( !myShape->_is_nil() ) {
567 GEOMBase::GetShape( myShape.get(), aShape );
568 gp_Ax3 aShapeLCS = gp_Ax3().Transformed( aShape.Location().Transformation() );
569 aToShapeLCS.SetTransformation( gp_Ax3(), aShapeLCS );
572 myAnnotationProperties.Attach = anAttachPoint.Transformed( aToShapeLCS );
574 if ( hasAttachPoint && !myIsPositionDefined ) {
576 gp_Pnt aPosition = getDefaultPosition( anAttachPoint );
578 myAnnotationProperties.Position = ( !myAnnotationProperties.IsScreenFixed ) ?
579 aPosition.Transformed( aToShapeLCS ) : aPosition;
581 myIsPositionDefined = true;
583 else if ( !hasAttachPoint ) {
585 myIsPositionDefined = false;
591 //=======================================================================
592 //function : closeEvent
594 //=======================================================================
595 void MeasureGUI_AnnotationDlg::closeEvent( QCloseEvent* theEv )
597 if ( myInteractor ) {
598 myInteractor->Disable();
600 GEOMBase_Skeleton::closeEvent( theEv );
603 //=======================================================================
604 //function : onTextChange
605 //purpose : change annotation text
606 //=======================================================================
607 void MeasureGUI_AnnotationDlg::onTextChange()
609 myAnnotationProperties.Text = myTextEdit->text();
610 if ( !myShapeNameModified )
611 myShapeNameModified = true;
615 //=======================================================================
616 //function : onTypeChange
617 //purpose : change annotation type: 2D or 3D
618 //=======================================================================
619 void MeasureGUI_AnnotationDlg::onTypeChange()
621 const bool isScreenFixedBefore = myAnnotationProperties.IsScreenFixed;
623 myAnnotationProperties.IsScreenFixed = myIsScreenFixed->isChecked();
625 // convert point position from screen space to 3D space
626 if ( myIsPositionDefined ) {
628 SUIT_ViewWindow* anActiveView = GEOMBase_Helper::getActiveView();
629 OCCViewer_ViewWindow* anOccView = NULL;
630 if ( anActiveView ) {
632 anOccView = qobject_cast<OCCViewer_ViewWindow*>( anActiveView );
638 GEOMBase::GetShape( myShape.get(), aShape );
639 const gp_Ax3 aShapeLCS = gp_Ax3().Transformed( aShape.Location().Transformation() );
641 gp_Trsf aToShapeLCS, aFrShapeLCS;
642 aFrShapeLCS.SetTransformation( aShapeLCS, gp_Ax3() );
643 aToShapeLCS.SetTransformation( gp_Ax3(), aShapeLCS );
645 const Handle(V3d_View) aView3d = anOccView->getViewPort()->getView();
646 const gp_Pnt aPosition = myAnnotationProperties.Position;
647 const gp_Pnt aAttach3d = myAnnotationProperties.Attach.Transformed( aFrShapeLCS );
648 if ( !isScreenFixedBefore ) {
650 gp_Pnt aPosition3d = aPosition.Transformed( aFrShapeLCS );
651 gp_Pnt aPosition2d = GEOM_Annotation::ConvertPosition2d( aPosition3d, aAttach3d, aView3d );
652 myAnnotationProperties.Position = aPosition2d;
656 gp_Pnt aPosition3d = GEOM_Annotation::ConvertPosition3d( aPosition, aAttach3d, aView3d );
657 aPosition3d = aPosition3d.Transformed( aToShapeLCS );
658 myAnnotationProperties.Position = aPosition3d;
666 //=======================================================================
667 //function : onSubShapeTypeChange
669 //=======================================================================
670 void MeasureGUI_AnnotationDlg::onSubShapeTypeChange()
672 const TopAbs_ShapeEnum aShapeType = getShapeType();
674 activateSelectionArgument( aShapeType == TopAbs_SHAPE ? myShapeSelBtn : mySubShapeSelBtn );
676 myAnnotationProperties.ShapeType = aShapeType;
678 if ( aShapeType != mySelectionMode ) {
679 mySubShapeName->setText( "" );
680 myAnnotationProperties.ShapeIndex = -1;
681 mySelectionMode = aShapeType;
684 updateSubShapeEnableState();
690 //=================================================================================
691 // function : onDragged
693 //=================================================================================
694 void MeasureGUI_AnnotationDlg::onDragged( Handle_GEOM_Annotation theAnnotation )
697 GEOMBase::GetShape( myShape.get(), aShape );
698 gp_Ax3 aShapeLCS = gp_Ax3().Transformed( aShape.Location().Transformation() );
700 aToShapeLCS.SetTransformation( gp_Ax3(), aShapeLCS );
702 if ( !myAnnotationProperties.IsScreenFixed ) {
703 myAnnotationProperties.Position = theAnnotation->GetPosition().Transformed( aToShapeLCS );
705 if ( !myIsCreation ) {
706 myGeomGUI->GetAnnotationMgr()->storeFixedPosition( myEditAnnotationEntry, 0 );
710 myAnnotationProperties.Position = theAnnotation->GetPosition();
714 #define RETURN_WITH_MSG( a, b ) \
716 theMessage += ( b ); \
720 //=================================================================================
721 // function : createOperation
723 //=================================================================================
724 GEOM::GEOM_IOperations_ptr MeasureGUI_AnnotationDlg::createOperation()
726 return getGeomEngine()->GetILocalOperations( );
729 //=================================================================================
730 // function : isValid()
731 // purpose : Verify validity of input data
732 //=================================================================================
733 bool MeasureGUI_AnnotationDlg::isValid( QString& theMessage )
735 SalomeApp_Study* study = getStudy();
736 RETURN_WITH_MSG( !study, tr( "GEOM_NO_STUDY" ) )
737 RETURN_WITH_MSG( study->studyDS()->GetProperties()->IsLocked(),
738 tr( "GEOM_STUDY_LOCKED" ) )
740 if ( myIsCreation ) {
741 RETURN_WITH_MSG( myShape->_is_nil(), tr( "NO_SHAPE" ) )
743 //RETURN_WITH_MSG( CORBA::is_nil( myShape ), tr( "NO_FIELD" ) )
746 if ( getShapeType() != TopAbs_SHAPE ) {
747 if ( myIsCreation ) {
748 RETURN_WITH_MSG( myAnnotationProperties.ShapeIndex < 0, tr( "NO_SUB_SHAPE" ) )
750 //RETURN_WITH_MSG( CORBA::is_nil( myShape ), tr( "NO_FIELD" ) )
754 if ( myIsCreation ) {
755 RETURN_WITH_MSG( !myIsPositionDefined, tr( "NO_POSITION" ) )
761 //=================================================================================
762 // function : execute
764 //=================================================================================
765 bool MeasureGUI_AnnotationDlg::execute()
768 if ( !isValid( anError ) )
771 SalomeApp_Study* aStudy = getStudy();
772 _PTR(SObject) aSObj = aStudy->studyDS()->FindObjectID( myShape->GetStudyEntry() );
774 Handle(GEOMGUI_AnnotationAttrs) aShapeAnnotations =
775 GEOMGUI_AnnotationAttrs::FindOrCreateAttributes( aSObj, aStudy );
777 if ( myIsCreation ) {
778 myAnnotationProperties.IsVisible = true; // initially created annotation is hidden
780 aShapeAnnotations->Append( myAnnotationProperties );
782 myGeomGUI->emitAnnotationsUpdated( QString( myShape->GetStudyEntry() ) );
784 erasePreview( true );
786 globalSelection( myGeomGUI->getLocalSelectionMode() , true );
788 myGeomGUI->GetAnnotationMgr()->Display( myShape->GetStudyEntry(), aShapeAnnotations->GetNbAnnotation()-1 );
792 aShapeAnnotations->SetProperties( myEditAnnotationIndex, myAnnotationProperties );
793 myGeomGUI->emitAnnotationsUpdated( QString( myShape->GetStudyEntry() ) );
798 //=================================================================================
799 // function : buildPrs
800 // purpose : creates annotation presentation object and corresponded SALOME presentation
801 //=================================================================================
802 SALOME_Prs* MeasureGUI_AnnotationDlg::buildPrs()
804 QString aEntry = myIsCreation ?
805 myGeomGUI->GetAnnotationMgr()->makeAnnotationEntry( myShape->GetStudyEntry(), - 1 ) :
806 myGeomGUI->GetAnnotationMgr()->makeAnnotationEntry( myEditAnnotationEntry, myEditAnnotationIndex );
808 SALOME_Prs* aPrs = myGeomGUI->GetAnnotationMgr()->CreatePresentation(
809 myAnnotationProperties, myShape.get(), 0, aEntry );
811 // set preview style for the created presentation
812 AIS_ListOfInteractive aIObjects;
813 ((SOCC_Prs*)aPrs)->GetObjects( aIObjects );
814 AIS_ListOfInteractive::Iterator aIOIt( aIObjects );
815 for ( ; aIOIt.More(); aIOIt.Next() ) {
817 Handle( GEOM_Annotation ) aPresentation = Handle( GEOM_Annotation )::DownCast( aIOIt.Value() );
818 aPresentation->SetTextColor( Quantity_NOC_VIOLET );
819 aPresentation->SetLineColor( Quantity_NOC_VIOLET );
820 aPresentation->SetDepthCulling( Standard_False );
826 //=================================================================================
827 // function : updateSubShapeEnableState
828 // purpose : creates annotation presentation object and corresponded SALOME presentation
829 //=================================================================================
830 void MeasureGUI_AnnotationDlg::updateSubShapeEnableState()
835 bool isWholeShape = getShapeType() == TopAbs_SHAPE;
836 bool aNullShape = myShape->_is_nil();
837 mySubShapeSelBtn->setEnabled( !aNullShape && !isWholeShape );
838 mySubShapeName->setEnabled( !aNullShape && !isWholeShape );
841 //=================================================================================
842 // function : redisplayPreview
843 // purpose : creates annotation presentation object and corresponded SALOME presentation
844 //=================================================================================
845 void MeasureGUI_AnnotationDlg::redisplayPreview()
847 if ( myIsCreation ) {
850 if ( !isValid( aMess ) ) {
851 erasePreview( true );
855 erasePreview( false );
858 SUIT_OverrideCursor wc;
859 getDisplayer()->SetToActivate( true );
861 if ( SALOME_Prs* aPrs = buildPrs() )
862 displayPreview( aPrs );
863 } catch ( const SALOME::SALOME_Exception& e ) {
864 SalomeApp_Tools::QtCatchCorbaException( e );
869 myGeomGUI->GetAnnotationMgr()->Redisplay( myEditAnnotationEntry, myEditAnnotationIndex,
870 myAnnotationProperties );
874 if ( myIsCreation && !myShape->_is_nil() ) {
875 anEntry = myGeomGUI->GetAnnotationMgr()->makeAnnotationEntry( myShape->GetStudyEntry(), -1 );
877 else if ( !myIsCreation ) {
878 anEntry = myGeomGUI->GetAnnotationMgr()->makeAnnotationEntry( myEditAnnotationEntry, myEditAnnotationIndex );
881 myInteractor->SetEditEntry( anEntry );
884 //=================================================================================
885 // function : getPickedPoint
886 // purpose : finds picked point in active viewer on the selected shape
887 //=================================================================================
888 bool MeasureGUI_AnnotationDlg::getPickedPoint( gp_Pnt& thePnt, const TopoDS_Shape& theShape )
890 if ( theShape.ShapeType() == TopAbs_VERTEX )
893 thePnt = getAttachPoint( theShape, isOk );
897 const SUIT_ViewWindow* anActiveView = GEOMBase_Helper::getActiveView();
901 const OCCViewer_ViewWindow* anOccView = qobject_cast<const OCCViewer_ViewWindow*>( anActiveView );
902 if ( !anOccView || !anOccView->underMouse() )
905 OCCViewer_ViewManager* aVM = ( OCCViewer_ViewManager* )anOccView->getViewManager();
906 OCCViewer_Viewer* aViewer = aVM->getOCCViewer();
908 Handle(AIS_InteractiveContext) anAISContext = aViewer->getAISContext();
909 Handle(SelectMgr_ViewerSelector) aSelector;
910 #if OCC_VERSION_LARGE <= 0x07030000
911 if ( anAISContext->HasOpenedContext() )
912 aSelector = anAISContext->LocalSelector();
915 aSelector = anAISContext->MainSelector();
917 if ( aSelector->NbPicked() < 1 )
920 thePnt = aSelector->PickedPoint( 1 );
924 //=================================================================================
925 // function : getAttachPoint
926 // purpose : computes default attachment point on the shape
927 //=================================================================================
928 gp_Pnt MeasureGUI_AnnotationDlg::getAttachPoint( const TopoDS_Shape& theShape, bool& theIsOk )
930 gp_Pnt aPnt( 0.0, 0.0, 0.0 );
932 if ( theShape.ShapeType() == TopAbs_COMPSOLID
933 || theShape.ShapeType() == TopAbs_SOLID
934 || theShape.ShapeType() == TopAbs_SHELL )
937 BRepBndLib::Add( theShape, aBox );
938 const gp_Pnt aMin = aBox.CornerMin();
939 const gp_Pnt aMax = aBox.CornerMax();
940 aPnt = gp_Pnt( (aMin.X() + aMax.X()) / 2.0,
941 (aMin.Y() + aMax.Y()) / 2.0,
942 (aMin.Z() + aMax.Z()) / 2.0 );
944 else if ( theShape.ShapeType() == TopAbs_FACE )
946 BRepAdaptor_Surface aFace( TopoDS::Face( theShape ) );
947 const Standard_Real aU1 = aFace.FirstUParameter();
948 const Standard_Real aU2 = aFace.LastUParameter();
949 const Standard_Real aV1 = aFace.FirstVParameter();
950 const Standard_Real aV2 = aFace.LastVParameter();
951 aPnt = aFace.Value( ( aU1 + aU2 ) / 2.0, ( aV1 + aV2 ) / 2.0 );
953 else if ( theShape.ShapeType() == TopAbs_WIRE )
955 BRepAdaptor_CompCurve aWire( TopoDS::Wire( theShape ) );
956 const Standard_Real aP1 = aWire.FirstParameter();
957 const Standard_Real aP2 = aWire.LastParameter();
958 aPnt = aWire.Value( ( aP1 + aP2 ) / 2.0 );
960 else if ( theShape.ShapeType() == TopAbs_EDGE )
962 BRepAdaptor_Curve aEdge( TopoDS::Edge( theShape ) );
963 const Standard_Real aP1 = aEdge.FirstParameter();
964 const Standard_Real aP2 = aEdge.LastParameter();
965 aPnt = aEdge.Value( ( aP1 + aP2 ) / 2.0 );
967 else if ( theShape.ShapeType() == TopAbs_VERTEX )
969 aPnt = BRep_Tool::Pnt( TopoDS::Vertex( theShape ) );
979 //=================================================================================
980 // function : getDefaultPosition
981 // purpose : computes default position for the given attachment point
982 //=================================================================================
983 gp_Pnt MeasureGUI_AnnotationDlg::getDefaultPosition( const gp_Pnt& theAttach )
985 SUIT_ViewWindow* anActiveView = GEOMBase_Helper::getActiveView();
986 if ( !anActiveView ) {
988 return myAnnotationProperties.IsScreenFixed ? gp::Origin() : theAttach;
991 OCCViewer_ViewWindow* anOccView = qobject_cast<OCCViewer_ViewWindow*>( anActiveView );
994 return myAnnotationProperties.IsScreenFixed ? gp::Origin() : theAttach;
997 OCCViewer_ViewPort3d* aViewPort = anOccView->getViewPort();
999 SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
1001 const QFont aFont = aResMgr->fontValue( "Geometry", "shape_annotation_font", QFont( "Y14.5M-2009", 24 ) );
1003 const Handle(V3d_View) aView3d = aViewPort->getView();
1005 const Standard_Real aFontHeight =( aFont.pixelSize() != -1 ) ? aFont.pixelSize() : aFont.pointSize();
1007 return GEOM_Annotation::GetDefaultPosition( myAnnotationProperties.IsScreenFixed,
1008 theAttach, aFontHeight * 1.5, aView3d );