]> SALOME platform Git repositories - modules/geom.git/blob - src/MeasureGUI/MeasureGUI_AnnotationDlg.cxx
Salome HOME
XAO test fixed to work in salome test
[modules/geom.git] / src / MeasureGUI / MeasureGUI_AnnotationDlg.cxx
1 // Copyright ( C ) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright ( C ) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or ( at your option ) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  File   : MeasureGUI_AnnotationDlg.cxx
24
25 #include "MeasureGUI.h"
26 #include "MeasureGUI_AnnotationDlg.h"
27 #include "MeasureGUI_AnnotationInteractor.h"
28
29 #include <DlgRef.h>
30 #include <GEOMBase.h>
31 #include <GEOMBase_Skeleton.h>
32 #include <GEOM_Displayer.h>
33 #include <GeometryGUI.h>
34 #include <GEOMGUI_AnnotationMgr.h>
35 #include <GEOMGUI_TextTreeWdg.h>
36
37 #include <SOCC_Prs.h>
38 #include <SOCC_ViewModel.h>
39
40 #include <SalomeApp_Application.h>
41 #include <SalomeApp_Study.h>
42 #include <SalomeApp_Tools.h>
43 #include <SalomeApp_IntSpinBox.h>
44 #include <SalomeApp_DoubleSpinBox.h>
45
46 #include <LightApp_SelectionMgr.h>
47
48 #include <OCCViewer_ViewModel.h>
49 #include <OCCViewer_ViewManager.h>
50 #include <OCCViewer_ViewWindow.h>
51 #include <OCCViewer_ViewPort3d.h>
52 #include <SVTK_ViewModel.h>
53 #include <SALOME_Prs.h>
54 #include <SALOME_ListIO.hxx>
55
56 #include <SUIT_Desktop.h>
57 #include <SUIT_MessageBox.h>
58 #include <SUIT_OverrideCursor.h>
59 #include <SUIT_ResourceMgr.h>
60 #include <SUIT_Session.h>
61 #include <SUIT_ViewWindow.h>
62 #include <SUIT_ViewManager.h>
63
64 #include <QComboBox>
65 #include <QGridLayout>
66 #include <QGroupBox>
67 #include <QHeaderView>
68 #include <QInputDialog>
69 #include <QLabel>
70 #include <QLineEdit>
71 #include <QPushButton>
72 #include <QStack>
73 #include <QTableWidget>
74 #include <QVBoxLayout>
75
76 #include <AIS_InteractiveContext.hxx>
77 #include <AIS_ListOfInteractive.hxx>
78 #include <AIS_ListIteratorOfListOfInteractive.hxx>
79
80 #include <Bnd_Box.hxx>
81 #include <BRepAdaptor_CompCurve.hxx>
82 #include <BRepAdaptor_Curve.hxx>
83 #include <BRepAdaptor_Surface.hxx>
84 #include <BRepBndLib.hxx>
85 #include <BRep_Tool.hxx>
86
87 #include <SelectMgr_ViewerSelector.hxx>
88
89 #include <TopoDS.hxx>
90 #include <TopExp.hxx>
91 #include <TopExp_Explorer.hxx>
92 #include <TopTools_IndexedMapOfShape.hxx>
93 #include <TColStd_IndexedMapOfInteger.hxx>
94 #include <TColStd_MapOfInteger.hxx>
95 #include <TColStd_DataMapIteratorOfDataMapOfIntegerInteger.hxx>
96
97 #include <NCollection_Handle.hxx>
98
99 #include <limits>
100
101 #include <SALOMEDS_wrap.hxx>
102 #include <GEOMImpl_Types.hxx>
103
104 #ifdef max
105 #undef max
106 #endif
107
108 //=======================================================================
109 //function : MeasureGUI_AnnotationDlg
110 //purpose  : 
111 //=======================================================================
112
113 MeasureGUI_AnnotationDlg::MeasureGUI_AnnotationDlg( GeometryGUI* theGeometryGUI, const bool theIsCreate,
114                                                    QWidget* parent, bool modal, Qt::WindowFlags fl )
115 : GEOMBase_Skeleton( theGeometryGUI, parent, modal, fl ),
116   myIsCreation( theIsCreate ), myShapeNameModified( false )
117 {
118   myEditCurrentArgument = 0;
119
120   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
121   QPixmap iconSelect( resMgr->loadPixmap( "GEOM", tr( "ICON_SELECT" ) ) );
122
123   setWindowTitle( myIsCreation ? tr( "CREATE_ANNOTATION_TITLE" ) : tr( "EDIT_ANNOTATION_TITLE" ) );
124
125   // Shape type button group
126   mainFrame()->GroupBoxName->hide();
127   mainFrame()->GroupConstructors->hide();
128
129   // Field properties
130   QGroupBox* propGroup = new QGroupBox( tr( "ANNOTATION_PROPERTIES" ), centralWidget() );
131   QGridLayout* propLayout = new QGridLayout( propGroup );
132   propLayout->setMargin( 9 );
133   propLayout->setSpacing( 6 );
134
135   QLabel* textLabel = new QLabel( tr( "ANNOTATION_TEXT" ), propGroup );
136   myTextEdit = new QLineEdit( propGroup );
137   propLayout->addWidget( textLabel, 0, 0 );
138   propLayout->addWidget( myTextEdit, 0, 1, 1, 2 );
139
140   // shape
141   QLabel* shapeLabel = new QLabel( tr( "ANNOTATION_SHAPE" ), propGroup );
142   myShapeSelBtn = new QPushButton( propGroup );
143   myShapeSelBtn->setIcon( iconSelect );
144   myShapeSelBtn->setEnabled( myIsCreation );
145   myShapeName = new QLineEdit( propGroup );
146   myShapeName->setReadOnly( true );
147   myShapeName->setEnabled( myIsCreation );
148
149   // data type
150   myIsScreenFixed = new QCheckBox( tr( "ANNOTATION_IS_SCREEN_FIXED" ), propGroup );
151   myIsScreenFixed->setChecked( false ); // 3D, not fixed
152
153   propLayout->addWidget( shapeLabel, 1, 0 );
154   propLayout->addWidget( myShapeSelBtn, 1, 1 );
155   propLayout->addWidget( myShapeName, 1, 2 );
156   propLayout->addWidget( myIsScreenFixed, 2, 0, 1, 3 );
157   propLayout->setColumnStretch( 2, 5 );
158
159   QLabel* shapeTypeLabel = new QLabel( tr( "ANNOTATION_SUB_SHAPE" ), propGroup );
160   mySubShapeTypeCombo = new QComboBox( propGroup );
161   mySubShapeTypeCombo->setEnabled( myIsCreation );
162   mySubShapeTypeCombo->addItem( tr( "WHOLE_SHAPE" ), TopAbs_SHAPE );
163   mySubShapeTypeCombo->addItem( tr( "GEOM_VERTEX" ), TopAbs_VERTEX );
164   mySubShapeTypeCombo->addItem( tr( "GEOM_EDGE" ), TopAbs_EDGE );
165   mySubShapeTypeCombo->addItem( tr( "GEOM_FACE" ), TopAbs_FACE );
166   mySubShapeTypeCombo->addItem( tr( "GEOM_SOLID" ), TopAbs_SOLID );
167   mySubShapeTypeCombo->setCurrentIndex( 0 ); // SHAPE
168
169   propLayout->addWidget( shapeTypeLabel, 3, 0 );
170   propLayout->addWidget( mySubShapeTypeCombo, 3, 1, 1, 2 );
171
172   // sub-shape
173   mySubShapeSelBtn = new QPushButton( propGroup );
174   mySubShapeSelBtn->setIcon( iconSelect );
175   mySubShapeSelBtn->setEnabled( myIsCreation );
176   mySubShapeName = new QLineEdit( propGroup );
177   mySubShapeName->setReadOnly( true );
178   mySubShapeName->setEnabled( myIsCreation );
179
180   propLayout->addWidget( mySubShapeSelBtn, 4, 1 );
181   propLayout->addWidget( mySubShapeName, 4, 2 );
182
183   QVBoxLayout* layout = new QVBoxLayout( centralWidget() );
184   layout->setMargin( 0 );
185   layout->setSpacing( 6 );
186   layout->addWidget( propGroup );
187
188   setHelpFileName( "annotation_page.html" );
189
190   LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
191   connect( aSelMgr, SIGNAL( currentSelectionChanged() ), this,
192            SLOT( SelectionIntoArgument() ) );
193   connect( buttonOk(), SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) );
194   connect( buttonApply(), SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) );
195
196   myInteractor = new MeasureGUI_AnnotationInteractor( theGeometryGUI, parent );
197   myInteractor->Enable();
198
199   connect( myInteractor, SIGNAL( SignalInteractionFinished( Handle_GEOM_Annotation ) ),
200            this, SLOT( onDragged( Handle_GEOM_Annotation ) ) );
201
202   Init();
203 }
204
205 //=======================================================================
206 //function : ~MeasureGUI_AnnotationDlg
207 //purpose  : 
208 //=======================================================================
209
210 MeasureGUI_AnnotationDlg::~MeasureGUI_AnnotationDlg() {
211 }
212
213 //=================================================================================
214 // function : Init()
215 // purpose  : fills annotation properties with default values( in create mode ) or
216 // the values of modified object
217 //=================================================================================
218 void MeasureGUI_AnnotationDlg::Init()
219 {
220   if ( myIsCreation ) {
221
222     // default presentation values
223     myIsPositionDefined = false;
224     myAnnotationProperties.Text = tr( "ANNOTATION_PREFIX" );
225     myAnnotationProperties.IsVisible = false;
226     myAnnotationProperties.IsScreenFixed = false;
227     myAnnotationProperties.Attach = gp_Pnt( 0, 0, 0 );
228     myAnnotationProperties.ShapeIndex = -1;
229     myAnnotationProperties.ShapeType = ( int ) TopAbs_SHAPE;
230
231     // update internal controls and fields following to default values
232     activateSelectionArgument( myShapeSelBtn );
233
234     myTextEdit->setText( myAnnotationProperties.Text );
235     myShapeNameModified = false;
236     myIsScreenFixed->setChecked( myAnnotationProperties.IsScreenFixed );
237
238     int aSubShapeTypeIndex = -1;
239     int aTypesCount = mySubShapeTypeCombo->count();
240     for ( int i = 0; i < aTypesCount && aSubShapeTypeIndex < 0; i++ ) {
241       int aType = mySubShapeTypeCombo->itemData( i ).toInt();
242       if ( aType == myAnnotationProperties.ShapeType )
243         aSubShapeTypeIndex = i;
244     }
245     mySubShapeTypeCombo->setCurrentIndex( aSubShapeTypeIndex );
246
247     mySelectionMode = ( TopAbs_ShapeEnum ) myAnnotationProperties.ShapeType;
248     SelectionIntoArgument();
249     updateSubShapeEnableState();
250
251     // connect controls
252     connect( myShapeSelBtn, SIGNAL( clicked() ), this,
253         SLOT( SetEditCurrentArgument() ) );
254     connect( mySubShapeSelBtn, SIGNAL( clicked() ), this,
255         SLOT( SetEditCurrentArgument() ) );
256
257     connect( myTextEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChange() ) );
258     connect( myIsScreenFixed, SIGNAL( clicked( bool ) ), this, SLOT( onTypeChange() ) );
259     connect( mySubShapeTypeCombo, SIGNAL( currentIndexChanged( int ) ),
260         this, SLOT( onSubShapeTypeChange() ) );
261
262     //SelectionIntoArgument();
263
264     redisplayPreview();
265   } else { // edition
266     myIsPositionDefined = true;
267     mySelectionMode = TopAbs_SHAPE;
268     // find annotation
269     GEOMGUI_TextTreeWdg* aTextTreeWdg = myGeomGUI->GetTextTreeWdg();
270     // text tree widget should be not empty
271     QMap<QString, QList<int> > anAnnotations;
272     aTextTreeWdg->getSelected( anAnnotations );
273     // there is only one annotation selected when edit is started
274     QMap<QString, QList<int> >::const_iterator anIt = anAnnotations.begin();
275     myEditAnnotationEntry = anIt.key();
276     myEditAnnotationIndex = anIt.value()[0];
277
278     SalomeApp_Study* aStudy = getStudy();
279     _PTR(SObject) aSObj = aStudy->studyDS()->FindObjectID( myEditAnnotationEntry.toStdString() );
280     const Handle(GEOMGUI_AnnotationAttrs) aShapeAnnotations = GEOMGUI_AnnotationAttrs::FindAttributes( aSObj );
281     if ( !aShapeAnnotations.IsNull() ) {
282       aShapeAnnotations->GetProperties( myEditAnnotationIndex, myAnnotationProperties );
283
284       myShape = GEOM::GEOM_Object::_narrow( GeometryGUI::ClientSObjectToObject(aSObj) );
285     }
286
287     /// fill dialog controls
288     myTextEdit->setText( myAnnotationProperties.Text );
289     myShapeNameModified = false;
290     myIsScreenFixed->setChecked( myAnnotationProperties.IsScreenFixed );
291
292     int aSubShapeTypeIndex = -1;
293     int aTypesCount = mySubShapeTypeCombo->count();
294     for ( int i = 0; i < aTypesCount && aSubShapeTypeIndex < 0; i++ ) {
295       int aType = mySubShapeTypeCombo->itemData( i ).toInt();
296       if ( aType == myAnnotationProperties.ShapeType )
297         aSubShapeTypeIndex = i;
298     }
299     mySubShapeTypeCombo->setCurrentIndex( aSubShapeTypeIndex );
300
301     QString aShapeName = "";
302     _PTR(GenericAttribute) anAttr;
303     if ( aSObj && aSObj->FindAttribute( anAttr, "AttributeName") ) {
304       _PTR(AttributeName) aNameAttr( anAttr );
305       aNameAttr->Value();
306       aShapeName = aNameAttr->Value().c_str();
307     }
308     myShapeName->setText( aShapeName );
309
310     QString aSubShapeName = "";
311     TopAbs_ShapeEnum aShapeType = ( TopAbs_ShapeEnum ) myAnnotationProperties.ShapeType;
312     if ( aShapeType != TopAbs_SHAPE ) {
313       aSubShapeName = QString( "%1:%2_%3" ).arg( aShapeName )
314                                            .arg( GEOMBase::TypeName( aShapeType ) )
315                                            .arg( myAnnotationProperties.ShapeIndex );
316     }
317     mySubShapeName->setText( aSubShapeName );
318
319     mySelectionMode = ( TopAbs_ShapeEnum ) myAnnotationProperties.ShapeType;
320     //SelectionIntoArgument();
321     updateSubShapeEnableState();
322
323     // connect controls
324     connect( myTextEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChange() ) );
325     connect( myIsScreenFixed, SIGNAL( clicked( bool ) ), this, SLOT( onTypeChange() ) );
326
327     myGeomGUI->GetAnnotationMgr()->SetPreviewStyle( myEditAnnotationEntry, myEditAnnotationIndex, true );
328
329     SalomeApp_Application* anApp = myGeomGUI->getApp();
330     if ( anApp )
331     {
332       OCCViewer_ViewManager* aVM = (OCCViewer_ViewManager*)anApp->getViewManager( OCCViewer_Viewer::Type(), false );
333       OCCViewer_Viewer* aViewer = (OCCViewer_Viewer*)aVM->getViewModel();
334       aViewer->unHighlightAll( true, true );
335     }
336
337     redisplayPreview();
338   }
339 }
340
341 //=================================================================================
342 // function : activateSelection
343 // purpose  : Activate local selection
344 //=================================================================================
345 void MeasureGUI_AnnotationDlg::activateSelection()
346 {
347   globalSelection( GEOM_ALLOBJECTS );
348   if ( !myShape->_is_nil() && mySelectionMode != TopAbs_SHAPE ) {
349     localSelection( myShape.get(), mySelectionMode );
350   }
351 }
352
353 //=================================================================================
354 // function : getShapeType()
355 // purpose  :
356 //=================================================================================
357 TopAbs_ShapeEnum MeasureGUI_AnnotationDlg::getShapeType() const
358 {
359   return ( TopAbs_ShapeEnum ) mySubShapeTypeCombo->itemData(
360       mySubShapeTypeCombo->currentIndex() ).toInt();
361 }
362
363 //=================================================================================
364 // function : ClickOnOk()
365 // purpose  :
366 //=================================================================================
367 void MeasureGUI_AnnotationDlg::ClickOnOk()
368 {
369   setIsApplyAndClose( true );
370   if ( ClickOnApply() )
371     ClickOnCancel();
372   setIsApplyAndClose( false );
373 }
374
375 //=================================================================================
376 // function : ClickOnApply()
377 // purpose  :
378 //=================================================================================
379 bool MeasureGUI_AnnotationDlg::ClickOnApply()
380 {
381   if ( !isApplyAndClose() ) {
382     setIsDisableBrowsing( true );
383     setIsDisplayResult( false );
384   }
385
386   QString msg;
387   if ( !isValid( msg ) ) {
388     showError( msg );
389     return false;
390   }
391
392   SUIT_OverrideCursor wc;
393   SUIT_Session::session()->activeApplication()->putInfo( "" );
394
395   try {
396     if ( openCommand() )
397       if ( !execute( /*isApplyAndClose()*/ ) ) {
398         abortCommand();
399         showError();
400         return false;
401       }
402   } catch ( const SALOME::SALOME_Exception& e ) {
403     SalomeApp_Tools::QtCatchCorbaException( e );
404     abortCommand();
405     return false;
406   }
407   commitCommand();
408
409   if ( !isApplyAndClose() ) {
410     setIsDisableBrowsing( false );
411     setIsDisplayResult( true );
412   }
413
414   if ( !myShape->_is_nil() ) {
415     redisplay( myShape.get() );
416   }
417
418   if ( myIsCreation ) {
419
420    if ( !isApplyAndClose() )
421      Init();
422   }
423
424   return true;
425 }
426
427 //=================================================================================
428 // function : SetEditCurrentArgument()
429 // purpose  : process click on shape/sub-shape button. It stores as current edit argument
430 // the corresponded line edit, set focus in it and unpress other button if it was pressed
431 //=================================================================================
432 void MeasureGUI_AnnotationDlg::SetEditCurrentArgument()
433 {
434   QPushButton* aSelectButton = ( QPushButton* ) sender();
435
436   activateSelectionArgument( aSelectButton );
437
438   SelectionIntoArgument();
439 }
440
441 //=================================================================================
442 // function : activateSelectionArgument()
443 // purpose  : it stores as current edit argument the corresponded line edit,
444 // sets the focus on it and unpresses other button if it was pressed
445 //=================================================================================
446 void MeasureGUI_AnnotationDlg::activateSelectionArgument
447 (
448   QPushButton* theSelectionButton ) {
449   QPushButton* anOtherButton = 0;
450   if ( theSelectionButton == myShapeSelBtn ) {
451     myEditCurrentArgument = myShapeName;
452     anOtherButton = mySubShapeSelBtn;
453     // throw down current sub-shape selection
454     TopAbs_ShapeEnum aShapeType = TopAbs_SHAPE;
455
456     mySubShapeTypeCombo->setCurrentIndex( 0 );
457     mySubShapeName->setText( "" );
458
459     myAnnotationProperties.ShapeType = aShapeType;
460     myAnnotationProperties.ShapeIndex = -1;
461
462     mySelectionMode = aShapeType;
463
464     updateSubShapeEnableState();
465   } else if ( theSelectionButton == mySubShapeSelBtn ) {
466     myEditCurrentArgument = mySubShapeName;
467     anOtherButton = myShapeSelBtn;
468   } else
469     myEditCurrentArgument = 0;
470
471   if ( myEditCurrentArgument )
472     myEditCurrentArgument->setFocus();
473
474   theSelectionButton->setDown( true );
475   anOtherButton->setDown( false );
476 }
477
478 //=================================================================================
479 // function : SelectionIntoArgument()
480 // purpose  : Called when selection has changed. Sets the current selection in the
481 // annotation property and redisplays presentation
482 //=================================================================================
483 void MeasureGUI_AnnotationDlg::SelectionIntoArgument()
484 {
485   if ( myIsCreation && myEditCurrentArgument )
486   {
487     myEditCurrentArgument->setText( "" );
488
489     GEOM::GeomObjPtr anObj = getSelected( mySelectionMode );
490
491     bool hasAttachPoint = false;
492     gp_Pnt anAttachPoint( 0, 0, 0 );
493     int aSubShapeIndex = -1;
494     if ( myEditCurrentArgument == myShapeName ) { // Selection of a shape is active
495       if ( anObj->_is_nil() || mySelectionMode != TopAbs_SHAPE ) {
496         myShape = GEOM::GEOM_Object::_nil();
497       } else {
498         myShape = anObj;
499         QString aName = GEOMBase::GetName( anObj.get() );
500         myEditCurrentArgument->setText( aName );
501         if ( !myShapeNameModified ) {
502           myTextEdit->setText( aName );
503           onTextChange();
504           // modified state should not be changed as modification was performed not manually
505           myShapeNameModified = false;
506         }
507       }
508
509       bool aNullShape = myShape->_is_nil();
510       mySubShapeTypeCombo->setEnabled( !aNullShape );
511       updateSubShapeEnableState();
512
513       activateSelection();
514
515       if ( !aNullShape ) {
516
517         TopoDS_Shape aShape;
518         GEOMBase::GetShape( myShape.get(), aShape );
519
520         hasAttachPoint = getPickedPoint( anAttachPoint, aShape );
521         if ( !hasAttachPoint ) {
522
523           anAttachPoint = getAttachPoint( aShape, hasAttachPoint );
524         }
525       }
526     } else if ( myEditCurrentArgument == mySubShapeName ) {
527       if ( !myShape->_is_nil() ) {
528
529         if ( anObj->_is_nil() ) {
530           myEditCurrentArgument->setText( QString() );
531         }
532         else {
533
534           QString aName = GEOMBase::GetName( anObj.get() );
535           myEditCurrentArgument->setText( aName );
536
537           TopTools_IndexedMapOfShape aMainMap;
538           TopoDS_Shape aMainShape;
539           TopoDS_Shape aSubShape;
540           GEOMBase::GetShape( myShape.get(), aMainShape );
541           GEOMBase::GetShape( anObj.get(), aSubShape );
542           TopExp::MapShapes( aMainShape, getShapeType(), aMainMap );
543
544           if ( aMainMap.Contains( aSubShape ) ) {
545             aSubShapeIndex = aMainMap.FindIndex( aSubShape );
546           }
547
548           if ( !aSubShape.IsNull() ) {
549
550             TopoDS_Shape aShape;
551             GEOMBase::GetShape( myShape.get(), aShape );
552
553             hasAttachPoint = getPickedPoint( anAttachPoint, aSubShape );
554             if ( !hasAttachPoint ) {
555
556               anAttachPoint = getAttachPoint( aSubShape, hasAttachPoint );
557             }
558           }
559         }
560       }
561       myAnnotationProperties.ShapeIndex = aSubShapeIndex;
562     }
563
564     gp_Trsf aToShapeLCS;
565     if ( !myShape->_is_nil() ) {
566
567       TopoDS_Shape aShape;
568       GEOMBase::GetShape( myShape.get(), aShape );
569       gp_Ax3 aShapeLCS = gp_Ax3().Transformed( aShape.Location().Transformation() );
570       aToShapeLCS.SetTransformation( gp_Ax3(), aShapeLCS );
571     }
572
573     myAnnotationProperties.Attach = anAttachPoint.Transformed( aToShapeLCS );
574
575     if ( hasAttachPoint && !myIsPositionDefined ) {
576
577       gp_Pnt aPosition = getDefaultPosition( anAttachPoint );
578
579       myAnnotationProperties.Position = ( !myAnnotationProperties.IsScreenFixed ) ?
580         aPosition.Transformed( aToShapeLCS ) : aPosition;
581
582       myIsPositionDefined = true;
583     }
584     else if ( !hasAttachPoint ) {
585
586       myIsPositionDefined = false;
587     }
588   }
589   redisplayPreview();
590 }
591
592 //=======================================================================
593 //function : closeEvent
594 //purpose  :
595 //=======================================================================
596 void MeasureGUI_AnnotationDlg::closeEvent( QCloseEvent* theEv )
597 {
598   if ( myInteractor ) {
599     myInteractor->Disable();
600   }
601   GEOMBase_Skeleton::closeEvent( theEv );
602 }
603
604 //=======================================================================
605 //function : onTextChange
606 //purpose  : change annotation text
607 //=======================================================================
608 void MeasureGUI_AnnotationDlg::onTextChange()
609 {
610   myAnnotationProperties.Text = myTextEdit->text();
611   if ( !myShapeNameModified )
612     myShapeNameModified = true;
613   redisplayPreview();
614 }
615
616 //=======================================================================
617 //function : onTypeChange
618 //purpose  : change annotation type: 2D or 3D
619 //=======================================================================
620 void MeasureGUI_AnnotationDlg::onTypeChange()
621 {
622   const bool isScreenFixedBefore = myAnnotationProperties.IsScreenFixed;
623
624   myAnnotationProperties.IsScreenFixed = myIsScreenFixed->isChecked();
625
626   // convert point position from screen space to 3D space
627   if ( myIsPositionDefined ) {
628
629     SUIT_ViewWindow* anActiveView = GEOMBase_Helper::getActiveView();
630     OCCViewer_ViewWindow* anOccView = NULL;
631     if ( anActiveView ) {
632
633       anOccView = qobject_cast<OCCViewer_ViewWindow*>( anActiveView );
634     }
635
636     if ( anOccView ) {
637
638       TopoDS_Shape aShape;
639       GEOMBase::GetShape( myShape.get(), aShape );
640       const gp_Ax3 aShapeLCS = gp_Ax3().Transformed( aShape.Location().Transformation() );
641
642       gp_Trsf aToShapeLCS, aFrShapeLCS;
643       aFrShapeLCS.SetTransformation( aShapeLCS, gp_Ax3() );
644       aToShapeLCS.SetTransformation( gp_Ax3(), aShapeLCS );
645
646       const Handle(V3d_View) aView3d = anOccView->getViewPort()->getView();
647       const gp_Pnt aPosition = myAnnotationProperties.Position;
648       const gp_Pnt aAttach3d = myAnnotationProperties.Attach.Transformed( aFrShapeLCS );
649       if ( !isScreenFixedBefore ) {
650
651         gp_Pnt aPosition3d = aPosition.Transformed( aFrShapeLCS );
652         gp_Pnt aPosition2d = GEOM_Annotation::ConvertPosition2d( aPosition3d, aAttach3d, aView3d );
653         myAnnotationProperties.Position = aPosition2d;
654       }
655       else {
656
657         gp_Pnt aPosition3d = GEOM_Annotation::ConvertPosition3d( aPosition, aAttach3d, aView3d );
658         aPosition3d = aPosition3d.Transformed( aToShapeLCS );
659         myAnnotationProperties.Position = aPosition3d;
660       }
661     }
662   }
663
664   redisplayPreview();
665 }
666
667 //=======================================================================
668 //function : onSubShapeTypeChange
669 //purpose  :
670 //=======================================================================
671 void MeasureGUI_AnnotationDlg::onSubShapeTypeChange()
672 {
673   const TopAbs_ShapeEnum aShapeType = getShapeType();
674   
675   activateSelectionArgument( aShapeType == TopAbs_SHAPE ? myShapeSelBtn : mySubShapeSelBtn );
676
677   myAnnotationProperties.ShapeType = aShapeType;
678
679   if ( aShapeType != mySelectionMode ) {
680     mySubShapeName->setText( "" );
681     myAnnotationProperties.ShapeIndex = -1;
682     mySelectionMode = aShapeType;
683   }
684
685   updateSubShapeEnableState();
686
687   activateSelection();
688   redisplayPreview();
689 }
690
691 //=================================================================================
692 // function : onDragged
693 // purpose  :
694 //=================================================================================
695 void MeasureGUI_AnnotationDlg::onDragged( Handle_GEOM_Annotation theAnnotation )
696 {
697   TopoDS_Shape aShape;
698   GEOMBase::GetShape( myShape.get(), aShape );
699   gp_Ax3 aShapeLCS = gp_Ax3().Transformed( aShape.Location().Transformation() );
700   gp_Trsf aToShapeLCS;
701   aToShapeLCS.SetTransformation( gp_Ax3(), aShapeLCS );
702
703   if ( !myAnnotationProperties.IsScreenFixed ) {
704     myAnnotationProperties.Position = theAnnotation->GetPosition().Transformed( aToShapeLCS );
705
706     if ( !myIsCreation ) {
707       myGeomGUI->GetAnnotationMgr()->storeFixedPosition( myEditAnnotationEntry, 0 );
708     }
709   }
710   else {
711     myAnnotationProperties.Position = theAnnotation->GetPosition();
712   }
713 }
714
715 #define RETURN_WITH_MSG( a, b ) \
716   if ( ( a ) ) { \
717     theMessage += ( b ); \
718     return false; \
719   }
720
721 //=================================================================================
722 // function : createOperation
723 // purpose  :
724 //=================================================================================
725 GEOM::GEOM_IOperations_ptr MeasureGUI_AnnotationDlg::createOperation()
726 {
727   return getGeomEngine()->GetILocalOperations( getStudyId() );
728 }
729
730 //=================================================================================
731 // function : isValid()
732 // purpose  : Verify validity of input data
733 //=================================================================================
734 bool MeasureGUI_AnnotationDlg::isValid( QString& theMessage )
735 {
736   SalomeApp_Study* study = getStudy();
737   RETURN_WITH_MSG( !study, tr( "GEOM_NO_STUDY" ) )
738   RETURN_WITH_MSG( study->studyDS()->GetProperties()->IsLocked(),
739       tr( "GEOM_STUDY_LOCKED" ) )
740
741   if ( myIsCreation ) {
742     RETURN_WITH_MSG( myShape->_is_nil(), tr( "NO_SHAPE" ) )
743   } else {
744     //RETURN_WITH_MSG( CORBA::is_nil( myShape ), tr( "NO_FIELD" ) )
745   }
746
747   if ( getShapeType() != TopAbs_SHAPE ) {
748     if ( myIsCreation ) {
749       RETURN_WITH_MSG( myAnnotationProperties.ShapeIndex < 0, tr( "NO_SUB_SHAPE" ) )
750     } else {
751       //RETURN_WITH_MSG( CORBA::is_nil( myShape ), tr( "NO_FIELD" ) )
752     }
753   }
754
755   if ( myIsCreation ) {
756     RETURN_WITH_MSG( !myIsPositionDefined, tr( "NO_POSITION" ) )
757   }
758
759   return true;
760 }
761
762 //=================================================================================
763 // function : execute
764 // purpose  :
765 //=================================================================================
766 bool MeasureGUI_AnnotationDlg::execute()
767 {
768   QString anError;
769   if ( !isValid( anError ) )
770     return false;
771
772   SalomeApp_Study* aStudy = getStudy();
773   _PTR(SObject) aSObj = aStudy->studyDS()->FindObjectID( myShape->GetStudyEntry() );
774
775   Handle(GEOMGUI_AnnotationAttrs) aShapeAnnotations =
776     GEOMGUI_AnnotationAttrs::FindOrCreateAttributes( aSObj, aStudy );
777
778   if ( myIsCreation ) {
779     myAnnotationProperties.IsVisible = true; // initially created annotation is hidden
780
781     aShapeAnnotations->Append( myAnnotationProperties );
782
783     myGeomGUI->emitAnnotationsUpdated( QString( myShape->GetStudyEntry() ) );
784
785     erasePreview( true );
786
787     globalSelection( myGeomGUI->getLocalSelectionMode() , true );
788
789     myGeomGUI->GetAnnotationMgr()->Display( myShape->GetStudyEntry(), aShapeAnnotations->GetNbAnnotation()-1 );
790   }
791   else {
792
793     aShapeAnnotations->SetProperties( myEditAnnotationIndex, myAnnotationProperties );
794     myGeomGUI->emitAnnotationsUpdated( QString( myShape->GetStudyEntry() ) );
795   }
796   return true;
797 }
798
799 //=================================================================================
800 // function : buildPrs
801 // purpose  : creates annotation presentation object and corresponded SALOME presentation
802 //=================================================================================
803 SALOME_Prs* MeasureGUI_AnnotationDlg::buildPrs()
804 {
805   QString aEntry = myIsCreation ? 
806     myGeomGUI->GetAnnotationMgr()->makeAnnotationEntry( myShape->GetStudyEntry(), - 1 ) :
807     myGeomGUI->GetAnnotationMgr()->makeAnnotationEntry( myEditAnnotationEntry, myEditAnnotationIndex );
808
809   SALOME_Prs* aPrs = myGeomGUI->GetAnnotationMgr()->CreatePresentation(
810     myAnnotationProperties, myShape.get(), 0, aEntry );
811
812   // set preview style for the created presentation
813   AIS_ListOfInteractive aIObjects;
814   ((SOCC_Prs*)aPrs)->GetObjects( aIObjects );
815   AIS_ListOfInteractive::Iterator aIOIt( aIObjects );
816   for ( ; aIOIt.More(); aIOIt.Next() ) {
817   
818     Handle( GEOM_Annotation ) aPresentation = Handle( GEOM_Annotation )::DownCast( aIOIt.Value() );
819     aPresentation->SetTextColor( Quantity_NOC_VIOLET );
820     aPresentation->SetLineColor( Quantity_NOC_VIOLET );
821     aPresentation->SetDepthCulling( Standard_False );
822   }
823
824   return aPrs;
825 }
826
827 //=================================================================================
828 // function : updateSubShapeEnableState
829 // purpose  : creates annotation presentation object and corresponded SALOME presentation
830 //=================================================================================
831 void MeasureGUI_AnnotationDlg::updateSubShapeEnableState()
832 {
833   if ( !myIsCreation )
834     return;
835
836   bool isWholeShape = getShapeType() == TopAbs_SHAPE;
837   bool aNullShape = myShape->_is_nil();
838   mySubShapeSelBtn->setEnabled( !aNullShape && !isWholeShape );
839   mySubShapeName->setEnabled( !aNullShape && !isWholeShape );
840 }
841
842 //=================================================================================
843 // function : redisplayPreview
844 // purpose  : creates annotation presentation object and corresponded SALOME presentation
845 //=================================================================================
846 void MeasureGUI_AnnotationDlg::redisplayPreview()
847 {
848   if ( myIsCreation ) {
849
850     QString aMess;
851     if ( !isValid( aMess ) ) {
852       erasePreview( true );
853       return;
854     }
855
856     erasePreview( false );
857
858     try {
859       SUIT_OverrideCursor wc;
860       getDisplayer()->SetToActivate( true );
861
862       if ( SALOME_Prs* aPrs = buildPrs() )
863         displayPreview( aPrs );
864       } catch ( const SALOME::SALOME_Exception& e ) {
865         SalomeApp_Tools::QtCatchCorbaException( e );
866       } catch ( ... ) {
867     }
868   }
869   else {
870     myGeomGUI->GetAnnotationMgr()->Redisplay( myEditAnnotationEntry, myEditAnnotationIndex,
871                                               myAnnotationProperties );
872   }
873
874   QString anEntry;
875   if ( myIsCreation && !myShape->_is_nil() ) {
876     anEntry = myGeomGUI->GetAnnotationMgr()->makeAnnotationEntry( myShape->GetStudyEntry(), -1 );
877   }
878   else if ( !myIsCreation ) {
879     anEntry = myGeomGUI->GetAnnotationMgr()->makeAnnotationEntry( myEditAnnotationEntry, myEditAnnotationIndex );
880   }
881
882   myInteractor->SetEditEntry( anEntry );
883 }
884
885 //=================================================================================
886 // function : getPickedPoint
887 // purpose  : finds picked point in active viewer on the selected shape
888 //=================================================================================
889 bool MeasureGUI_AnnotationDlg::getPickedPoint( gp_Pnt& thePnt, const TopoDS_Shape& theShape )
890 {
891   if ( theShape.ShapeType() == TopAbs_VERTEX )
892   {
893     bool isOk = false;
894     thePnt = getAttachPoint( theShape, isOk );
895     return isOk;
896   }
897
898   const SUIT_ViewWindow* anActiveView = GEOMBase_Helper::getActiveView();
899   if ( !anActiveView )
900     return false;
901
902   const OCCViewer_ViewWindow* anOccView = qobject_cast<const OCCViewer_ViewWindow*>( anActiveView );
903   if ( !anOccView || !anOccView->underMouse() )
904     return false;
905
906   OCCViewer_ViewManager* aVM = ( OCCViewer_ViewManager* )anOccView->getViewManager();
907   OCCViewer_Viewer* aViewer = aVM->getOCCViewer();
908
909   Handle(AIS_InteractiveContext) anAISContext = aViewer->getAISContext();
910   Handle(SelectMgr_ViewerSelector) aSelector;
911   if ( anAISContext->HasOpenedContext() )
912     aSelector = anAISContext->LocalSelector();
913   else
914     aSelector = anAISContext->MainSelector();
915
916   if ( aSelector->NbPicked() < 1 )
917     return false;
918
919   thePnt = aSelector->PickedPoint( 1 );
920   return true;
921 }
922
923 //=================================================================================
924 // function : getAttachPoint
925 // purpose  : computes default attachment point on the shape
926 //=================================================================================
927 gp_Pnt MeasureGUI_AnnotationDlg::getAttachPoint( const TopoDS_Shape& theShape, bool& theIsOk )
928 {
929   gp_Pnt aPnt( 0.0, 0.0, 0.0 );
930   theIsOk = true;
931   if ( theShape.ShapeType() == TopAbs_COMPSOLID
932     || theShape.ShapeType() == TopAbs_SOLID
933     || theShape.ShapeType() == TopAbs_SHELL )
934   {
935     Bnd_Box aBox;
936     BRepBndLib::Add( theShape, aBox );
937     const gp_Pnt aMin = aBox.CornerMin();
938     const gp_Pnt aMax = aBox.CornerMax();
939     aPnt = gp_Pnt( (aMin.X() + aMax.X()) / 2.0,
940                    (aMin.Y() + aMax.Y()) / 2.0,
941                    (aMin.Z() + aMax.Z()) / 2.0 );
942   }
943   else if ( theShape.ShapeType() == TopAbs_FACE )
944   {
945     BRepAdaptor_Surface aFace( TopoDS::Face( theShape ) );
946     const Standard_Real aU1 = aFace.FirstUParameter();
947     const Standard_Real aU2 = aFace.LastUParameter();
948     const Standard_Real aV1 = aFace.FirstVParameter();
949     const Standard_Real aV2 = aFace.LastVParameter();
950     aPnt = aFace.Value( ( aU1 + aU2 ) / 2.0, ( aV1 + aV2 ) / 2.0 );
951   }
952   else if ( theShape.ShapeType() == TopAbs_WIRE )
953   {
954     BRepAdaptor_CompCurve aWire( TopoDS::Wire( theShape ) );
955     const Standard_Real aP1 = aWire.FirstParameter();
956     const Standard_Real aP2 = aWire.LastParameter();
957     aPnt = aWire.Value( ( aP1 + aP2 ) / 2.0 );
958   }
959   else if ( theShape.ShapeType() == TopAbs_EDGE )
960   {
961     BRepAdaptor_Curve aEdge( TopoDS::Edge( theShape ) );
962     const Standard_Real aP1 = aEdge.FirstParameter();
963     const Standard_Real aP2 = aEdge.LastParameter();
964     aPnt = aEdge.Value( ( aP1 + aP2 ) / 2.0 );
965   }
966   else if ( theShape.ShapeType() == TopAbs_VERTEX )
967   {
968     aPnt = BRep_Tool::Pnt( TopoDS::Vertex( theShape ) );
969   }
970   else
971   {
972     theIsOk = false;
973   }
974
975   return aPnt;
976 }
977
978 //=================================================================================
979 // function : getDefaultPosition
980 // purpose  : computes default position for the given attachment point
981 //=================================================================================
982 gp_Pnt MeasureGUI_AnnotationDlg::getDefaultPosition( const gp_Pnt& theAttach )
983 {
984   SUIT_ViewWindow* anActiveView = GEOMBase_Helper::getActiveView();
985   if ( !anActiveView ) {
986
987     return myAnnotationProperties.IsScreenFixed ? gp::Origin() : theAttach;
988   }
989
990   OCCViewer_ViewWindow* anOccView = qobject_cast<OCCViewer_ViewWindow*>( anActiveView );
991   if ( !anOccView ) {
992
993     return myAnnotationProperties.IsScreenFixed ? gp::Origin() : theAttach;
994   }
995
996   OCCViewer_ViewPort3d* aViewPort = anOccView->getViewPort();
997
998   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
999
1000   const QFont aFont = aResMgr->fontValue( "Geometry", "shape_annotation_font", QFont( "Y14.5M-2009", 24 ) );
1001
1002   const Handle(V3d_View) aView3d = aViewPort->getView();
1003
1004   const Standard_Real aFontHeight =( aFont.pixelSize() != -1 ) ? aFont.pixelSize() : aFont.pointSize();
1005
1006   return GEOM_Annotation::GetDefaultPosition( myAnnotationProperties.IsScreenFixed,
1007     theAttach, aFontHeight * 1.5, aView3d );
1008 }