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