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