Salome HOME
Copyright update 2020
[modules/geom.git] / src / MeasureGUI / MeasureGUI_CreateDimensionDlg.cxx
1 // Copyright (C) 2007-2020  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 // GEOM GEOMGUI : GUI for Geometry component
24 // File   : MeasureGUI_CreateDimensionDlg.cxx
25 // Author : Anton POLETAEV, Open CASCADE S.A.S.
26
27 #include "MeasureGUI_CreateDimensionDlg.h"
28 #include "MeasureGUI_DimensionCreateTool.h"
29
30 #include <GEOM_Constants.h>
31 #include <GeometryGUI.h>
32 #include <GEOMBase.h>
33 #include <DlgRef.h>
34 #include <GEOMUtils.hxx>
35 #include <GEOMGUI_DimensionProperty.h>
36
37 #include <OCCViewer_ViewManager.h>
38 #include <OCCViewer_ViewWindow.h>
39 #include <OCCViewer_ViewPort3d.h>
40 #include <LightApp_SelectionMgr.h>
41 #include <SalomeApp_Application.h>
42 #include <SalomeApp_DataObject.h>
43 #include <SalomeApp_Study.h>
44 #include <SOCC_ViewModel.h>
45 #include <SOCC_Prs.h>
46 #include <SUIT_ViewWindow.h>
47 #include <SUIT_ViewManager.h>
48 #include <SUIT_MessageBox.h>
49 #include <SUIT_ResourceMgr.h>
50 #include <SUIT_Session.h>
51 #include <SUIT_Desktop.h>
52
53 #include <Aspect_PolygonOffsetMode.hxx>
54
55 #include <Basics_OCCTVersion.hxx>
56
57 //=================================================================================
58 // function : Constructor
59 // purpose  :
60 //=================================================================================
61 MeasureGUI_CreateDimensionDlg::MeasureGUI_CreateDimensionDlg( const GEOM::GeomObjPtr& theObj,
62                                                               GeometryGUI* theGUI,
63                                                               QWidget* theParent )
64 : GEOMBase_Skeleton( theGUI, theParent ),
65   myParentObj( theObj ),
66   myEditingViewer( NULL )
67 {
68   setWindowTitle( tr( "CREATE_DIMENSION_TITLE" ) );
69
70   // init "dimension type" radio buttons
71   QAbstractButton* aTypeButtonLength   = mainFrame()->RadioButton1;
72   QAbstractButton* aTypeButtonDiameter = mainFrame()->RadioButton2;
73   QAbstractButton* aTypeButtonAngle    = mainFrame()->RadioButton3;
74
75   mainFrame()->GroupConstructors->setTitle( tr( "DIMENSIONS" ) );
76   aTypeButtonDiameter->setText( tr( "DIAMETER" ) );
77   aTypeButtonLength->setText( tr( "LENGTH" ) );
78   aTypeButtonAngle->setText( tr( "ANGLE" ) );
79
80   // construct "arguments" pane
81   QGroupBox*   aGroupArgs       = new QGroupBox( tr( "ARGUMENTS" ), centralWidget() );
82   QVBoxLayout* aGroupArgsLayout = new QVBoxLayout( aGroupArgs );
83
84   myLengthArgs   = new LengthPane  ( centralWidget() );
85   myDiameterArgs = new DiameterPane( centralWidget() );
86   myAngleArgs    = new AnglePane   ( centralWidget() );
87
88   // connect selector pane signals
89   connect( myLengthArgs,   SIGNAL( StartSelection( const QList<TopAbs_ShapeEnum>& ) ),
90                            SLOT( OnStartSelection( const QList<TopAbs_ShapeEnum>& ) ) );
91   connect( myDiameterArgs, SIGNAL( StartSelection( const QList<TopAbs_ShapeEnum>& ) ),
92                            SLOT( OnStartSelection( const QList<TopAbs_ShapeEnum>& ) ) );
93   connect( myAngleArgs,    SIGNAL( StartSelection( const QList<TopAbs_ShapeEnum>& ) ), 
94                            SLOT( OnStartSelection( const QList<TopAbs_ShapeEnum>& ) ) );
95
96   connect( myLengthArgs,   SIGNAL( StopSelection() ), SLOT( OnStopSelection() ) );
97   connect( myDiameterArgs, SIGNAL( StopSelection() ), SLOT( OnStopSelection() ) );
98   connect( myAngleArgs,    SIGNAL( StopSelection() ), SLOT( OnStopSelection( ) ) );
99
100   connect( myLengthArgs,   SIGNAL( SelectionDone() ), SLOT( OnSelectionDone() ) );
101   connect( myDiameterArgs, SIGNAL( SelectionDone() ), SLOT( OnSelectionDone() ) );
102   connect( myAngleArgs,    SIGNAL( SelectionDone() ), SLOT( OnSelectionDone() ) );
103
104   aGroupArgsLayout->addWidget( myLengthArgs );
105   aGroupArgsLayout->addWidget( myDiameterArgs );
106   aGroupArgsLayout->addWidget( myAngleArgs );
107
108   // construct main layout
109   QVBoxLayout* aCustomWidLayout = new QVBoxLayout( centralWidget() );
110   aCustomWidLayout->setMargin( 0 ); 
111   aCustomWidLayout->setSpacing( 6 );
112   aCustomWidLayout->addWidget( aGroupArgs );
113
114   // add visibility rules for structural widgets
115   connect( aTypeButtonLength,   SIGNAL( toggled(bool) ), myLengthArgs,   SLOT( setVisible(bool) ) );
116   connect( aTypeButtonDiameter, SIGNAL( toggled(bool) ), myDiameterArgs, SLOT( setVisible(bool) ) );
117   connect( aTypeButtonAngle,    SIGNAL( toggled(bool) ), myAngleArgs,    SLOT( setVisible(bool) ) );
118
119   // signals and slots connections
120   connect( buttonOk(),    SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) );
121   connect( buttonApply(), SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) );
122
123   // map functional signals
124   myRBGroup->setId( aTypeButtonLength,   TypeButtonID_Length );
125   myRBGroup->setId( aTypeButtonDiameter, TypeButtonID_Diameter );
126   myRBGroup->setId( aTypeButtonAngle,    TypeButtonID_Angle );
127
128   connect( this, SIGNAL( constructorsClicked( int ) ), SLOT( ConstructTypeChanged( int ) ) );
129   connect( myLengthArgs,   SIGNAL( TabChanged() ), SLOT( OnArgumentTabChanged() ) );
130   connect( myDiameterArgs, SIGNAL( TabChanged() ), SLOT( OnArgumentTabChanged() ) );
131   connect( myAngleArgs,    SIGNAL( TabChanged() ), SLOT( OnArgumentTabChanged() ) );
132
133   myDimensionInteractor = new MeasureGUI_DimensionInteractor( theGUI, theParent );
134
135   myDiameterArgs->setVisible( false );
136   myAngleArgs   ->setVisible( false );
137   myLengthArgs  ->setVisible( true );
138
139   myRBGroup->button( TypeButtonID_Length )->click();
140
141   Init();
142
143   setHelpFileName("add_dimension_page.html");
144 }
145
146 //=================================================================================
147 // function : Destructor
148 // purpose  :
149 //=================================================================================
150 MeasureGUI_CreateDimensionDlg::~MeasureGUI_CreateDimensionDlg()
151 {
152 }
153
154 //=================================================================================
155 // function : ActiveArgs
156 // purpose  : 
157 //=================================================================================
158 MeasureGUI_CreateDimensionDlg::BaseSelectorPane* MeasureGUI_CreateDimensionDlg::ActiveArgs()
159 {
160   switch ( getConstructorId() )
161   {
162     case TypeButtonID_Length   : return myLengthArgs;
163     case TypeButtonID_Diameter : return myDiameterArgs;
164     case TypeButtonID_Angle    : return myAngleArgs;
165     default:
166       return NULL;
167   }
168 }
169
170 //=================================================================================
171 // function : GenerateName
172 // purpose  : 
173 //=================================================================================
174 QString MeasureGUI_CreateDimensionDlg::GenerateName( const QString& thePrefix )
175 {
176   QRegExp anExtractIds( "^" + thePrefix + "_([0-9]+)$" );
177
178   QSet<int> anOccupiedIds;
179
180   GEOMGUI_DimensionProperty aProp =
181     getStudy()->getObjectProperty( GEOM::sharedPropertiesId(),
182                                    myParentObj->GetStudyEntry(),
183                                    GEOM::propertyName( GEOM::Dimensions ),
184                                    QVariant() )
185                                    .value<GEOMGUI_DimensionProperty>();
186
187   // get names and convert to QStrings to perform index matching
188   for( int anIt = 0; anIt < aProp.GetNumber(); ++anIt )
189   {
190     if ( anExtractIds.indexIn( aProp.GetName( anIt ) ) == -1 )
191     {
192       continue;
193     }
194
195     anOccupiedIds.insert( anExtractIds.cap( 1 ).toInt() );
196   }
197
198   int aSearchId = 1;
199   while ( true )
200   {
201     if ( !anOccupiedIds.contains( aSearchId ) )
202     {
203       break;
204     }
205
206     aSearchId++;
207   }
208
209   return QString( thePrefix + "_%1" ).arg( aSearchId );
210 }
211
212 //=================================================================================
213 // function : ConstructTypeChanged
214 // purpose  : 
215 //=================================================================================
216 void MeasureGUI_CreateDimensionDlg::ConstructTypeChanged( int theType )
217 {
218   ActiveArgs()->Reset();
219
220   updateGeometry();
221
222   QString aName;
223   switch ( theType )
224   {
225     case TypeButtonID_Length   : aName = GenerateName( tr("NAME_LENGTH") );   break;
226     case TypeButtonID_Diameter : aName = GenerateName( tr("NAME_DIAMETER") ); break;
227     case TypeButtonID_Angle    : aName = GenerateName( tr("NAME_ANGLE") );    break;
228   }
229
230   myMainFrame->ResultName->setText( aName );
231
232   StopLocalEditing();
233   erasePreview();
234
235   updateGeometry();
236   resize( minimumSizeHint() );
237 }
238
239 //=================================================================================
240 // function : OnArgumentTabChanged
241 // purpose  : 
242 //=================================================================================
243 void MeasureGUI_CreateDimensionDlg::OnArgumentTabChanged()
244 {
245   StopLocalEditing();
246   erasePreview();
247 }
248
249 //=================================================================================
250 // function : OnStartSelection
251 // purpose  :
252 //=================================================================================
253 void MeasureGUI_CreateDimensionDlg::OnStartSelection( const QList<TopAbs_ShapeEnum>& theModes )
254 {
255   OnStopSelection();
256
257   StopLocalEditing();
258
259   QList<TopAbs_ShapeEnum>::const_iterator aModeIt = theModes.constBegin();
260   for ( ; aModeIt != theModes.constEnd(); ++aModeIt )
261   {
262     localSelection( myParentObj.get(), *aModeIt );
263   }
264
265   mySelectionModes = theModes;
266
267   connect( myGeomGUI->getApp()->selectionMgr(),
268            SIGNAL( currentSelectionChanged() ),
269            SLOT( SelectionIntoArgument() ) );
270 }
271
272 //=================================================================================
273 // function : OnStopSelection
274 // purpose  :
275 //=================================================================================
276 void MeasureGUI_CreateDimensionDlg::OnStopSelection()
277 {
278   globalSelection();
279
280   disconnect( myGeomGUI->getApp()->selectionMgr(),
281               SIGNAL( currentSelectionChanged() ),
282               this,
283               SLOT( SelectionIntoArgument() ) );
284 }
285
286 //=================================================================================
287 // function : SelectionIntoArgument
288 // purpose  : Handle model selection by active selector pane
289 //=================================================================================
290 void MeasureGUI_CreateDimensionDlg::SelectionIntoArgument()
291 {
292   LightApp_SelectionMgr* aSelectionMgr = myGeomGUI->getApp()->selectionMgr();
293   SALOME_ListIO aSelection;
294   aSelectionMgr->selectedObjects( aSelection );
295
296   if ( aSelection.Extent() != 1 )
297   {
298     ActiveArgs()->SelectionIntoArguments( GEOM::GeomObjPtr() );
299     return;
300   }
301
302   GEOM::GeomObjPtr aSelected = getSelected( mySelectionModes );
303   if ( aSelected.isNull() )
304   {
305     ActiveArgs()->SelectionIntoArguments( GEOM::GeomObjPtr() );
306     return;
307   }
308
309   GEOM::GeomObjPtr aSelectedMain = 
310     !aSelected->IsMainShape() 
311       ? aSelected->GetMainShape() 
312       : GEOM::GeomObjPtr();
313
314   if ( myParentObj != aSelected && myParentObj != aSelectedMain )
315   {
316     ActiveArgs()->SelectionIntoArguments( GEOM::GeomObjPtr() );
317     return;
318   }
319
320   StopLocalEditing();
321
322   erasePreview();
323
324   ActiveArgs()->SelectionIntoArguments( aSelected );
325 }
326
327 //=================================================================================
328 // function : OnSelectionDone
329 // purpose  :
330 //=================================================================================
331 void MeasureGUI_CreateDimensionDlg::OnSelectionDone()
332 {
333   // create new dimension presentation
334   myDimension = CreateDimension();
335
336   if ( myDimension.IsNull() )
337   {
338     // can not create preview, repeat selection
339     SUIT_MessageBox::warning( this,
340                               tr( "WARNING_TITLE_CANNOT_CREATE_DIMENSION" ),
341                               tr( "WARNING_MSG_INVALID_ARGUMENTS" ) );
342
343     ActiveArgs()->Reset();
344
345     return;
346   }
347
348   // show preview of dimension object
349   SUIT_ViewWindow* aViewWindow = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
350
351   SOCC_Prs* aSalomePrs = dynamic_cast<SOCC_Prs*>( ( (SOCC_Viewer*)( aViewWindow->getViewManager()->getViewModel() ) )->CreatePrs( 0 ) );
352
353   aSalomePrs->AddObject( myDimension );
354
355   displayPreview( aSalomePrs );
356
357   StartLocalEditing();
358 }
359
360 //=================================================================================
361 // function : ClickOnOk
362 // purpose  : 
363 //=================================================================================
364 void MeasureGUI_CreateDimensionDlg::ClickOnOk()
365 {
366   setIsApplyAndClose( true );
367   if ( ClickOnApply() )
368   {
369     ClickOnCancel();
370   }
371 }
372
373 //=================================================================================
374 // function : ClickOnApply
375 // purpose  : 
376 //=================================================================================
377 bool MeasureGUI_CreateDimensionDlg::ClickOnApply()
378 {
379   StopLocalEditing();
380
381   if ( myDimension.IsNull() )
382   {
383     return true;
384   }
385
386   if ( !AddDimensionToOwner() )
387   {
388     return false;
389   }
390
391   redisplay( myParentObj.get() );
392
393   if ( !isApplyAndClose() )
394   {
395     emit applyClicked();
396     Init();
397     ConstructTypeChanged( getConstructorId() );
398   }
399
400   return true;
401 }
402
403 //=================================================================================
404 // function : StartLocalEditing
405 // purpose  : 
406 //=================================================================================
407 void MeasureGUI_CreateDimensionDlg::StartLocalEditing()
408 {
409   StopLocalEditing();
410
411   myDimensionInteractor->Enable();
412
413   if ( myDimension.IsNull() )
414   {
415     return;
416   }
417
418   SalomeApp_Application* anApp = myGeomGUI->getApp();
419
420   SUIT_ViewManager* aViewMgr = anApp->activeViewManager();
421
422   if ( aViewMgr->getType() != OCCViewer_Viewer::Type() )
423   {
424     return;
425   }
426
427   SOCC_Viewer* anOCCViewer = dynamic_cast<SOCC_Viewer*>( aViewMgr->getViewModel() );
428
429   myEditingViewer = anOCCViewer;
430   if ( !myEditingViewer )
431   {
432     return;
433   }
434
435   Handle(AIS_InteractiveContext) anAISContext = myEditingViewer->getAISContext();
436   Handle(V3d_Viewer)             aViewer3d    = myEditingViewer->getViewer3d();
437
438   aViewer3d->AddZLayer( myEditingLayer );
439 #if OCC_VERSION_LARGE <= 0x07030000
440   anAISContext->OpenLocalContext( Standard_False, Standard_False );
441 #endif
442   anAISContext->Load( myDimension, AIS_DSM_All );
443   anAISContext->SetZLayer( myDimension, myEditingLayer );
444   anAISContext->Activate( myDimension, AIS_DSM_Line );
445   anAISContext->Activate( myDimension, AIS_DSM_Text );
446   anAISContext->Redisplay( myDimension , Standard_True );
447 }
448
449 //=================================================================================
450 // function : StopLocalEditing
451 // purpose  : 
452 //=================================================================================
453 void MeasureGUI_CreateDimensionDlg::StopLocalEditing()
454 {
455   myDimensionInteractor->Disable();
456
457   if ( !myEditingViewer )
458   {
459     return;
460   }
461
462   Handle(AIS_InteractiveContext) anAISContext = myEditingViewer->getAISContext();
463   Handle(V3d_Viewer)             aViewer3d    = myEditingViewer->getViewer3d();
464
465   aViewer3d->RemoveZLayer( myEditingLayer );
466 #if OCC_VERSION_LARGE <= 0x07030000
467   anAISContext->CloseLocalContext( Standard_True );
468 #else
469   anAISContext->Deactivate();
470   anAISContext->Activate(0);
471 #endif
472
473   myEditingViewer = NULL;
474 }
475
476 //=================================================================================
477 // function : Init
478 // purpose  : 
479 //=================================================================================
480 void MeasureGUI_CreateDimensionDlg::Init()
481 {
482   myDimension = NULL;
483
484   StopLocalEditing();
485
486   erasePreview();
487
488   myDiameterArgs->Reset();
489   myLengthArgs->Reset();
490   myAngleArgs->Reset();
491 }
492
493 //=================================================================================
494 // function : CreateDimensionPrs
495 // purpose  : 
496 //=================================================================================
497 Handle(AIS_Dimension) MeasureGUI_CreateDimensionDlg::CreateDimension()
498 {
499   Handle(AIS_Dimension) aDimensionIO;
500
501   // prepare dimension styling
502   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
503
504   QColor  aQColor       = aResMgr->colorValue  ( "Geometry", "dimensions_color", QColor( 0, 255, 0 ) );
505   int     aLineWidth    = aResMgr->integerValue( "Geometry", "dimensions_line_width", 1 );
506   QFont   aFont         = aResMgr->fontValue   ( "Geometry", "dimensions_font", QFont("Y14.5M-2009", 14) );
507   double  anArrowLength = aResMgr->doubleValue ( "Geometry", "dimensions_arrow_length", 5 );
508   double  aDefFlyout    = aResMgr->doubleValue ( "Geometry", "dimensions_default_flyout", 20 );
509   bool    isUnitsShown  = aResMgr->booleanValue( "Geometry", "dimensions_show_units", false );
510   QString aUnitsLength  = aResMgr->stringValue ( "Geometry", "dimensions_length_units", "m" );
511   QString aUnitsAngle   = aResMgr->stringValue ( "Geometry", "dimensions_angle_units", "deg" );
512   bool    aUseText3d    = aResMgr->booleanValue( "Geometry", "dimensions_use_text3d", false );
513
514   OCCViewer_ViewWindow* anActiveView = NULL;
515
516   SalomeApp_Application* anApp = myGeomGUI->getApp();
517
518   if ( anApp )
519   {
520     OCCViewer_ViewManager* aViewMgr = (OCCViewer_ViewManager*) anApp->getViewManager( OCCViewer_Viewer::Type(), false );
521     if ( aViewMgr )
522     {
523       anActiveView = (OCCViewer_ViewWindow*) aViewMgr->getActiveView();
524     }
525   }
526
527   MeasureGUI_DimensionCreateTool aTool;
528
529   aTool.Settings.DefaultFlyout = aDefFlyout;
530   aTool.Settings.ActiveView    = anActiveView ? anActiveView->getViewPort()->getView() : NULL;
531
532   switch ( getConstructorId() )
533   {
534     // create length dimension
535     case TypeButtonID_Length :
536     {
537       LengthPane* aLengthPane = qobject_cast<LengthPane*>( ActiveArgs() );
538
539       switch (aLengthPane->ActiveTab())
540       {
541         case LengthPane::TabID_SingleEdge:
542         {
543           const GEOM::GeomObjPtr& anEdge = aLengthPane->GetSingleEdge();
544
545           aDimensionIO = aTool.LengthOnEdge( anEdge );
546           break;
547         }
548
549         case LengthPane::TabID_TwoPoints:
550         {
551           const GEOM::GeomObjPtr& aPoint1 = aLengthPane->GetPoint1();
552           const GEOM::GeomObjPtr& aPoint2 = aLengthPane->GetPoint2();
553
554           aDimensionIO = aTool.LengthByPoints( aPoint1, aPoint2 );
555           break;
556         }
557
558         case LengthPane::TabID_ParallelEdges:
559         {
560           const GEOM::GeomObjPtr& anEdge1 = aLengthPane->GetEdge1();
561           const GEOM::GeomObjPtr& anEdge2 = aLengthPane->GetEdge2();
562
563           aDimensionIO = aTool.LengthByParallelEdges( anEdge1, anEdge2 );
564           break;
565         }
566       }
567     }
568     break;
569
570     // create diameter dimension
571     case TypeButtonID_Diameter :
572     {
573       DiameterPane* aDiameterPane = qobject_cast<DiameterPane*>( ActiveArgs() );
574
575       const GEOM::GeomObjPtr& aShape = aDiameterPane->GetShape();
576
577       aDimensionIO = aTool.Diameter( aShape );
578       break;
579     }
580
581     // create angle dimension
582     case TypeButtonID_Angle :
583     {
584       AnglePane* anAnglePane = qobject_cast<AnglePane*>( ActiveArgs() );
585
586       switch (ActiveArgs()->ActiveTab())
587       {
588         case AnglePane::TabID_TwoEdges:
589         {
590           const GEOM::GeomObjPtr& anEdge1 = anAnglePane->GetEdge1();
591           const GEOM::GeomObjPtr& anEdge2 = anAnglePane->GetEdge2();
592
593           aDimensionIO = aTool.AngleByTwoEdges( anEdge1, anEdge2 );
594           break;
595         }
596
597         case AnglePane::TabID_ThreePoints:
598         {
599           const GEOM::GeomObjPtr& aPoint1 = anAnglePane->GetPoint1();
600           const GEOM::GeomObjPtr& aPoint2 = anAnglePane->GetPoint2();
601           const GEOM::GeomObjPtr& aPoint3 = anAnglePane->GetPoint3();
602
603           aDimensionIO = aTool.AngleByThreePoints( aPoint1, aPoint2, aPoint3 );
604           break;
605         }
606       }
607       break;
608     }
609   }
610
611   if ( aDimensionIO.IsNull() )
612   {
613     return NULL;
614   }
615
616   Quantity_Color aColor( aQColor.redF(), aQColor.greenF(), aQColor.blueF(), Quantity_TOC_RGB );
617
618   Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect();
619
620   aStyle->SetCommonColor( aColor );
621   aStyle->MakeUnitsDisplayed( (Standard_Boolean) isUnitsShown );
622   aStyle->MakeText3d( aUseText3d );
623   aStyle->MakeTextShaded( Standard_True );
624   int fsize = aFont.pixelSize() != -1 ? aFont.pixelSize() : aFont.pointSize();
625   aStyle->SetExtensionSize( fsize * 0.5 );
626   aStyle->TextAspect()->SetFont( aFont.family().toLatin1().data() );
627   aStyle->TextAspect()->SetHeight( fsize );
628   aStyle->ArrowAspect()->SetLength( anArrowLength );
629   aStyle->LineAspect()->SetWidth( aLineWidth );
630
631   if ( aDimensionIO->IsKind( STANDARD_TYPE(AIS_AngleDimension) ) )
632   {
633     // show degree symbol for dimension instead of label "deg"
634     if ( aUnitsAngle == "deg" )
635     {
636       aDimensionIO->SetSpecialSymbol(0xB0);
637       aDimensionIO->SetDisplaySpecialSymbol( isUnitsShown ? AIS_DSS_After : AIS_DSS_No );
638       aStyle->MakeUnitsDisplayed(Standard_False);
639     }
640     else
641     {
642       aDimensionIO->SetDisplaySpecialSymbol(AIS_DSS_No);
643       aStyle->MakeUnitsDisplayed( (Standard_Boolean) isUnitsShown );
644     }
645   }
646   else
647   {
648     aStyle->MakeUnitsDisplayed( (Standard_Boolean) isUnitsShown );
649   }
650
651   aDimensionIO->Attributes()->SetDimLengthDisplayUnits( aUnitsLength.toLatin1().data() );
652   aDimensionIO->Attributes()->SetDimAngleDisplayUnits( aUnitsAngle.toLatin1().data() );
653   aDimensionIO->SetDimensionAspect( aStyle );
654   aDimensionIO->SetPolygonOffsets( Aspect_POM_Fill, -1.0, -1.0 );
655
656   return aDimensionIO;
657 }
658
659 //=================================================================================
660 // class    : AddDimensionToOwner
661 // purpose  : 
662 //=================================================================================
663 bool MeasureGUI_CreateDimensionDlg::AddDimensionToOwner()
664 {
665   if ( myDimension.IsNull() )
666   {
667     return false;
668   }
669
670   gp_Ax3 aLCS;
671   TopoDS_Shape anParentSh;
672   if ( GEOMBase::GetShape( myParentObj.get(), anParentSh ) )
673   {
674     aLCS = gp_Ax3().Transformed( anParentSh.Location().Transformation() );
675   }
676
677   QString aName = getNewObjectName();
678
679   SalomeApp_Study* aStudy = getStudy();
680
681   GEOMGUI_DimensionProperty aProp =
682     aStudy->getObjectProperty( GEOM::sharedPropertiesId(),
683                                myParentObj->GetStudyEntry(),
684                                GEOM::propertyName( GEOM::Dimensions ),
685                                QVariant() )
686                                .value<GEOMGUI_DimensionProperty>();
687
688   // append new dimension record to data
689   aProp.AddRecord( myDimension, aLCS );
690   aProp.SetName( aProp.GetNumber() - 1, aName );
691   aProp.SetVisible( aProp.GetNumber() - 1, true );
692
693   // store modified property data
694   aStudy->setObjectProperty( GEOM::sharedPropertiesId(),
695                              myParentObj->GetStudyEntry(),
696                              GEOM::propertyName( GEOM::Dimensions ),
697                              aProp );
698
699   return true;
700 }
701
702 /* ------------------------------------------------------------------------------*
703  *                                                                               *
704  *                    Argument shape selector layout                             *
705  *                                                                               *
706  * ------------------------------------------------------------------------------*/
707
708 //=================================================================================
709 // class    : MeasureGUI_CreateDimensionDlg::LengthPane
710 // purpose  : Constructor
711 //=================================================================================
712 MeasureGUI_CreateDimensionDlg::LengthPane::LengthPane( QWidget* theParent )
713 : BaseSelectorPane( theParent )
714 {
715   myTabs                   = new QTabWidget( this );
716   mySingleEdgeSelectors    = new MeasureGUI_1Sel_Frame( this );
717   myTwoPointsSelectors     = new MeasureGUI_2Sel_Frame( this );
718   myParallelEdgesSelectors = new MeasureGUI_2Sel_Frame( this );
719
720   myTabs->addTab( mySingleEdgeSelectors,    MeasureGUI_CreateDimensionDlg::tr( "EDGE_LENGTH" ) );
721   myTabs->addTab( myTwoPointsSelectors,     MeasureGUI_CreateDimensionDlg::tr( "TWO_POINTS" ) );
722   myTabs->addTab( myParallelEdgesSelectors, MeasureGUI_CreateDimensionDlg::tr( "PARALLEL_EDGES" ) );
723
724   mySingleEdgeSelectors->PushButton1->setIcon( mySelectorIcon );
725   mySingleEdgeSelectors->TextLabel1->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE" ) );
726   mySingleEdgeSelectors->LineEdit1->setReadOnly( true );
727
728   myTwoPointsSelectors->PushButton1->setIcon( mySelectorIcon );
729   myTwoPointsSelectors->PushButton2->setIcon( mySelectorIcon );
730   myTwoPointsSelectors->TextLabel1->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_1" ) );
731   myTwoPointsSelectors->TextLabel2->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_2" ) );
732   myTwoPointsSelectors->LineEdit1->setReadOnly( true );
733   myTwoPointsSelectors->LineEdit2->setReadOnly( true );
734
735   myParallelEdgesSelectors->PushButton1->setIcon( mySelectorIcon );
736   myParallelEdgesSelectors->PushButton2->setIcon( mySelectorIcon );
737   myParallelEdgesSelectors->TextLabel1 ->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE_1" ) );
738   myParallelEdgesSelectors->TextLabel2 ->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE_2" ) );
739   myParallelEdgesSelectors->LineEdit1->setReadOnly( true );
740   myParallelEdgesSelectors->LineEdit2->setReadOnly( true );
741
742   QVBoxLayout* aLayout = new QVBoxLayout( this );
743
744   aLayout->setMargin( 0 );
745   aLayout->addWidget( myTabs );
746
747   SelectionModes anEdgeModes;
748   SelectionModes aPointModes;
749   anEdgeModes << TopAbs_EDGE;
750   aPointModes << TopAbs_VERTEX;
751
752   SetTabWidget( myTabs );
753   RegisterSelector( mySingleEdgeSelectors->LineEdit1,    mySingleEdgeSelectors->PushButton1,    anEdgeModes, TabID_SingleEdge );
754   RegisterSelector( myTwoPointsSelectors->LineEdit1,     myTwoPointsSelectors->PushButton1,     aPointModes, TabID_TwoPoints );
755   RegisterSelector( myTwoPointsSelectors->LineEdit2,     myTwoPointsSelectors->PushButton2,     aPointModes, TabID_TwoPoints );
756   RegisterSelector( myParallelEdgesSelectors->LineEdit1, myParallelEdgesSelectors->PushButton1, anEdgeModes, TabID_ParallelEdges );
757   RegisterSelector( myParallelEdgesSelectors->LineEdit2, myParallelEdgesSelectors->PushButton2, anEdgeModes, TabID_ParallelEdges );
758 }
759
760 //=================================================================================
761 // class    : MeasureGUI_CreateDimensionDlg::DiameterPane
762 // purpose  : Constructor
763 //=================================================================================
764 MeasureGUI_CreateDimensionDlg::DiameterPane::DiameterPane( QWidget* theParent )
765 : BaseSelectorPane( theParent )
766 {
767   myShapeSelector = new MeasureGUI_1Sel_Frame( this );
768   myShapeSelector->PushButton1->setIcon( mySelectorIcon );
769   myShapeSelector->TextLabel1 ->setText( MeasureGUI_CreateDimensionDlg::tr( "OBJECT" ) );
770
771   QVBoxLayout* aLayout = new QVBoxLayout( this );
772
773   aLayout->setMargin( 0 );
774   aLayout->addWidget( myShapeSelector );
775
776   SelectionModes aDiamModes;
777   aDiamModes << TopAbs_SHAPE
778              << TopAbs_FACE
779              << TopAbs_EDGE;
780
781   RegisterSelector( myShapeSelector->LineEdit1, myShapeSelector->PushButton1, aDiamModes );
782 }
783
784 //=================================================================================
785 // class    : MeasureGUI_CreateDimensionDlg::AnglePane
786 // purpose  : Constructor
787 //=================================================================================
788 MeasureGUI_CreateDimensionDlg::AnglePane::AnglePane( QWidget* theParent )
789 : BaseSelectorPane( theParent )
790 {
791   myTabs                 = new QTabWidget( this );
792   myTwoEdgesSelectors    = new MeasureGUI_2Sel_Frame( this );
793   myThreePointsSelectors = new MeasureGUI_3Sel_Frame( this );
794
795   myTabs->addTab( myTwoEdgesSelectors,    MeasureGUI_CreateDimensionDlg::tr( "TWO_EDGES" ) );
796   myTabs->addTab( myThreePointsSelectors, MeasureGUI_CreateDimensionDlg::tr( "THREE_POINTS" ) );
797
798   myTwoEdgesSelectors->PushButton1->setIcon( mySelectorIcon );
799   myTwoEdgesSelectors->PushButton2->setIcon( mySelectorIcon );
800   myTwoEdgesSelectors->TextLabel1 ->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE_1" ) );
801   myTwoEdgesSelectors->TextLabel2 ->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE_2" ) );
802
803   myThreePointsSelectors->PushButton1->setIcon( mySelectorIcon );
804   myThreePointsSelectors->PushButton2->setIcon( mySelectorIcon );
805   myThreePointsSelectors->PushButton3->setIcon( mySelectorIcon );
806   myThreePointsSelectors->TextLabel1 ->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_1" ) );
807   myThreePointsSelectors->TextLabel2 ->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_2" ) );
808   myThreePointsSelectors->TextLabel3 ->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_3" ) );
809
810   QVBoxLayout* aLayout = new QVBoxLayout( this );
811
812   aLayout->setMargin( 0 );
813   aLayout->addWidget( myTabs );
814
815   SelectionModes anEdgeModes;
816   SelectionModes aPointModes;
817   anEdgeModes << TopAbs_EDGE;
818   aPointModes << TopAbs_VERTEX;
819
820   SetTabWidget( myTabs );
821   RegisterSelector( myTwoEdgesSelectors->LineEdit1,    myTwoEdgesSelectors->PushButton1,    anEdgeModes, TabID_TwoEdges );
822   RegisterSelector( myTwoEdgesSelectors->LineEdit2,    myTwoEdgesSelectors->PushButton2,    anEdgeModes, TabID_TwoEdges );
823   RegisterSelector( myThreePointsSelectors->LineEdit1, myThreePointsSelectors->PushButton1, aPointModes, TabID_ThreePoints );
824   RegisterSelector( myThreePointsSelectors->LineEdit2, myThreePointsSelectors->PushButton2, aPointModes, TabID_ThreePoints );
825   RegisterSelector( myThreePointsSelectors->LineEdit3, myThreePointsSelectors->PushButton3, aPointModes, TabID_ThreePoints );
826 }
827
828 /* ------------------------------------------------------------------------------*
829  *                                                                               *
830  *                   Argument shape selection logics                             *
831  *                                                                               *
832  * ------------------------------------------------------------------------------*/
833
834 //=================================================================================
835 // class    : MeasureGUI_CreateDimensionDlg::BaseSelectorPane
836 // purpose  : Constructor
837 //=================================================================================
838 MeasureGUI_CreateDimensionDlg::BaseSelectorPane::BaseSelectorPane( QWidget* theParent )
839 : QWidget( theParent ),
840   myTabs( NULL )
841 {
842   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
843   mySelectorIcon = aResMgr->loadPixmap( "GEOM", tr( "ICON_SELECT" ) );
844 }
845
846 //=================================================================================
847 // function : BaseSelectorPane::Reset
848 // purpose  : Reset selector line edits and controls
849 //=================================================================================
850 void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::Reset( bool theOpenDefaultTab )
851 {
852   if ( theOpenDefaultTab && myTabs )
853   {
854     myTabs->setCurrentIndex( 0 );
855   }
856
857   QMap< int, QList<QLineEdit*> >::iterator aTabsIt = mySelectors.begin();
858   for ( ; aTabsIt != mySelectors.end(); ++aTabsIt )
859   {
860     QList<QLineEdit*>& aSelectors = *aTabsIt;
861     QList<QLineEdit*>::iterator aSelectorIt = aSelectors.begin();
862     for ( ; aSelectorIt != aSelectors.end(); ++aSelectorIt )
863     {
864       QLineEdit* aSelector = *aSelectorIt;
865       aSelector->clear();
866       mySelectedShapes[aSelector] = GEOM::GeomObjPtr();
867     }
868   }
869
870   QLineEdit* aFirstSelector = mySelectors[ ActiveTab() ].first();
871
872   mySelectionButtons[aFirstSelector]->click();
873 }
874
875 //=================================================================================
876 // function : BaseSelectorPane::ActiveTab
877 // purpose  : Returns active tab
878 //=================================================================================
879 int MeasureGUI_CreateDimensionDlg::BaseSelectorPane::ActiveTab() const
880 {
881   return myTabs != NULL ? myTabs->currentIndex() : 0;
882 }
883
884 //=================================================================================
885 // function : BaseSelectorPane::SelectionIntoArgument
886 // purpose  : Populates current selector
887 //=================================================================================
888 void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::SelectionIntoArguments( const GEOM::GeomObjPtr& theSelected )
889 {
890   if ( theSelected.isNull() )
891   {
892     myCurrentSelector->clear();
893     mySelectedShapes[myCurrentSelector] = GEOM::GeomObjPtr();
894     return;
895   }
896
897   QString aName = GEOMBase::GetName( theSelected.get() );
898
899   myCurrentSelector->setText( aName );
900
901   mySelectedShapes[myCurrentSelector] = theSelected;
902
903   // find next empty selector (iterate to the last)
904   QList<QLineEdit*>& aCurrentSelectors = mySelectors[ ActiveTab() ];
905   int aCurrentPos = aCurrentSelectors.indexOf( myCurrentSelector );
906   int aSelectorIt = aCurrentPos + 1;
907   for ( ; aSelectorIt != aCurrentSelectors.size(); ++aSelectorIt )
908   {
909     QLineEdit* aNextSelector = aCurrentSelectors[aSelectorIt];
910     if ( mySelectedShapes[aNextSelector].isNull() )
911     {
912       mySelectionButtons[aNextSelector]->click();
913       return;
914     }
915   }
916
917   // find next empty selector (itearte from the first)
918   aSelectorIt = 0;
919   for ( ; aSelectorIt != aCurrentPos; ++aSelectorIt )
920   {
921     QLineEdit* aNextSelector = aCurrentSelectors[aSelectorIt];
922     if ( mySelectedShapes[aNextSelector].isNull() )
923     {
924       mySelectionButtons[aNextSelector]->click();
925       return;
926     }
927   }
928
929   // stop selector switching
930   myCurrentSelector->setEnabled( false );
931   mySelectionButtons[myCurrentSelector]->setDown( false );
932
933   // every selector is populated - construct presentation
934   emit StopSelection();
935   emit SelectionDone();
936 }
937
938 //=================================================================================
939 // function : BaseSelectorPane::GetSelection
940 // purpose  : 
941 //=================================================================================
942 GEOM::GeomObjPtr MeasureGUI_CreateDimensionDlg::BaseSelectorPane::GetSelection( QLineEdit* theSelector ) const
943 {
944   return mySelectedShapes[theSelector];
945 }
946
947 //=================================================================================
948 // function : BaseSelectorPane::OnSelectorClicked
949 // purpose  : Handle activation of selector controls pair {edit, button}
950 //=================================================================================
951 void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::OnSelectorClicked()
952 {
953   // clicked "selector" button
954   QAbstractButton* aSender = qobject_cast<QAbstractButton*>( sender() );
955   if ( !aSender )
956   {
957     return;
958   }
959
960   // get "selector" controls on the active tab
961   QList<QLineEdit*>& aCurrentSelectors = mySelectors[ ActiveTab() ];
962
963   // iterate over controls on the tab and process them
964   for ( int aSelectorIt = 0; aSelectorIt < aCurrentSelectors.size(); ++aSelectorIt )
965   {
966     QLineEdit* aSelector = aCurrentSelectors[aSelectorIt];
967     QPushButton* aButton = mySelectionButtons[aSelector];
968
969     bool isClickedOnes = (aButton == aSender);
970
971     aSelector->setEnabled( isClickedOnes );
972
973     if ( isClickedOnes )
974     {
975       myCurrentSelector = aSelector;
976       myCurrentSelector->setFocus();
977     }
978
979     aButton->setDown( isClickedOnes );
980   }
981
982   emit StartSelection( mySelectionModes[myCurrentSelector] );
983 }
984
985 //=================================================================================
986 // function : BaseSelectorPane::OnTabChanged
987 // purpose  :
988 //=================================================================================
989 void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::OnTabChanged()
990 {
991   QList<QLineEdit*>& aSelectors = mySelectors[ ActiveTab() ];
992   QList<QLineEdit*>::iterator aSelectorIt = aSelectors.begin();
993   for ( ; aSelectorIt != aSelectors.end(); ++aSelectorIt )
994   {
995     QLineEdit* aSelector = *aSelectorIt;
996
997     aSelector->clear();
998
999     mySelectedShapes[aSelector] = GEOM::GeomObjPtr();
1000   }
1001
1002   QLineEdit* aFirstSelector = mySelectors[ ActiveTab() ].first();
1003
1004   mySelectionButtons[aFirstSelector]->click();
1005
1006   emit TabChanged();
1007 }
1008
1009 //=================================================================================
1010 // function : BaseSelectorPane::SetTabWidget
1011 // purpose  :
1012 //=================================================================================
1013 void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::SetTabWidget( QTabWidget* theTabs )
1014 {
1015   myTabs = theTabs;
1016   connect( myTabs, SIGNAL( currentChanged( int ) ), this, SLOT( OnTabChanged() ) );
1017 }
1018
1019 //=================================================================================
1020 // function : BaseSelectorPane::RegisterSelector
1021 // purpose  :
1022 //=================================================================================
1023 void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::RegisterSelector( QLineEdit* theSelectorEdit,
1024                                                                         QPushButton* theSelectorButton,
1025                                                                         const SelectionModes& theSelectorModes,
1026                                                                         const int theTab )
1027 {
1028   if ( !mySelectors.contains( theTab ) )
1029   {
1030     mySelectors.insert( theTab, QList<QLineEdit*>() );
1031   }
1032   mySelectors[theTab].append( theSelectorEdit );
1033
1034   mySelectionButtons[theSelectorEdit] = theSelectorButton;
1035   mySelectionModes  [theSelectorEdit] = theSelectorModes;
1036
1037   connect( theSelectorButton, SIGNAL( clicked() ), this, SLOT( OnSelectorClicked() ) );
1038 }