Salome HOME
5e8aca4bdf3e583b6877af4f556f0890487be491
[modules/geom.git] / src / GEOMToolsGUI / GEOMToolsGUI_MaterialPropertiesDlg.cxx
1 // Copyright (C) 2007-2023  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 // File   : GEOMToolsGUI_MaterialPropertiesDlg.cxx
21 // Author : Margarita KARPUNINA, Open CASCADE S.A.S. (margarita.karpunina@opencascade.com)
22
23 #include "GEOMToolsGUI_MaterialPropertiesDlg.h"
24
25 #include "GeometryGUI.h"
26 #include "GEOM_Constants.h"
27 #include "GEOM_VTKPropertyMaterial.hxx"
28 #include "GEOMBase.h"
29 #include "GEOM_Displayer.h"
30
31 #include <QtxColorButton.h>
32 #include <QtxDoubleSpinBox.h>
33 #include <SUIT_Desktop.h>
34 #include <SUIT_MessageBox.h>
35 #include <SUIT_OverrideCursor.h>
36 #include <SUIT_ResourceMgr.h>
37 #include <SUIT_Session.h>
38 #include <SUIT_ViewManager.h>
39 #include <SALOME_ListIO.hxx>
40 #include <OCCViewer_ViewModel.h>
41 #include <SVTK_ViewModel.h>
42 #include <SVTK_ViewWindow.h>
43 #include <SVTK_View.h>
44 #include <LightApp_SelectionMgr.h>
45 #include <SalomeApp_Application.h>
46 #include <SalomeApp_Study.h>
47 #include <SalomeApp_Tools.h>
48
49 #include <QCheckBox>
50 #include <QGridLayout>
51 #include <QHBoxLayout>
52 #include <QKeyEvent>
53 #include <QLabel>
54 #include <QLineEdit>
55 #include <QMap>
56 #include <QMenu>
57 #include <QPushButton>
58 #include <QVBoxLayout>
59
60 #define MARGIN  9  // layout spacing
61 #define SPACING 6  // layout margin
62
63 /*!
64   \class GEOMToolsGUI_MaterialList
65   \brief Internal class, used to handle context menu event from materials list
66   \internal
67 */
68
69 /*!
70   \brief Constructor
71  */
72 GEOMToolsGUI_MaterialList::GEOMToolsGUI_MaterialList( QWidget* parent )
73   : QListWidget( parent )
74 {}
75
76 /*!
77   \brief Context menu event, emits context menu signal passing event as parameter
78 */
79 void GEOMToolsGUI_MaterialList::contextMenuEvent( QContextMenuEvent* e )
80 {
81   emit contextMenu( e );
82 }
83
84 /*!
85   \class GEOMToolsGUI_MaterialPropertiesDlg
86   \brief GEOM material properties dialog box class
87
88   The dialog box is used to set material properties for the presentation objects.
89 */
90
91 /*!
92   \brief Constructor
93   \param parent parent widget
94   \param showSelWidget if \c true then objects can be selected by user
95   \param modal if \c true dialog box is modal
96   \param f specified control buttons for dialog box (QtxDialog::ButtonFlags)
97 */
98 GEOMToolsGUI_MaterialPropertiesDlg::GEOMToolsGUI_MaterialPropertiesDlg( QWidget* parent,bool showSelWidget, bool modal,const int f )
99   : QtxDialog( parent, modal, true, f )
100 {
101   myShowSelWidget = showSelWidget;
102   // Set title
103   setWindowTitle( tr( "MATERIAL_PROPERTIES_TLT" ) );
104         
105   // main layout
106   QVBoxLayout* main = new QVBoxLayout( mainFrame() );
107   main->setMargin( 0 );
108   main->setSpacing( SPACING );
109
110   // add top-level frame box to enclose all main widgets (excluding buttons)
111   QFrame* fr = new QFrame( mainFrame() );
112   fr->setFrameStyle( QFrame::Box | QFrame::Sunken );
113   main->addWidget( fr );
114   // selection widget
115   myLineEditCurArg = new QLineEdit(fr);
116   myLineEditCurArg->setReadOnly(true);
117   myPushBtn = new QPushButton(fr);
118   QLabel* PushBtnLab = new QLabel( tr( "GEOM_OBJECTS" ), fr );
119
120   // materials list widget
121   myMaterials = new GEOMToolsGUI_MaterialList( fr );
122   // properties widget
123   QWidget* propWidget = new QWidget( fr );
124
125   // layout main widgets
126   QHBoxLayout* frLayout = new QHBoxLayout( fr );
127   frLayout->setMargin( MARGIN );
128   frLayout->setSpacing( SPACING );
129   frLayout->addWidget( myMaterials );
130   frLayout->addWidget( propWidget );
131
132   // layout for material properties widgets
133   QGridLayout* propLayout = new QGridLayout( propWidget );
134   propLayout->setMargin( 0 );
135   propLayout->setSpacing( SPACING );
136
137   // current color widgets
138   myColorLab = new QLabel( tr( "CURRENT_COLOR" ), propWidget );
139   myColor = new QtxColorButton( propWidget );
140
141   // "physical" material type widgets
142   myPhysical = new QCheckBox( tr( "PHYSICAL" ), propWidget );
143
144   // Labels for front and back reflection components
145   QLabel* aFrontLabel = new QLabel( tr( "FRONT_FACE" ), propWidget );
146   QLabel* aBackLabel = new QLabel( tr( "BACK_FACE" ), propWidget );
147
148   // reflection components widgets
149   for ( int i = Material_Model::Ambient; i <= Material_Model::Emissive; i++ )
150   {
151     Reflection refl;
152     
153     refl.enabled = new QCheckBox( propWidget );
154
155     refl.label = new QLabel( tr( QString( "REFLECTION_%1" ).arg( i ).toLatin1().data() ), propWidget );
156
157     refl.color = new QtxColorButton( propWidget );
158     //refl.color->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
159
160     refl.front_coef = new QtxDoubleSpinBox( propWidget );
161     refl.front_coef->setPrecision( 4 );
162     refl.front_coef->setDecimals( 4 ); 
163     refl.front_coef->setRange( 0., 1. );
164     refl.front_coef->setSingleStep( 0.05 );
165     refl.front_coef->setMinimumWidth( 80 );
166     
167     refl.back_coef = new QtxDoubleSpinBox( propWidget );
168     refl.back_coef->setPrecision( 4 );
169     refl.back_coef->setDecimals( 4 ); 
170     refl.back_coef->setRange( 0., 1. );
171     refl.back_coef->setSingleStep( 0.05 );
172     refl.back_coef->setMinimumWidth( 80 );
173
174     myReflection << refl;
175   }
176
177   // shininess widgets
178   QLabel* shininessLab = new QLabel( tr( "SHININESS" ), propWidget );
179   myFrontShininess = new QtxDoubleSpinBox( propWidget );
180   myFrontShininess->setPrecision( 4 );
181   myFrontShininess->setDecimals( 4 ); 
182   myFrontShininess->setRange( 0., 1. );
183   myFrontShininess->setSingleStep( 0.05 );
184
185   myBackShininess = new QtxDoubleSpinBox( propWidget );
186   myBackShininess->setPrecision( 4 );
187   myBackShininess->setDecimals( 4 ); 
188   myBackShininess->setRange( 0., 1. );
189   myBackShininess->setSingleStep( 0.05 );
190
191   // separator widgets
192   QFrame* line1 = new QFrame( propWidget );
193   line1->setFrameStyle( QFrame::HLine | QFrame::Sunken );
194   QFrame* line2 = new QFrame( propWidget );
195   line2->setFrameStyle( QFrame::HLine | QFrame::Sunken );
196   QFrame* line3 = new QFrame( propWidget );
197   line3->setFrameStyle( QFrame::VLine | QFrame::Sunken );
198   QFrame* line4 = new QFrame( propWidget );
199   line4->setFrameStyle( QFrame::VLine | QFrame::Sunken );
200   QFrame* line5 = new QFrame( propWidget );
201   line5->setFrameStyle( QFrame::HLine | QFrame::Sunken );
202
203   // add / remove material buttons
204   myAddButton = new QPushButton( tr( "ADD_MATERIAL" ),    propWidget );
205   myDelButton = new QPushButton( tr( "DELETE_MATERIAL" ), propWidget );
206
207   // buttons layout
208   QHBoxLayout* btnLayout = new QHBoxLayout;
209   btnLayout->setMargin( 0 );
210   btnLayout->setSpacing( SPACING );
211   btnLayout->addWidget( myAddButton );
212   btnLayout->addWidget( myDelButton );
213
214   // layout all properties widgets together
215   propLayout->addWidget( PushBtnLab,0,0);
216   propLayout->addWidget( myPushBtn,0,1);
217   propLayout->addWidget( myLineEditCurArg, 0, 2, 1, 5 );
218   propLayout->addWidget( line1, 1, 0, 1, 7 );
219   propLayout->addWidget( myColorLab, 2, 1 );
220   propLayout->addWidget( myColor,    2, 2 );
221   propLayout->addWidget( myPhysical, 2, 0 );
222   propLayout->addWidget( line2, 3, 0, 1, 7 );
223   propLayout->addWidget( aFrontLabel, 4, 4);
224   propLayout->addWidget( aBackLabel, 4, 6);
225   
226   propLayout->addWidget( line3, 4, 3, 6, 1 );
227   propLayout->addWidget( line4, 4, 5, 6, 1 );
228
229   if( !myShowSelWidget ) {
230     myColorLab->hide();
231     myColor->hide();
232     line1->hide();
233     myLineEditCurArg->hide();
234     myPushBtn->hide();
235     PushBtnLab->hide();
236   }
237   for ( int i = Material_Model::Ambient; i <= Material_Model::Emissive; i++ ) {
238     propLayout->addWidget( myReflection[i].enabled, i+5, 0 );
239     propLayout->addWidget( myReflection[i].label,   i+5, 1 );
240     propLayout->addWidget( myReflection[i].color,   i+5, 2 );
241     propLayout->addWidget( myReflection[i].front_coef,    i+5, 4 );
242     propLayout->addWidget( myReflection[i].back_coef,    i+5, 6 );
243   }
244
245   propLayout->addWidget( shininessLab,   9, 0 );
246   propLayout->addWidget( myFrontShininess,    9, 4 );
247   propLayout->addWidget( myBackShininess,    9, 6 );
248   propLayout->addWidget( line5, 10, 0, 1, 7 );
249   propLayout->setRowStretch( 11, 5 );
250   propLayout->addLayout( btnLayout, 12, 0, 1, 7 );
251
252   // initialize dialog box
253   setButtonPosition( Right, Close );
254
255   // fill in the list of materials
256   QStringList globalMaterials = myResourceMgr.materials( Material_ResourceMgr::Global );
257   QStringList userMaterials   = myResourceMgr.materials( Material_ResourceMgr::User );
258
259   QListWidgetItem* item;
260
261   // - current material
262   item = new QListWidgetItem( tr( "CURRENT_MATERIAL" ) );
263   item->setForeground( QColor( Qt::red ) );
264   item->setData( TypeRole, QVariant( Current ) );
265   myMaterials->addItem( item );
266   // - global materials
267   foreach( QString material, globalMaterials ) {
268     item = new QListWidgetItem( material );
269     item->setForeground( QColor( Qt::blue ) );
270     item->setData( TypeRole, QVariant( Global ) );
271     item->setData( NameRole, QVariant( material ) );
272     myMaterials->addItem( item );
273   }
274   // - user materials
275   foreach ( QString material, userMaterials ) {
276     item = new QListWidgetItem( material );
277     item->setData( TypeRole, QVariant( User ) );
278     item->setData( NameRole, QVariant( material ) );
279     item->setFlags( item->flags() | Qt::ItemIsEditable );
280     myMaterials->addItem( item );
281   }
282   // install event filter to the materials list to process key press events
283   myMaterials->installEventFilter( this );
284
285   //Set image
286   myPushBtn->setIcon(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_SELECT")));
287
288   // connect signals
289   // note: all widgets, that change material properties, are connected to the common signal
290   // changed(), instead of connecting directly to the slot - this allows easy temporary blocking 
291   // of the change signal
292   connect( myPhysical, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) ); 
293   for ( int i = Material_Model::Ambient; i <= Material_Model::Emissive; i++ ) {
294     connect( myReflection[i].color,   SIGNAL( changed( QColor ) ),   this, SIGNAL( changed() ) );
295     connect( myReflection[i].front_coef,    SIGNAL( valueChanged( double ) ), this, SIGNAL( changed() ) );
296     connect( myReflection[i].back_coef,    SIGNAL( valueChanged( double ) ), this, SIGNAL( changed() ) );
297     connect( myReflection[i].enabled, SIGNAL( toggled( bool ) ),     this, SIGNAL( changed() ) );
298   }
299   connect( myFrontShininess, SIGNAL( valueChanged( double ) ), this, SIGNAL( changed() ) );
300   connect( myBackShininess, SIGNAL( valueChanged( double ) ), this, SIGNAL( changed() ) );
301   connect( myMaterials, SIGNAL( itemSelectionChanged() ),
302            this,        SLOT( onMaterialChanged() ) );
303   connect( myMaterials, SIGNAL( itemChanged( QListWidgetItem* ) ),
304            this,        SLOT( onItemChanged( QListWidgetItem* ) ) );
305   connect( myMaterials, SIGNAL( contextMenu( QContextMenuEvent* ) ),
306            this,        SLOT( onContextMenu( QContextMenuEvent* ) ) );
307   connect( myAddButton, SIGNAL( clicked() ), this, SLOT( onAddMaterial() ) );
308   connect( myDelButton, SIGNAL( clicked() ), this, SLOT( onDeleteMaterial() ) );
309   connect( this, SIGNAL( dlgApply() ), this, SLOT( onApply() ) );
310   connect( this, SIGNAL( dlgHelp() ),  this, SLOT( onHelp() ) );
311   connect( this, SIGNAL( changed() ),  this, SLOT( onChanged() ) );
312   connect(myPushBtn, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
313   connect(((SalomeApp_Application*)(SUIT_Session::session()->activeApplication()))->selectionMgr(),
314            SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
315
316   // initialize current material model according to the selection
317   myColor->setColor( SUIT_Session::session()->resourceMgr()->colorValue( "Geometry", "shading_color", QColor( 255, 0, 0 ) ) );
318   myCurrentModel.fromResources( SUIT_Session::session()->resourceMgr()->stringValue( "Geometry", "material", "Plastic" ) );
319   SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( SUIT_Session::session()->activeApplication() );
320   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( app->activeStudy() );
321   LightApp_SelectionMgr* selMgr = app->selectionMgr();
322   if ( study ) {
323     SALOME_ListIO selected;
324     selMgr->selectedObjects( selected );
325     if ( selected.Extent() > 0 ) {
326       Handle(SALOME_InteractiveObject) io = selected.First();
327       if ( !io.IsNull() ) {
328         SUIT_ViewWindow* window = app->desktop()->activeWindow();
329         if ( window ) {
330           int mgrId = window->getViewManager()->getGlobalId();
331           PropMap propMap = study->getObjectProperties( mgrId, io->getEntry() );
332           QString matProp = propMap.value(GEOM::propertyName( GEOM::Material )).toString();         
333           if ( !matProp.isEmpty() )
334             myCurrentModel.fromProperties( matProp );
335           QColor c = propMap.value(GEOM::propertyName( GEOM::Color )).value<QColor>();
336           if ( c.isValid() )
337             myColor->setColor( c );
338         }
339       }
340     }
341   }
342   myLineEditCurArg->setText(""); 
343   myPushBtn->click();
344   SelectionIntoArgument();
345
346   // finally activate current material properties
347   myMaterials->setCurrentRow( 0 );
348 }
349
350 /*!
351   \brief Destructor
352 */
353 GEOMToolsGUI_MaterialPropertiesDlg::~GEOMToolsGUI_MaterialPropertiesDlg()
354 {
355 }
356
357 /*!
358   \brief Called when "OK" button is clicked
359 */
360 void GEOMToolsGUI_MaterialPropertiesDlg::accept()
361 {
362   onApply();
363   QtxDialog::accept();
364 }
365
366 /*!
367   \brief Event filter
368   \param o sender
369   \param e event
370 */
371 bool GEOMToolsGUI_MaterialPropertiesDlg::eventFilter( QObject* o, QEvent* e )
372 {
373   // process key press event from materials list
374   if ( o == myMaterials && e->type() == QEvent::KeyPress ) {
375     QKeyEvent* ke = (QKeyEvent*)e;
376     if ( ke->key() == Qt::Key_Delete ) {
377       onDeleteMaterial();
378     }
379   }
380   return QtxDialog::eventFilter( o, e );
381 }
382
383 /*!
384   \brief Initialize dialog box widgets from material model
385   \param model material model
386 */
387 void GEOMToolsGUI_MaterialPropertiesDlg::fromModel( const Material_Model& model )
388 {
389   // reflection components
390   for ( int i = Material_Model::Ambient; i <= Material_Model::Emissive; i++ )
391   {
392     myReflection[i].color->setColor( model.color( (Material_Model::ReflectionType)i ) );
393     myReflection[i].front_coef->setValue( model.reflection( (Material_Model::ReflectionType)i, true ) );
394     myReflection[i].back_coef->setValue( model.reflection( (Material_Model::ReflectionType)i, false ) );
395     myReflection[i].enabled->setChecked( model.hasReflection( (Material_Model::ReflectionType)i ) );
396   }
397   
398   // shininess
399   myFrontShininess->setValue( model.shininess( true ) );
400   myBackShininess->setValue( model.shininess( false ) );
401
402   // type (physical or no)
403   myPhysical->setChecked( model.isPhysical() );
404 }
405  
406 /*!
407   \brief Save values from dialog box widgets to material model
408   \param model material model to be filled in
409 */
410 void GEOMToolsGUI_MaterialPropertiesDlg::toModel( Material_Model& model ) const
411 {
412   // type (physical or no)
413   model.setPhysical( myPhysical->isChecked() );
414
415   // shininess
416   model.setShininess( myFrontShininess->value(), true );
417   model.setShininess( myBackShininess->value(), false );
418
419   // reflection components
420   for ( int i = Material_Model::Ambient; i <= Material_Model::Emissive; i++ )
421   {
422     model.setColor     ( (Material_Model::ReflectionType)i, myReflection[i].color->color() );
423     model.setReflection( (Material_Model::ReflectionType)i, myReflection[i].front_coef->value(), true );
424     model.setReflection( (Material_Model::ReflectionType)i, myReflection[i].back_coef->value(), false );
425     model.setReflection( (Material_Model::ReflectionType)i, myReflection[i].enabled->isChecked() );
426   }
427 }
428
429 /*!
430   \brief Find unique name for the material name
431   \param name material name template
432   \param item the item to be ignored when browsing through the materials list
433   \param addSuffix if \c true, the integrer suffix is always added to the material name (otherwise
434   suffix is added only if item name is not unique)
435   \return new unique material name
436 */
437 QString GEOMToolsGUI_MaterialPropertiesDlg::findUniqueName( const QString& name, QListWidgetItem* item, bool addSuffix )
438 {
439   bool found = false;
440   int idx = 0;
441   for( int i = 1; i < myMaterials->count(); i++ ) {
442     if ( item == myMaterials->item( i ) ) continue;
443     QString iname = myMaterials->item( i )->text();
444     if ( iname == name ) {
445       found = true;
446     }
447     else if ( iname.startsWith( name ) ) {
448       iname = iname.mid( name.length() ).trimmed();
449       bool ok = false;
450       int nx = iname.toInt( &ok );
451       if ( ok ) idx = qMax( idx, nx );
452     }
453   }
454   return found || addSuffix ? QString( "%1 %2" ).arg( name ).arg( idx+1 ) : name;
455 }
456
457 /*!
458   \brief Called when "Apply" button is pressed
459 */
460 void GEOMToolsGUI_MaterialPropertiesDlg::onApply()
461 {  
462   // save user materials
463   myResourceMgr.save();
464   if( !myShowSelWidget ) return;
465   // store selected material properties in the current model
466   toModel( myCurrentModel );
467
468   SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( SUIT_Session::session()->activeApplication() );
469   LightApp_SelectionMgr* selMgr = app->selectionMgr();
470   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( app->activeStudy() );
471   
472   if ( !study ) return;
473
474   // get selection
475   SALOME_ListIO selected;
476   selMgr->selectedObjects( selected );
477   if ( selected.IsEmpty() ) return;
478
479   SUIT_ViewWindow* window = app->desktop()->activeWindow();
480   int mgrId = window->getViewManager()->getGlobalId();
481
482   // convert current material properties to the string representation
483   QString prop = myCurrentModel.toProperties();
484  
485   if ( window && window->getViewManager()->getType() == SVTK_Viewer::Type() ) {
486     // for VTK viewer
487     SVTK_ViewWindow* vtkVW = dynamic_cast<SVTK_ViewWindow*>( window );
488     if ( !vtkVW )
489       return;
490
491     SVTK_View* aView = vtkVW->getView();
492
493     // get VTK material properties from the current model
494     GEOM_VTKPropertyMaterial* vtkPropF = myCurrentModel.getMaterialVTKProperty();
495     GEOM_VTKPropertyMaterial* vtkPropB = myCurrentModel.getMaterialVTKProperty( false );
496
497     SUIT_OverrideCursor wc();
498
499     for ( SALOME_ListIteratorOfListIO It( selected ); It.More(); It.Next() ) {
500       // set material property to the presentation
501       aView->SetMaterial( It.Value(), vtkPropF, vtkPropB );
502       // store chosen material in the property map
503       study->setObjectProperty( mgrId, It.Value()->getEntry(), GEOM::propertyName( GEOM::Material ), prop );
504       // set correct color for the non-physical material
505       if ( !myCurrentModel.isPhysical() ) {
506         aView->SetColor( It.Value(), myColor->color() );
507         study->setObjectProperty( mgrId, It.Value()->getEntry(), GEOM::propertyName( GEOM::Color ), myColor->color() );
508       }
509     }
510     aView->Repaint();
511     GeometryGUI::Modified();
512   }
513   else if ( window && window->getViewManager()->getType() == OCCViewer_Viewer::Type() ) {    
514     // for OCC viewer
515     OCCViewer_Viewer* vm = dynamic_cast<OCCViewer_Viewer*>( window->getViewManager()->getViewModel() );
516     if ( !vm )
517       return;
518
519     Handle(AIS_InteractiveContext) ic = vm->getAISContext();
520
521     // get OCC material aspect from the current model
522     Graphic3d_MaterialAspect front_occAspect = myCurrentModel.getMaterialOCCAspect( true );
523     Graphic3d_MaterialAspect back_occAspect = myCurrentModel.getMaterialOCCAspect( false );
524
525     SUIT_OverrideCursor wc();
526
527     for ( SALOME_ListIteratorOfListIO It( selected ); It.More(); It.Next() ) {
528       Handle(GEOM_AISShape) aisShape = GEOMBase::ConvertIOinGEOMAISShape( It.Value(), true );
529       if ( !aisShape.IsNull() ) {
530         // Set front material for the selected shape
531         aisShape->SetCurrentFacingModel(Aspect_TOFM_FRONT_SIDE);
532         aisShape->SetMaterial(front_occAspect);
533         // Set back material for the selected shape
534         aisShape->SetCurrentFacingModel(Aspect_TOFM_BACK_SIDE);
535         aisShape->SetMaterial(back_occAspect);
536         // Return to the default facing mode
537         aisShape->SetCurrentFacingModel(Aspect_TOFM_BOTH_SIDE);
538         // store chosen material in the property map
539         study->setObjectProperty( mgrId, It.Value()->getEntry(), GEOM::propertyName( GEOM::Material ), prop );
540         // set correct color for the non-physical material
541         if ( !myCurrentModel.isPhysical() ) {
542           aisShape->SetShadingColor( SalomeApp_Tools::color( myColor->color() ) );
543           study->setObjectProperty( mgrId, It.Value()->getEntry(), GEOM::propertyName( GEOM::Color ), myColor->color() );
544           ic->RecomputePrsOnly( aisShape, Standard_False );
545         }
546         //if ( aisShape->DisplayMode() != AIS_Shaded/*aisShape->DisplayMode() == GEOM_AISShape::ShadingWithEdges*/)
547         ic->Redisplay( aisShape, Standard_False );
548       }
549     }
550     ic->UpdateCurrentViewer();
551     GeometryGUI::Modified();
552   }
553 }
554
555 /*!
556   \brief Called when "Help" button is pressed
557 */
558 void GEOMToolsGUI_MaterialPropertiesDlg::onHelp()
559 {
560   LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
561   app->onHelpContextModule( "GEOM", "material_page.html" );
562 }
563
564 /*!
565   \brief Called when user selects any material item in the materials list
566 */
567 void GEOMToolsGUI_MaterialPropertiesDlg::onMaterialChanged()
568 {
569   // get currently selected item
570   QListWidgetItem* item = myMaterials->currentItem();
571   if ( !item ) return;
572
573   bool blocked = blockSignals( true );
574
575   int type = item->data( TypeRole ).toInt();
576   if ( type == Current ) {
577     // initialize widgets from current material model
578     fromModel( myCurrentModel );
579   }
580   else {
581     // initialize widgets from chosen material model (using resources manager)
582     Material_Model model;
583     model.fromResources( item->data( NameRole ).toString(), &myResourceMgr );
584     fromModel( model );
585   }
586
587   blockSignals( blocked );
588
589   // update buttons state
590   updateState();
591 }
592
593 /*!
594   \brief Called when any material parameter is changed by the user
595 */
596 void GEOMToolsGUI_MaterialPropertiesDlg::onChanged()
597 {
598   // get currently selected item
599   QListWidgetItem* item = myMaterials->currentItem();
600   int type = item->data( TypeRole ).toInt();
601   if ( !item ) return;
602
603   if ( type == Current ) {    
604     // for the current model do not perform any actions except store changed values
605     toModel( myCurrentModel );
606   }
607   else if ( type == User ) {    
608     // for the user model, simply store the changes in the resource manager
609     Material_Model model;
610     toModel( model );
611     // check if the user model is renamed
612     QString oldName = item->data( NameRole ).toString(), newName = item->text();
613     if ( oldName == newName ) {
614       // model is not renamed: store data using current name
615       model.toResources( oldName, &myResourceMgr );
616     }
617     else {
618       // model is renamed: remove model with old name and store model using new name
619       myResourceMgr.remove( oldName );
620       model.toResources( newName, &myResourceMgr );
621       item->setData( NameRole, newName );
622     }
623   }
624   else {
625     // it is no allowed to change global material
626     // user is asked about creating of a new user material model based on the currently selected one
627     if ( SUIT_MessageBox::question( this,
628                                     tr( "GEOM_WRN_WARNING" ),
629                                     tr( "QUE_CREATE_NEW_MATERIAL" ),
630                                     QMessageBox::Yes | QMessageBox::No,
631                                     QMessageBox::Yes ) == QMessageBox::Yes ) {
632       // user has chosen creation of new user model
633       onAddMaterial();
634     }
635     else {
636       // user has rejected creation of new user model: revert changes
637       bool blocked = blockSignals( true );
638       Material_Model model;
639       model.fromResources( item->data( NameRole ).toString(), &myResourceMgr );
640       fromModel( model );
641       blockSignals( blocked );
642     }
643   }
644
645   // update buttons state
646   updateState();
647 }
648
649 /*!
650   \brief Called when user material is renamed by the user
651 */
652 void GEOMToolsGUI_MaterialPropertiesDlg::onItemChanged( QListWidgetItem* item )
653 {
654   // check new name to be unique (add suffix if necessary)
655   QString newName = item->text();
656   QString uniqueName = findUniqueName( newName, item );
657   if ( uniqueName != newName ) {
658     bool blocked = myMaterials->blockSignals( true );
659     item->setText( uniqueName );
660     myMaterials->blockSignals( blocked );
661   }
662   onChanged();
663 }                               
664
665 /*!
666   \brief Process context menu event from materials list
667 */
668 void GEOMToolsGUI_MaterialPropertiesDlg::onContextMenu( QContextMenuEvent* e )
669 {
670   QListWidgetItem* item = myMaterials->itemAt( e->pos() );
671   QMap<QAction*, int> actionMap;
672   QMenu m;
673   // rename
674   if ( item && item->data( TypeRole ).toInt() == User ) {
675     actionMap[ m.addAction( tr( "RENAME_MATERIAL" ) ) ] = 0;
676     m.addSeparator();
677   }
678   // add user material
679   actionMap[ m.addAction( tr( "ADD_MATERIAL" ) ) ] = 1;
680   // delete user material
681   if ( item && item->data( TypeRole ).toInt() == User ) {
682     actionMap[ m.addAction( tr( "DELETE_MATERIAL" ) ) ] = 2;
683   }
684   QAction* a = m.exec( e->globalPos() );
685   switch( actionMap[ a ] ) {
686   case 0:
687     // rename
688     myMaterials->editItem( item );
689     break;
690   case 1:
691     // add user material
692     onAddMaterial();
693     break;
694   case 2:
695     // delete user material
696     onDeleteMaterial();
697     break;
698   default:
699     break;
700   }
701 }
702
703 /*!
704   \brief Delete currently selected user model
705 */
706 void GEOMToolsGUI_MaterialPropertiesDlg::onDeleteMaterial()
707 {
708   QListWidgetItem* item = myMaterials->currentItem();
709   if ( item && item->data( TypeRole ).toInt() == User ) {
710     if ( SUIT_MessageBox::question( this,
711                                     tr( "GEOM_WRN_WARNING" ),
712                                     tr( "QUE_REMOVE_MATERIAL" ).arg( item->text() ),
713                                     QMessageBox::Yes | QMessageBox::No,
714                                     QMessageBox::Yes ) == QMessageBox::Yes ) {
715       myResourceMgr.remove( item->data( NameRole ).toString() );
716       delete item;
717     }
718   }
719 }
720
721 /*!
722   \brief Add new user material model
723 */
724 void GEOMToolsGUI_MaterialPropertiesDlg::onAddMaterial()
725 {
726   QString newName = findUniqueName( tr( "CUSTOM_MATERIAL" ), 0, true );
727   QListWidgetItem* item = new QListWidgetItem( newName );
728   item->setData( TypeRole, QVariant( User ) );
729   item->setData( NameRole, QVariant( newName ) );
730   item->setFlags( item->flags() | Qt::ItemIsEditable );
731   myMaterials->addItem( item );
732   
733   Material_Model model;
734   toModel( model );
735   model.toResources( newName, &myResourceMgr );
736   myMaterials->setCurrentItem( item );
737   myMaterials->editItem( item );
738 }
739
740 /*!
741   \brief Update buttons state
742 */
743 void GEOMToolsGUI_MaterialPropertiesDlg::updateState()
744 {
745   QListWidgetItem* item = myMaterials->currentItem();
746   myDelButton->setEnabled( item && item->data( TypeRole ).toInt() == User );
747   myColorLab->setEnabled( !myPhysical->isChecked() );
748   myColor->setEnabled( !myPhysical->isChecked() );
749   myReflection[0].color->setEnabled( myPhysical->isChecked() );
750 }
751
752
753 void GEOMToolsGUI_MaterialPropertiesDlg::SetEditCurrentArgument()
754 {
755   QPushButton* send = (QPushButton*)sender();
756
757   if (send == myPushBtn) {
758   // enable line edit
759   myLineEditCurArg->setEnabled(true);
760   myLineEditCurArg->setFocus();
761         SelectionIntoArgument();
762   // after setFocus(), because it will be setDown(false) when loses focus
763   send->setDown(true);
764   }
765 }
766
767 /*!
768   \brief  Called when selection as changed or other case
769 */
770 void GEOMToolsGUI_MaterialPropertiesDlg::SelectionIntoArgument()
771 {
772   myLineEditCurArg->setText( "" );
773   QString aString = "";
774
775   SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( SUIT_Session::session()->activeApplication() );
776   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( app->activeStudy() );
777   LightApp_SelectionMgr* aSelMgr = app->selectionMgr();
778   if ( study ) {
779     SALOME_ListIO aSelList;
780     aSelMgr->selectedObjects(aSelList);
781     /*int nbSel = */GEOMBase::GetNameOfSelectedIObjects(aSelList, aString, true);
782   }
783   myLineEditCurArg->setText( aString );
784 }