KiCad PCB EDA Suite
transline_dlg_funct.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KICAD, a free EDA CAD application.
3  *
4  * Copyright (C) 2011 jean-pierre.charras
5  * Copyright (C) 1992-2021 Kicad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program. If not, see <http://www.gnu.org/licenses/>.
19  */
20 #include <wx/choicdlg.h>
21 #include <wx/filename.h>
22 #include <wx/settings.h>
23 
24 #include <bitmaps.h>
26 #include <common_data.h>
27 #include <widgets/unit_selector.h>
28 
29 
30 extern double DoubleFromString( const wxString& TextValue );
31 
32 
33 // Display a selection of usual Er, TanD, Rho values
34 // List format is <value><space><comment>
35 
36 
37 // A helper function to find the choice in a list of values
38 // return true if a index in aList that matches aValue is found.
39 static bool findMatch( wxArrayString& aList, const wxString& aValue, int& aIdx )
40 {
41  bool success = false;
42  // Find the previous choice index:
43  aIdx = 0;
44 
45  // Some countries use comma instead of point as separator.
46  // The value can be enter with pint or comma
47  // use point for string comparisons:
48  wxString cvalue = aValue;
49  cvalue.Replace( ',', '.' );
50 
51  // First compare strings:
52  for( wxString& text: aList )
53  {
54  if( text.IsEmpty() ) // No match found: select the empty line choice
55  break;
56 
57  wxString val_str = text.BeforeFirst( ' ' );
58  val_str.Replace( ',', '.' );
59 
60  // compare string values
61  if( val_str == cvalue )
62  {
63  success = true;
64  break;
65  }
66 
67  aIdx++;
68  }
69 
70  // Due to multiple ways to write a double, if string values
71  // do not match, compare double values
72  if( !success )
73  {
74  struct lconv* lc = localeconv();
75  char localeDecimalSeparator = *lc->decimal_point;
76 
77  if( localeDecimalSeparator == ',' )
78  cvalue.Replace( '.', ',' );
79 
80  double curr_value;
81  cvalue.ToDouble( &curr_value );
82 
83  aIdx = 0;
84 
85  for( wxString& text: aList )
86  {
87  if( text.IsEmpty() ) // No match found: select the empty line choice
88  break;
89 
90  double val;
91  wxString val_str = text.BeforeFirst( ' ' );
92 
93  if( localeDecimalSeparator == ',' )
94  val_str.Replace( '.', ',' );
95 
96  val_str.ToDouble( &val );;
97 
98  if( curr_value == val )
99  {
100  success = true;
101  break;
102  }
103 
104  aIdx++;
105  }
106  }
107 
108  return success;
109 }
110 
111 
112 void PANEL_TRANSLINE::OnTranslineEpsilonR_Button( wxCommandEvent& event )
113 {
114  wxArrayString list = StandardRelativeDielectricConstantList();
115  list.Add( "" ); // Add an empty line for no selection
116 
117  // Find the previous choice index:
118  wxString prevChoiceStr = m_Value_EpsilonR->GetValue();
119  int prevChoice = 0;
120  findMatch( list, prevChoiceStr, prevChoice );
121 
122  int index = wxGetSingleChoiceIndex( wxEmptyString, _( "Relative Dielectric Constants" ),
123  list, prevChoice );
124 
125  if( index >= 0 && !list.Item( index ).IsEmpty() ) // i.e. non canceled.
126  m_Value_EpsilonR->SetValue( list.Item( index ).BeforeFirst( ' ' ) );
127 }
128 
129 
130 void PANEL_TRANSLINE::OnTranslineTanD_Button( wxCommandEvent& event )
131 {
132  wxArrayString list = StandardLossTangentList();
133  list.Add( "" ); // Add an empty line for no selection
134 
135  // Find the previous choice index:
136  wxString prevChoiceStr = m_Value_TanD->GetValue();
137  int prevChoice = 0;
138  findMatch( list, prevChoiceStr, prevChoice );
139 
140  int index = wxGetSingleChoiceIndex( wxEmptyString, _( "Dielectric Loss Factor" ), list,
141  prevChoice, nullptr );
142 
143  if( index >= 0 && !list.Item( index ).IsEmpty() ) // i.e. non canceled.
144  m_Value_TanD->SetValue( list.Item( index ).BeforeFirst( ' ' ) );
145 }
146 
147 
148 void PANEL_TRANSLINE::OnTranslineRho_Button( wxCommandEvent& event )
149 {
150  wxArrayString list = StandardResistivityList();
151  list.Add( "" ); // Add an empty line for no selection
152 
153  // Find the previous choice index:
154  wxString prevChoiceStr = m_Value_Rho->GetValue();
155  int prevChoice = 0;
156  findMatch( list, prevChoiceStr, prevChoice );
157 
158  int index = wxGetSingleChoiceIndex( wxEmptyString, _( "Specific Resistance" ), list,
159  prevChoice, nullptr );
160 
161  if( index >= 0 && !list.Item( index ).IsEmpty() ) // i.e. non canceled.
162  m_Value_Rho->SetValue( list.Item( index ).BeforeFirst( ' ' ) );
163 }
164 
165 
166 // Minor helper struct to handle dialog items for a given parameter
168 {
169  wxStaticText* name;
170  wxTextCtrl* value;
172 };
173 
174 
176 {
177  m_currTransLineType = aType;
178 
181  {
183  }
184 
185  m_translineBitmap->SetBitmap( KiBitmap( m_transline_list[m_currTransLineType]->m_BitmapName ) );
186 
187  // This helper bitmap is shown for coupled microstrip only:
190  m_fgSizerZcomment->Show( aType == C_MICROSTRIP_TYPE );
191 
193  m_currTransLine = tr_ident->m_TLine;
194 
195  m_radioBtnPrm1->Show( tr_ident->m_HasPrmSelection );
196  m_radioBtnPrm2->Show( tr_ident->m_HasPrmSelection );
197 
198  // Setup messages
199  wxStaticText* left_msg_list[] =
200  {
203  };
204 
205  wxStaticText* msg_list[] =
206  {
208  };
209 
210  unsigned jj = 0;
211 
212  for( ; jj < tr_ident->m_Messages.GetCount(); jj++ )
213  {
214  if( left_msg_list[jj] == nullptr )
215  break;
216 
217  left_msg_list[jj]->SetLabel( tr_ident->m_Messages[jj] );
218  msg_list[jj]->SetLabel( wxEmptyString );
219  }
220 
221  while( left_msg_list[jj] )
222  {
223  left_msg_list[jj]->SetLabel( wxEmptyString );
224  msg_list[jj]->SetLabel( wxEmptyString );
225  jj++;
226  }
227 
228 
229  // Init parameters dialog items
230  struct DLG_PRM_DATA substrateprms[] =
231  {
232  { m_EpsilonR_label, m_Value_EpsilonR, nullptr },
233  { m_TanD_label, m_Value_TanD, nullptr },
234  { m_Rho_label, m_Value_Rho, nullptr },
241  };
242 
243 #define substrateprms_cnt (sizeof(substrateprms)/sizeof(substrateprms[0]))
244 
245  struct DLG_PRM_DATA physprms[] =
246  {
250  };
251 
252 #define physprms_cnt (sizeof(physprms)/sizeof(physprms[0]))
253 
254  struct DLG_PRM_DATA elecprms[] =
255  {
259  };
260 
261 #define elecprms_cnt (sizeof(elecprms)/sizeof(elecprms[0]))
262 
263  struct DLG_PRM_DATA frequencyprms[] =
264  {
266  };
267 
268 #define frequencyprms_cnt (sizeof(frequencyprms)/sizeof(frequencyprms[0]))
269 
270  unsigned idxsubs = 0;
271  unsigned idxphys = 0;
272  unsigned idxelec = 0;
273  unsigned idxfreq = 0;
274 
275  for( unsigned ii = 0; ii < tr_ident->GetPrmsCount(); ii++ )
276  {
277  TRANSLINE_PRM* prm = tr_ident->GetPrm( ii );
278  struct DLG_PRM_DATA * data = nullptr;
279 
280  switch( prm->m_Type )
281  {
282  case PRM_TYPE_SUBS:
283  wxASSERT( idxsubs < substrateprms_cnt );
284  data = &substrateprms[idxsubs];
285  idxsubs++;
286  break;
287 
288  case PRM_TYPE_PHYS:
289  wxASSERT( idxphys < physprms_cnt );
290  data = &physprms[idxphys];
291  idxphys++;
292  break;
293 
294  case PRM_TYPE_ELEC:
295  wxASSERT( idxelec < elecprms_cnt );
296  data = &elecprms[idxelec];
297  idxelec++;
298  break;
299 
300  case PRM_TYPE_FREQUENCY:
301  wxASSERT( idxfreq < frequencyprms_cnt );
302  data = &frequencyprms[idxfreq];
303  idxfreq++;
304  break;
305  }
306 
307  wxASSERT ( data );
308  data->name->SetToolTip( prm->m_ToolTip );
309  data->name->SetLabel( prm->m_DlgLabel != "" ? prm->m_DlgLabel + ':' : "" );
310  prm->m_ValueCtrl = data->value;
311 
312  if( prm->m_Id != DUMMY_PRM )
313  {
314  data->value->SetValue( wxString::Format( "%g", prm->m_Value ) );
315  data->value->Enable( true );
316  }
317  else
318  {
319  data->value->SetValue( wxEmptyString );
320  data->value->Enable( false );
321  }
322 
323  if( prm->m_ConvUnit )
324  prm->m_UnitCtrl = data->unit;
325 
326  if( data->unit )
327  {
328  data->unit->Show( prm->m_ConvUnit );
329  data->unit->Enable( prm->m_ConvUnit );
330  data->unit->SetSelection( prm->m_UnitSelection );
331  }
332  }
333 
334  // Clear all unused params
335  for( ; idxsubs < substrateprms_cnt; idxsubs++ )
336  {
337  substrateprms[idxsubs].name->SetLabel(wxEmptyString);
338  substrateprms[idxsubs].name->SetToolTip(wxEmptyString);
339  substrateprms[idxsubs].value->SetValue(wxEmptyString);
340  substrateprms[idxsubs].value->Enable( false );
341 
342  if( substrateprms[idxsubs].unit)
343  {
344  substrateprms[idxsubs].unit->Show( false );
345  substrateprms[idxsubs].unit->Enable( false );
346  substrateprms[idxsubs].unit->SetSelection( 0 );
347  }
348  }
349 
350  for( ; idxphys < physprms_cnt; idxphys++ )
351  {
352  physprms[idxphys].name->SetLabel(wxEmptyString);
353  physprms[idxphys].name->SetToolTip(wxEmptyString);
354  physprms[idxphys].value->SetValue(wxEmptyString);
355  physprms[idxphys].value->Enable( false );
356 
357  if( physprms[idxphys].unit)
358  {
359  physprms[idxphys].unit->Show( false );
360  physprms[idxphys].unit->Enable( false );
361  physprms[idxphys].unit->SetSelection( 0 );
362  }
363  }
364 
365  for( ; idxelec < elecprms_cnt; idxelec++)
366  {
367  elecprms[idxelec].name->SetLabel(wxEmptyString);
368  elecprms[idxelec].name->SetToolTip(wxEmptyString);
369  elecprms[idxelec].value->SetValue(wxEmptyString);
370  elecprms[idxelec].value->Enable( false );
371 
372  if( elecprms[idxelec].unit)
373  {
374  elecprms[idxelec].unit->Show( false );
375  elecprms[idxelec].unit->Enable( false );
376  elecprms[idxelec].unit->SetSelection( 0 );
377  }
378  }
379 
380  for( ; idxfreq < frequencyprms_cnt; idxfreq++ )
381  {
382  frequencyprms[idxfreq].name->SetLabel(wxEmptyString);
383  frequencyprms[idxfreq].name->SetToolTip(wxEmptyString);
384  frequencyprms[idxfreq].value->SetValue(wxEmptyString);
385  frequencyprms[idxfreq].value->Enable( false );
386 
387  if( frequencyprms[idxfreq].unit )
388  {
389  frequencyprms[idxfreq].unit->Show( false );
390  frequencyprms[idxfreq].unit->Enable( false );
391  frequencyprms[idxfreq].unit->SetSelection( 0 );
392  }
393  }
394 }
395 
396 
398 {
400 
401  for( unsigned ii = 0; ii < tr_ident->GetPrmsCount(); ii++ )
402  {
403  TRANSLINE_PRM* prm = tr_ident->GetPrm( ii );
404  wxTextCtrl * value_ctrl = (wxTextCtrl * ) prm->m_ValueCtrl;
405  wxString value_txt = value_ctrl->GetValue();
406  double value = DoubleFromString(value_txt);
407  prm->m_Value = value;
408  UNIT_SELECTOR * unit_ctrl = (UNIT_SELECTOR * ) prm->m_UnitCtrl;
409 
410  if( unit_ctrl )
411  {
412  prm->m_UnitSelection = unit_ctrl->GetSelection();
413  value *= unit_ctrl->GetUnitScale();
414  }
415 
416  prm->m_NormalizedValue = value;
417  }
418 }
419 
420 
421 void PANEL_TRANSLINE::OnTranslineSelection( wxCommandEvent& event )
422 {
423  enum TRANSLINE_TYPE_ID id = (enum TRANSLINE_TYPE_ID) event.GetSelection();
424 
426 
427  // Texts and units choice widgets can have their size modified:
428  // The new size must be taken in account
429  GetSizer()->Layout();
430  Refresh();
431 }
432 
433 
434 void PANEL_TRANSLINE::OnTransLineResetButtonClick( wxCommandEvent& event )
435 {
437  m_TranslineSelection->SetSelection( DEFAULT_TYPE );
438 
439  GetSizer()->Layout();
440  Refresh();
441 }
wxStaticText * m_left_message5
wxTextCtrl * m_Substrate_prm6_Value
void OnTranslineEpsilonR_Button(wxCommandEvent &event) override
Shows a list of current relative dielectric constant(Er) and set the selected value in main dialog fr...
TRANSLINE * m_currTransLine
wxStaticText * name
double m_NormalizedValue
wxArrayString StandardRelativeDielectricConstantList()
Definition: common_data.cpp:28
enum TRANSLINE_TYPE_ID m_currTransLineType
wxStaticText * m_left_message4
wxString m_DlgLabel
UNIT_SELECTOR_ANGLE * m_choiceUnit_ElecPrm3
wxStaticText * m_EpsilonR_label
wxTextCtrl * m_Substrate_prm7_Value
wxStaticText * m_elec_prm2_label
A class to handle one parameter of transline.
wxArrayString m_Messages
wxFlexGridSizer * m_fgSizerZcomment
A class to handle a list of parameters of a given transline.
wxRadioBox * m_TranslineSelection
#define frequencyprms_cnt
wxStaticBitmap * m_translineBitmap
wxTextCtrl * m_Substrate_prm4_Value
wxString m_ToolTip
wxStaticText * m_left_message7
wxTextCtrl * m_Substrate_prm5_Value
wxStaticText * m_substrate_prm7_label
static bool findMatch(wxArrayString &aList, const wxString &aValue, int &aIdx)
#define elecprms_cnt
UNIT_SELECTOR_LEN * m_SubsPrm6_choiceUnit
UNIT_SELECTOR_FREQUENCY * m_choiceUnit_Frequency
wxRadioButton * m_radioBtnPrm1
void TransfDlgDataToTranslineParams()
Read values entered in dialog frame, and transfer these values in current transline parameters,...
void OnTranslineTanD_Button(wxCommandEvent &event) override
Show a list of current dielectric loss factor (tangent delta) and set the selected value in main dial...
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
wxStaticText * m_left_message8
wxStaticText * m_Frequency_label
wxArrayString StandardLossTangentList()
Definition: common_data.cpp:55
UNIT_SELECTOR_RESISTOR * m_choiceUnit_ElecPrm1
wxStaticText * m_phys_prm3_label
wxTextCtrl * m_Value_Frequency_Ctrl
#define _(s)
wxArrayString StandardResistivityList()
Definition: common_data.cpp:84
unsigned GetPrmsCount() const
wxStaticText * m_substrate_prm8_label
wxStaticText * m_substrate_prm4_label
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
wxStaticText * m_phys_prm1_label
wxTextCtrl * m_Substrate_prm9_Value
void TranslineTypeSelection(enum TRANSLINE_TYPE_ID aType)
Must be called after selection of a new transline.
TRANSLINE_TYPE_ID
wxRadioButton * m_radioBtnPrm2
UNIT_SELECTOR * unit
void OnTranslineSelection(wxCommandEvent &event) override
Called on new transmission line selection.
UNIT_SELECTOR_LEN * m_SubsPrm7_choiceUnit
wxStaticBitmap * m_bmCMicrostripZoddZeven
UNIT_SELECTOR_LEN * m_SubsPrm9_choiceUnit
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
TRANSLINE_PRM * GetPrm(unsigned aIdx) const
UNIT_SELECTOR_LEN * m_SubsPrm5_choiceUnit
wxStaticText * m_elec_prm1_label
wxStaticText * m_elec_prm3_label
TRANSLINE * m_TLine
UNIT_SELECTOR_LEN * m_choiceUnit_Param3
wxStaticText * m_left_message6
UNIT_SELECTOR_LEN * m_choiceUnit_Param2
void OnTranslineRho_Button(wxCommandEvent &event) override
Show a list of current Specific resistance list (rho) and set the selected value in main dialog frame...
wxTextCtrl * m_Substrate_prm8_Value
void OnTransLineResetButtonClick(wxCommandEvent &event) override
Called when the user clicks the reset button; sets the parameters to their default values.
#define physprms_cnt
virtual double GetUnitScale()=0
Function GetUnitScale.
wxStaticText * m_phys_prm2_label
UNIT_SELECTOR_LEN * m_SubsPrm8_choiceUnit
wxStaticText * m_substrate_prm5_label
wxStaticText * m_substrate_prm6_label
#define substrateprms_cnt
wxStaticText * m_left_message2
UNIT_SELECTOR_LEN * m_choiceUnit_Param1
wxStaticText * m_left_message3
double DoubleFromString(const wxString &TextValue)
std::vector< TRANSLINE_IDENT * > m_transline_list
UNIT_SELECTOR_RESISTOR * m_choiceUnit_ElecPrm2
wxStaticText * m_left_message1
wxStaticText * m_substrate_prm9_label
UNIT_SELECTOR_LEN * m_SubsPrm4_choiceUnit