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