Salome HOME
0020082: EDF 869 GEOM : Edges Orientation indicator/reverse
[modules/smesh.git] / src / StdMeshersGUI / StdMeshersGUI_NbSegmentsCreator.cxx
1 //  Copyright (C) 2007-2008  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 // File   : StdMeshersGUI_NbSegmentsCreator.cxx
23 // Author : Open CASCADE S.A.S.
24 // SMESH includes
25 //
26 #include "StdMeshersGUI_NbSegmentsCreator.h"
27 #include "StdMeshersGUI_DistrTable.h"
28 #include "StdMeshersGUI_DistrPreview.h"
29 #include "StdMeshersGUI_SubShapeSelectorWdg.h"
30
31 #include <SMESHGUI.h>
32 #include <SMESHGUI_Utils.h>
33 #include <SMESHGUI_HypothesesUtils.h>
34 #include <SMESHGUI_SpinBox.h>
35
36 // IDL includes
37 #include CORBA_SERVER_HEADER(SMESH_BasicHypothesis)
38
39 // SALOME GUI includes
40 #include <SalomeApp_Tools.h>
41 #include <SalomeApp_IntSpinBox.h>
42 #include <QtxComboBox.h>
43
44 // Qt includes
45 #include <QLabel>
46 #include <QGroupBox>
47 #include <QFrame>
48 #include <QLineEdit>
49 #include <QButtonGroup>
50 #include <QRadioButton>
51 #include <QGridLayout>
52 #include <QVBoxLayout>
53 #include <QHBoxLayout>
54 #include <QApplication>
55
56 #define SPACING 6
57 #define MARGIN  11
58
59 StdMeshersGUI_NbSegmentsCreator::StdMeshersGUI_NbSegmentsCreator()
60 : StdMeshersGUI_StdHypothesisCreator( "NumberOfSegments" ),
61   myNbSeg( 0 ),
62   myDistr( 0 ),
63   myScale( 0 ),
64   myTable( 0 ),
65   myPreview( 0 ),
66   myExpr( 0 ),
67   myConvBox( 0 ),
68   myConv( 0 ),
69   myLScale( 0 ),
70   myLTable( 0 ),
71   myLExpr( 0 ),
72   myInfo( 0 ),
73   myGroupLayout( 0 ),
74   myTableRow( 0 ),
75   myPreviewRow( 0 )
76 {
77 }
78
79 StdMeshersGUI_NbSegmentsCreator::~StdMeshersGUI_NbSegmentsCreator()
80 {
81 }
82
83 bool StdMeshersGUI_NbSegmentsCreator::checkParams( QString& msg ) const
84 {
85   if( !SMESHGUI_GenericHypothesisCreator::checkParams( msg ) )
86     return false;
87   NbSegmentsHypothesisData data_old, data_new;
88   readParamsFromHypo( data_old );
89   readParamsFromWidgets( data_new );
90   bool res = storeParamsToHypo( data_new );
91   storeParamsToHypo( data_old );
92   res = myNbSeg->isValid( msg, true ) && res;
93   res = myScale->isValid( msg, true ) && res;
94   return res;
95 }
96
97 QFrame* StdMeshersGUI_NbSegmentsCreator::buildFrame()
98 {
99   QFrame* fr = new QFrame();
100
101   QVBoxLayout* lay = new QVBoxLayout( fr );
102   lay->setMargin( 0 );
103   lay->setSpacing( SPACING );
104
105   QGroupBox* GroupC1 = new QGroupBox( tr( "SMESH_ARGUMENTS" ), fr );
106   lay->addWidget( GroupC1 );
107
108   StdMeshers::StdMeshers_NumberOfSegments_var h =
109     StdMeshers::StdMeshers_NumberOfSegments::_narrow( hypothesis() );
110   myPreview = new StdMeshersGUI_DistrPreview( GroupC1, h.in() );
111
112   myGroupLayout = new QGridLayout( GroupC1 );
113   myGroupLayout->setSpacing( SPACING );
114   myGroupLayout->setMargin( MARGIN );
115   myGroupLayout->setColumnStretch( 0, 0 );
116   myGroupLayout->setColumnStretch( 1, 1 );
117
118   int row = 0;
119   // 0)  name
120   myName = 0;
121   if( isCreation() )
122   {
123     myName = new QLineEdit( GroupC1 );
124     myGroupLayout->addWidget( new QLabel( tr( "SMESH_NAME" ), GroupC1 ), row, 0 );
125     myGroupLayout->addWidget( myName, row, 1 );
126     row++;
127   }
128
129   // 1)  number of segments
130   myGroupLayout->addWidget( new QLabel( tr( "SMESH_NB_SEGMENTS_PARAM" ), GroupC1 ), row, 0 );
131   myNbSeg = new SalomeApp_IntSpinBox( GroupC1 );
132   myNbSeg->setMinimum( 1 );
133   myNbSeg->setMaximum( 9999 );
134   myGroupLayout->addWidget( myNbSeg, row, 1 );
135   row++;
136
137   // 2)  type of distribution
138   myGroupLayout->addWidget( new QLabel( tr( "SMESH_DISTR_TYPE" ), GroupC1 ), row, 0 );
139   myDistr = new QtxComboBox( GroupC1 );
140   QStringList types;
141   types.append( tr( "SMESH_DISTR_REGULAR" ) );
142   types.append( tr( "SMESH_DISTR_SCALE"   ) );
143   types.append( tr( "SMESH_DISTR_TAB"     ) );
144   types.append( tr( "SMESH_DISTR_EXPR"    ) );
145   myDistr->addItems( types );
146   myGroupLayout->addWidget( myDistr, row, 1 );
147   row++;
148
149   // 3)  scale
150   myGroupLayout->addWidget( myLScale = new QLabel( tr( "SMESH_NB_SEGMENTS_SCALE_PARAM" ), GroupC1 ), row, 0 );
151   myScale = new SMESHGUI_SpinBox( GroupC1 );
152   myScale->RangeStepAndValidator( 1E-5, 1E+5, 0.1, 6 );
153   myGroupLayout->addWidget( myScale, row, 1 );
154   row++;
155
156   myInfo = new QLabel( tr( "SMESH_FUNC_DOMAIN" ), GroupC1 );
157   myGroupLayout->addWidget( myInfo, row, 0, 1, 2 );
158   row++;
159   
160   // 4)  table
161   myGroupLayout->addWidget( myLTable = new QLabel( tr( "SMESH_TAB_FUNC" ), GroupC1 ), row, 0 );
162   myTable = new StdMeshersGUI_DistrTableFrame( GroupC1 );
163   myGroupLayout->addWidget( myTable, row, 1 );
164   myGroupLayout->setRowStretch( row, 1 );
165   myTableRow = row;
166   row++;
167
168   // 5)  expression
169   myGroupLayout->addWidget( myLExpr = new QLabel( tr( "SMESH_EXPR_FUNC" ), GroupC1 ), row, 0 );
170   myExpr = new QLineEdit( GroupC1 );
171   myGroupLayout->addWidget( myExpr, row, 1 );
172   row++;
173
174   // 6)  conversion (radiogroup)
175   myConvBox = new QGroupBox( tr( "SMESH_CONV_MODE" ), GroupC1 );
176   myConv = new QButtonGroup( GroupC1 );
177
178   QHBoxLayout* convLay = new QHBoxLayout( myConvBox );
179   convLay->setMargin( MARGIN );
180   convLay->setSpacing( SPACING );
181
182   QRadioButton* rbExp = new QRadioButton( tr( "SMESH_EXP_MODE" ), myConvBox );
183   QRadioButton* myCutNeg = new QRadioButton( tr( "SMESH_CUT_NEG_MODE" ), myConvBox );
184
185   convLay->addWidget( rbExp );
186   convLay->addWidget( myCutNeg );
187   myConv->addButton( rbExp, 0 );
188   myConv->addButton( myCutNeg, 1 );
189
190   myGroupLayout->addWidget( myConvBox, row, 0, 1, 2 );
191   row++;
192
193   // 7) distribution preview
194   myGroupLayout->addWidget( myPreview, row, 0, 1, 2 );
195   myGroupLayout->setRowStretch( row, 1 );
196   myPreviewRow = row;
197   row++;
198
199   // 8) reverce edge parameters
200   myReversedEdgesBox = new QGroupBox(tr( "SMESH_REVERSED_EDGES" ), fr);
201   QHBoxLayout* edgeLay = new QHBoxLayout( myReversedEdgesBox );
202
203   myDirectionWidget = new StdMeshersGUI_SubShapeSelectorWdg();
204   QString aGeomEntry = getShapeEntry();
205   QString aMainEntry = getMainShapeEntry();
206   if ( aGeomEntry == "" )
207     aGeomEntry = h->GetObjectEntry();
208   myDirectionWidget->SetGeomShapeEntry( aGeomEntry );
209   myDirectionWidget->SetMainShapeEntry( aMainEntry );
210   myDirectionWidget->SetListOfIDs( h->GetReversedEdges() );
211   edgeLay->addWidget( myDirectionWidget );
212
213   lay->addWidget( myReversedEdgesBox );
214
215   connect( myNbSeg, SIGNAL( valueChanged( const QString& ) ), this, SLOT( onValueChanged() ) );
216   connect( myDistr, SIGNAL( activated( int ) ), this, SLOT( onValueChanged() ) );
217   connect( myTable, SIGNAL( valueChanged( int, int ) ), this, SLOT( onValueChanged() ) );
218   connect( myExpr,  SIGNAL( textChanged( const QString& ) ), this, SLOT( onValueChanged() ) );
219   connect( myConv,  SIGNAL( buttonClicked( int ) ), this, SLOT( onValueChanged() ) );
220
221   return fr;
222 }
223
224 void StdMeshersGUI_NbSegmentsCreator::retrieveParams() const
225 {
226   NbSegmentsHypothesisData data;
227   readParamsFromHypo( data );
228
229   if( myName )
230     myName->setText( data.myName );
231   if(data.myNbSegVarName.isEmpty())
232     myNbSeg->setValue( data.myNbSeg );
233   else
234     myNbSeg->setText( data.myNbSegVarName );
235   
236   myDistr->setCurrentIndex( data.myDistrType );
237   if(data.myScaleVarName.isEmpty())
238     myScale->setValue( data.myScale );
239   else
240     myScale->setText( data.myScaleVarName );
241   myConv->button( data.myConv )->setChecked( true );
242   myTable->setFuncMinValue(myConv->checkedId()==0 ? -1E20 : 0);
243   myTable->setData( data.myTable );
244   myExpr->setText( data.myExpr );
245
246   if ( dlg() )
247     dlg()->setMinimumSize( dlg()->minimumSizeHint().width(), dlg()->minimumSizeHint().height() );
248 }
249
250 QString StdMeshersGUI_NbSegmentsCreator::storeParams() const
251 {
252   NbSegmentsHypothesisData data;
253   readParamsFromWidgets( data );
254   storeParamsToHypo( data );
255     
256   QString valStr = QString::number( data.myNbSeg ) += "; ";
257
258   enum DistrType
259   {
260     Regular, //!< equidistant distribution
261     Scale,   //!< scale distribution
262     TabFunc, //!< distribution with density function presented by table
263     ExprFunc //!< distribution with density function presented by expression
264   };
265   bool hasConv = false;
266   switch ( data.myDistrType ) {
267   case Regular :
268     valStr += tr("SMESH_DISTR_REGULAR");
269     break;
270   case Scale   : 
271     valStr += tr("SMESH_NB_SEGMENTS_SCALE_PARAM") + " = " + QString::number( data.myScale );\
272     break;
273   case TabFunc : {
274     //valStr += tr("SMESH_TAB_FUNC");
275     bool param = true;
276     for( int i=0; i < data.myTable.length(); i++, param = !param ) {
277       if ( param )
278         valStr += "[";
279       valStr += QString::number( data.myTable[ i ]);
280       valStr += ( param ? "," : "]" );
281     }
282     hasConv = true;
283     break;
284   }
285   case ExprFunc:
286     valStr += data.myExpr;
287     hasConv = true;
288     break;
289   }
290   if ( hasConv )
291     if ( data.myConv )
292       valStr += "; " + tr("SMESH_CUT_NEG_MODE");
293     else
294       valStr += "; " + tr("SMESH_EXP_MODE");
295
296   return valStr;
297 }
298
299 bool StdMeshersGUI_NbSegmentsCreator::readParamsFromHypo( NbSegmentsHypothesisData& h_data ) const
300 {
301   StdMeshers::StdMeshers_NumberOfSegments_var h =
302     StdMeshers::StdMeshers_NumberOfSegments::_narrow( initParamsHypothesis() );
303
304   h_data.myName = hypName();
305
306   h_data.myNbSeg = (int) h->GetNumberOfSegments();
307   
308   SMESH::ListOfParameters_var aParameters = h->GetLastParameters();
309
310   h_data.myNbSegVarName  = (aParameters->length() > 0) ? QString(aParameters[0].in()) : QString("");
311
312   int distr = (int) h->GetDistrType();
313   h_data.myDistrType = distr;
314   h_data.myScale = distr==1 ? h->GetScaleFactor() : 1.0;
315   
316   if(distr==1){
317     h_data.myScaleVarName  = (aParameters->length() > 1) ? QString(aParameters[1].in()) : QString("");
318   }
319   else 
320     h_data.myScaleVarName = QString("");
321
322   if( distr==2 )
323   {
324     SMESH::double_array* a = h->GetTableFunction();
325     h_data.myTable = *a;
326     delete a;
327   }
328   else
329   {
330     SMESH::double_array& a = h_data.myTable;
331     // by default, constant table function f(t)=1
332     a.length( 4 );
333     a[0] = 0.0; a[1] = 1.0;
334     a[2] = 1.0; a[3] = 1.0; 
335   }
336
337   h_data.myExpr = distr==3 ? h->GetExpressionFunction() : "1";
338   h_data.myConv = distr==2 || distr==3 ? h->ConversionMode() : 1; /*cut negative by default*/
339
340   return true;
341 }
342
343 bool StdMeshersGUI_NbSegmentsCreator::storeParamsToHypo( const NbSegmentsHypothesisData& h_data ) const
344 {
345   StdMeshers::StdMeshers_NumberOfSegments_var h =
346     StdMeshers::StdMeshers_NumberOfSegments::_narrow( hypothesis() );
347
348   bool ok = true;
349   try
350   {
351     if( isCreation() )
352       SMESH::SetName( SMESH::FindSObject( h ), h_data.myName.toLatin1().data() );
353
354     QStringList aVariablesList;
355     aVariablesList.append(h_data.myNbSegVarName);
356
357     h->SetNumberOfSegments( h_data.myNbSeg );
358     int distr = h_data.myDistrType;
359     h->SetDistrType( distr );
360     
361     if( distr==1 ) {
362       h->SetScaleFactor( h_data.myScale );
363       aVariablesList.append(h_data.myScaleVarName);
364     }
365     if( distr==2 || distr==3 )
366       h->SetConversionMode( h_data.myConv );
367
368     if( distr==1 || distr==2 || distr==3 ) {
369       h->SetReversedEdges( myDirectionWidget->GetListOfIDs() );
370       h->SetObjectEntry( myDirectionWidget->GetMainShapeEntry() );
371     }
372
373     if( distr==2 )
374       h->SetTableFunction( h_data.myTable );
375
376     if( distr==3 )
377       h->SetExpressionFunction( h_data.myExpr.toLatin1().data() );
378     //setting of function must follow after setConversionMode, because otherwise
379     //the function will be checked with old conversion mode, so that it may occurs
380     //unexpected errors for user
381
382     h->SetParameters(SMESHGUI::JoinObjectParameters(aVariablesList));
383   }
384   catch(const SALOME::SALOME_Exception& ex)
385   {
386     SalomeApp_Tools::QtCatchCorbaException(ex);
387     ok = false;
388   }
389   return ok;
390 }
391
392 bool StdMeshersGUI_NbSegmentsCreator::readParamsFromWidgets( NbSegmentsHypothesisData& h_data ) const
393 {
394   h_data.myName      = myName ? myName->text() : "";
395   h_data.myNbSeg     = myNbSeg->value();
396   h_data.myNbSegVarName =  myNbSeg->text();
397   h_data.myScaleVarName =  myScale->text();
398   h_data.myDistrType = myDistr->currentIndex();
399   h_data.myConv      = myConv->checkedId();
400   h_data.myScale     = myScale->value();
401   myTable->data( h_data.myTable );
402   h_data.myExpr      = myExpr->text();
403   return true;
404 }
405
406 void StdMeshersGUI_NbSegmentsCreator::onValueChanged()
407 {
408   int distr = myDistr->currentIndex();
409
410 /*  if( distr==2 ) //table func
411     myCutNeg->setText( tr( "SMESH_NO_CONV" ) );
412   else if( distr==3 )
413     myCutNeg->setText( tr( "SMESH_CUT_NEG_MODE" ) );*/
414
415   if( distr==2 && sender()==myConv ) //table func
416   {
417     myTable->setFuncMinValue( myConv->checkedId()==0 ? -1E20 : 0 );
418     SMESH::double_array arr;
419     myTable->data( arr );
420     myTable->setData( arr ); //update data in table
421   }
422
423   myScale->setShown( distr==1 );
424   myLScale->setShown( distr==1 );
425   myReversedEdgesBox->setShown( !distr==0 );
426   myDirectionWidget->showPreview( !distr==0 );
427
428   bool isFunc = distr==2 || distr==3;
429   myPreview->setShown( isFunc );
430   myGroupLayout->setRowStretch( myPreviewRow, isFunc ? 1 : 0 );
431
432   myConvBox->setShown( isFunc );
433
434   if( distr==2 )
435     myTable->show();
436   else
437     myTable->hide();
438   myLTable->setShown( distr==2 );
439   myGroupLayout->setRowStretch( myTableRow, distr==2 ? 1 : 0 );
440
441   myExpr->setShown( distr==3 );
442   myLExpr->setShown( distr==3 );
443   myInfo->setShown( isFunc );
444
445   //change of preview
446   int nbSeg = myNbSeg->value();
447   if( distr==2 ) //preview for table-described function
448   {
449     SMESH::double_array a;
450     myTable->data( a );
451     myPreview->setParams( a, nbSeg, false );
452   }
453   else if( distr==3 ) //preview for analytic-described function
454     myPreview->setParams( myExpr->text(), nbSeg, 100, false );
455
456   if( isFunc )
457     myPreview->setConversion( StdMeshersGUI_DistrPreview::Conversion( myConv->checkedId() ) );
458
459   if ( (QtxComboBox*)sender() == myDistr && dlg() ) {
460     QApplication::instance()->processEvents();
461     myGroupLayout->invalidate();
462     dlg()->layout()->invalidate();
463     dlg()->updateGeometry();
464     dlg()->setMinimumSize( dlg()->minimumSizeHint() );
465     dlg()->resize( dlg()->minimumSize() );
466     QApplication::instance()->processEvents();
467   }
468 }