KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 The 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
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20#include <cmath>
21
22#include <wx/choicdlg.h>
23#include <wx/filename.h>
24#include <wx/settings.h>
25
26#include <bitmaps.h>
28#include <common_data.h>
32#include <properties/property.h>
33
34
36{
37 wxArrayString list = StandardRelativeDielectricConstantList();
38 list.Add( "" ); // Add an empty line for no selection
39
40 // Find the previous choice index:
41 wxString prevChoiceStr = m_Value_EpsilonR->GetValue();
42 int prevChoice = 0;
43 findMatch( list, prevChoiceStr, prevChoice );
44
45 int index = wxGetSingleChoiceIndex( wxEmptyString, _( "Relative Dielectric Constants" ),
46 list, prevChoice );
47
48 if( index >= 0 && !list.Item( index ).IsEmpty() ) // i.e. non canceled.
49 m_Value_EpsilonR->SetValue( list.Item( index ).BeforeFirst( ' ' ) );
50}
51
52
53void PANEL_TRANSLINE::OnTranslineTanD_Button( wxCommandEvent& event )
54{
55 wxArrayString list = StandardLossTangentList();
56 list.Add( "" ); // Add an empty line for no selection
57
58 // Find the previous choice index:
59 wxString prevChoiceStr = m_Value_TanD->GetValue();
60 int prevChoice = 0;
61 findMatch( list, prevChoiceStr, prevChoice );
62
63 int index = wxGetSingleChoiceIndex( wxEmptyString, _( "Dielectric Loss Factor" ), list,
64 prevChoice, nullptr );
65
66 if( index >= 0 && !list.Item( index ).IsEmpty() ) // i.e. non canceled.
67 m_Value_TanD->SetValue( list.Item( index ).BeforeFirst( ' ' ) );
68}
69
70
71void PANEL_TRANSLINE::OnTranslineRho_Button( wxCommandEvent& event )
72{
73 wxArrayString list = StandardResistivityList();
74 list.Add( "" ); // Add an empty line for no selection
75
76 // Find the previous choice index:
77 wxString prevChoiceStr = m_Value_Rho->GetValue();
78 int prevChoice = 0;
79 findMatch( list, prevChoiceStr, prevChoice );
80
81 int index = wxGetSingleChoiceIndex( wxEmptyString, _( "Specific Resistance" ), list,
82 prevChoice, nullptr );
83
84 if( index >= 0 && !list.Item( index ).IsEmpty() ) // i.e. non canceled.
85 m_Value_Rho->SetValue( list.Item( index ).BeforeFirst( ' ' ) );
86}
87
88
89// Minor helper struct to handle dialog items for a given parameter
91{
92 wxStaticText* name;
93 wxTextCtrl* value;
95};
96
97
99{
100 m_currTransLineType = aType;
101
104 {
106 }
107
109
110 // This helper bitmap is shown for coupled microstrip only:
111 m_bmCMicrostripZoddZeven->Show( aType == C_MICROSTRIP_TYPE || aType == C_STRIPLINE_TYPE );
113
114 // Soldermask correction applies to microstrip, coupled microstrip, CPW, and CBCPW.
115 // Stripline, coax, waveguide, and twistedpair have no exposed top surface to coat,
116 // so hide the whole group. Fills-gaps is CPW-only.
117 const bool maskEligible = ( aType == MICROSTRIP_TYPE ) || ( aType == C_MICROSTRIP_TYPE )
118 || ( aType == CPW_TYPE ) || ( aType == GROUNDED_CPW_TYPE );
119 const bool cpwFamily = ( aType == CPW_TYPE ) || ( aType == GROUNDED_CPW_TYPE );
120
121 m_soldermaskPresentCheck->Show( maskEligible );
122 m_soldermaskThicknessLabel->Show( maskEligible );
123 m_soldermaskThicknessValue->Show( maskEligible );
124 m_soldermaskThicknessUnit->Show( maskEligible );
125 m_soldermaskEpsilonRLabel->Show( maskEligible );
126 m_soldermaskEpsilonRValue->Show( maskEligible );
127 m_soldermaskTanDLabel->Show( maskEligible );
128 m_soldermaskTanDValue->Show( maskEligible );
129 m_soldermaskFillsGapsCheck->Show( maskEligible && cpwFamily );
130
132
134 m_currTransLine = tr_ident->m_TLine;
135
136 m_radioBtnPrm1->Show( tr_ident->m_HasPrmSelection );
137 m_radioBtnPrm2->Show( tr_ident->m_HasPrmSelection );
138
139 // Setup messages
140 wxStaticText* left_msg_list[] = { m_left_message1, m_left_message2, m_left_message3, m_left_message4,
143
144 wxStaticText* msg_list[] = { m_Message1, m_Message2, m_Message3, m_Message4, m_Message5, m_Message6,
146
147 unsigned jj = 0;
148
149 for( ; jj < tr_ident->m_Messages.GetCount(); jj++ )
150 {
151 if( left_msg_list[jj] == nullptr )
152 break;
153
154 left_msg_list[jj]->SetLabel( tr_ident->m_Messages[jj] );
155 msg_list[jj]->SetLabel( wxEmptyString );
156 }
157
158 while( left_msg_list[jj] )
159 {
160 left_msg_list[jj]->SetLabel( wxEmptyString );
161 msg_list[jj]->SetLabel( wxEmptyString );
162 jj++;
163 }
164
165
166 // Init parameters dialog items
167 struct DLG_PRM_DATA substrateprms[] =
168 {
170 { m_TanD_label, m_Value_TanD, nullptr },
171 { m_Rho_label, m_Value_Rho, nullptr },
178 };
179
180#define substrateprms_cnt (sizeof(substrateprms)/sizeof(substrateprms[0]))
181
182 struct DLG_PRM_DATA physprms[] =
183 {
187 };
188
189#define physprms_cnt (sizeof(physprms)/sizeof(physprms[0]))
190
191 struct DLG_PRM_DATA elecprms[] =
192 {
196 };
197
198#define elecprms_cnt (sizeof(elecprms)/sizeof(elecprms[0]))
199
200 struct DLG_PRM_DATA frequencyprms[] =
201 {
203 };
204
205#define frequencyprms_cnt (sizeof(frequencyprms)/sizeof(frequencyprms[0]))
206
207 unsigned idxsubs = 0;
208 unsigned idxphys = 0;
209 unsigned idxelec = 0;
210 unsigned idxfreq = 0;
211
212 for( unsigned ii = 0; ii < tr_ident->GetPrmsCount(); ii++ )
213 {
214 TRANSLINE_PRM* prm = tr_ident->GetPrm( ii );
215 struct DLG_PRM_DATA * data = nullptr;
216
217 switch( prm->m_Type )
218 {
219 case PRM_TYPE_SUBS:
220 wxASSERT( idxsubs < substrateprms_cnt );
221 data = &substrateprms[idxsubs];
222 idxsubs++;
223 break;
224
225 case PRM_TYPE_PHYS:
226 wxASSERT( idxphys < physprms_cnt );
227 data = &physprms[idxphys];
228 idxphys++;
229 break;
230
231 case PRM_TYPE_ELEC:
232 wxASSERT( idxelec < elecprms_cnt );
233 data = &elecprms[idxelec];
234 idxelec++;
235 break;
236
238 wxASSERT( idxfreq < frequencyprms_cnt );
239 data = &frequencyprms[idxfreq];
240 idxfreq++;
241 break;
242 }
243
244 wxASSERT ( data );
245 data->name->SetToolTip( prm->m_ToolTip );
246 data->name->SetLabel( prm->m_DlgLabel != wxS( "" ) ? prm->m_DlgLabel + wxS( ':' ) : wxString( wxS( "" ) ) );
247 prm->m_ValueCtrl = data->value;
248
249 if( prm->m_Id != DUMMY_PRM )
250 {
251 data->value->SetValue( wxString::Format( wxS( "%g" ), prm->m_Value ) );
252 data->value->Enable( true );
253 }
254 else
255 {
256 data->value->SetValue( wxEmptyString );
257 data->value->Enable( false );
258 }
259
260 if( prm->m_ConvUnit )
261 prm->m_UnitCtrl = data->unit;
262
263 if( data->unit )
264 {
265 data->unit->Show( prm->m_ConvUnit );
266 data->unit->Enable( prm->m_ConvUnit );
267 data->unit->SetSelection( prm->m_UnitSelection );
268 }
269 }
270
271 // Clear all unused params
272 for( ; idxsubs < substrateprms_cnt; idxsubs++ )
273 {
274 substrateprms[idxsubs].name->SetLabel(wxEmptyString);
275 substrateprms[idxsubs].name->SetToolTip(wxEmptyString);
276 substrateprms[idxsubs].value->SetValue(wxEmptyString);
277 substrateprms[idxsubs].value->Enable( false );
278
279 if( substrateprms[idxsubs].unit)
280 {
281 substrateprms[idxsubs].unit->Show( false );
282 substrateprms[idxsubs].unit->Enable( false );
283 substrateprms[idxsubs].unit->SetSelection( 0 );
284 }
285 }
286
287 for( ; idxphys < physprms_cnt; idxphys++ )
288 {
289 physprms[idxphys].name->SetLabel(wxEmptyString);
290 physprms[idxphys].name->SetToolTip(wxEmptyString);
291 physprms[idxphys].value->SetValue(wxEmptyString);
292 physprms[idxphys].value->Enable( false );
293
294 if( physprms[idxphys].unit)
295 {
296 physprms[idxphys].unit->Show( false );
297 physprms[idxphys].unit->Enable( false );
298 physprms[idxphys].unit->SetSelection( 0 );
299 }
300 }
301
302 for( ; idxelec < elecprms_cnt; idxelec++)
303 {
304 elecprms[idxelec].name->SetLabel(wxEmptyString);
305 elecprms[idxelec].name->SetToolTip(wxEmptyString);
306 elecprms[idxelec].value->SetValue(wxEmptyString);
307 elecprms[idxelec].value->Enable( false );
308
309 if( elecprms[idxelec].unit)
310 {
311 elecprms[idxelec].unit->Show( false );
312 elecprms[idxelec].unit->Enable( false );
313 elecprms[idxelec].unit->SetSelection( 0 );
314 }
315 }
316
317 for( ; idxfreq < frequencyprms_cnt; idxfreq++ )
318 {
319 frequencyprms[idxfreq].name->SetLabel(wxEmptyString);
320 frequencyprms[idxfreq].name->SetToolTip(wxEmptyString);
321 frequencyprms[idxfreq].value->SetValue(wxEmptyString);
322 frequencyprms[idxfreq].value->Enable( false );
323
324 if( frequencyprms[idxfreq].unit )
325 {
326 frequencyprms[idxfreq].unit->Show( false );
327 frequencyprms[idxfreq].unit->Enable( false );
328 frequencyprms[idxfreq].unit->SetSelection( 0 );
329 }
330 }
331}
332
333
335{
337
338 for( unsigned ii = 0; ii < tr_ident->GetPrmsCount(); ii++ )
339 {
340 TRANSLINE_PRM* prm = tr_ident->GetPrm( ii );
341 wxTextCtrl * value_ctrl = (wxTextCtrl * ) prm->m_ValueCtrl;
342 wxString value_txt = value_ctrl->GetValue();
343 double value = DoubleFromString(value_txt);
344 prm->m_Value = value;
345 UNIT_SELECTOR * unit_ctrl = (UNIT_SELECTOR * ) prm->m_UnitCtrl;
346
347 if( unit_ctrl )
348 {
349 prm->m_UnitSelection = unit_ctrl->GetSelection();
350 value *= unit_ctrl->GetUnitScale();
351 }
352
353 prm->m_NormalizedValue = value;
354 }
355
356 // Panel-level selections are not part of the per-calculator param list and must be
357 // pushed explicitly.
358 if( m_currTransLine )
359 {
360 const int modelSel = m_dielectricModelChoice ? m_dielectricModelChoice->GetSelection() : 0;
361 m_currTransLine->SetExtraParameter( DIELECTRIC_MODEL_PRM, static_cast<double>( modelSel ) );
362
364 {
365 const double fSpec = DoubleFromString( m_Value_SpecFrequency_Ctrl->GetValue() )
366 * m_choiceUnit_SpecFrequency->GetUnitScale();
367
368 if( std::isfinite( fSpec ) && fSpec > 0.0 )
369 m_currTransLine->SetExtraParameter( EPSILONR_SPEC_FREQ_PRM, fSpec );
370 }
371
372 // Soldermask panel values. Thickness is entered in micrometres; convert to metres to
373 // match the math backend. If the checkbox is off, SOLDERMASK_PRESENT = 0 forces a
374 // bit-identical result regardless of the other mask fields.
375 const double present = m_soldermaskPresentCheck->GetValue() ? 1.0 : 0.0;
376 m_currTransLine->SetExtraParameter( SOLDERMASK_PRESENT_PRM, present );
377
378 // DoubleFromString handles "20 um" suffixes, comma decimal separators, and 1e3
379 // notation; on parse failure it returns NaN. Push the NaN through so the
380 // backend / checkProperties surfaces the bad input instead of silently retaining
381 // the previously-valid value (which would let the UI text and analysis state
382 // diverge).
383 const double thicknessUm = DoubleFromString( m_soldermaskThicknessValue->GetValue() );
384 m_currTransLine->SetExtraParameter( SOLDERMASK_THICKNESS_PRM, thicknessUm * 1.0e-6 );
385
386 const double epsR = DoubleFromString( m_soldermaskEpsilonRValue->GetValue() );
387 m_currTransLine->SetExtraParameter( SOLDERMASK_EPSILONR_PRM, epsR );
388
389 const double tand = DoubleFromString( m_soldermaskTanDValue->GetValue() );
390 m_currTransLine->SetExtraParameter( SOLDERMASK_TAND_PRM, tand );
391
392 const double fillsGaps = m_soldermaskFillsGapsCheck->GetValue() ? 1.0 : 0.0;
393 m_currTransLine->SetExtraParameter( SOLDERMASK_FILLS_GAPS_PRM, fillsGaps );
394 }
395}
396
397
398void PANEL_TRANSLINE::OnTranslineSelection( wxCommandEvent& event )
399{
400 // Ensure parameters from current selection are taken in account before switching to a new selection
401 if( m_currTransLine )
403
404 enum TRANSLINE_TYPE_ID id = (enum TRANSLINE_TYPE_ID) event.GetSelection();
405
407
408 // Texts and units choice widgets can have their size modified:
409 // The new size must be taken in account
410 GetSizer()->Layout();
411 Refresh();
412}
413
414
416{
417 // Initialize param values to default value
419
420 for( unsigned ii = 0; ii < tr_ident->GetPrmsCount(); ii++ )
421 {
422 TRANSLINE_PRM* prm = tr_ident->GetPrm( ii );
423 prm->m_Value = prm->m_DefaultValue;
424 UNIT_SELECTOR* unit_ctrl = (UNIT_SELECTOR*) prm->m_UnitCtrl;
425
426 if( unit_ctrl )
427 prm->m_UnitSelection = prm->m_DefaultUnit;
428 }
429
430 // Reinit displayed values
432
433 Refresh();
434}
int index
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
@ microstrip_zodd_zeven
wxTextCtrl * m_Substrate_prm5_Value
UNIT_SELECTOR_RESISTOR * m_choiceUnit_ElecPrm2
UNIT_SELECTOR_LEN * m_SubsPrm9_choiceUnit
wxStaticText * m_soldermaskTanDLabel
wxStaticText * m_substrate_prm9_label
wxTextCtrl * m_Substrate_prm9_Value
UNIT_SELECTOR_FREQUENCY * m_choiceUnit_SpecFrequency
wxStaticText * m_soldermaskEpsilonRLabel
UNIT_SELECTOR_LEN * m_SubsPrm4_choiceUnit
wxStaticText * m_EpsilonR_label
wxStaticText * m_substrate_prm7_label
wxStaticText * m_Frequency_label
wxTextCtrl * m_Substrate_prm7_Value
wxStaticBitmap * m_bmCMicrostripZoddZeven
wxStaticText * m_substrate_prm6_label
UNIT_SELECTOR_LEN * m_SubsPrm7_choiceUnit
UNIT_SELECTOR_LEN * m_choiceUnit_Param3
wxTextCtrl * m_soldermaskThicknessValue
wxTextCtrl * m_Substrate_prm4_Value
wxCheckBox * m_soldermaskPresentCheck
UNIT_SELECTOR_LEN * m_SubsPrm5_choiceUnit
wxTextCtrl * m_Substrate_prm6_Value
wxStaticText * m_substrate_prm8_label
wxStaticText * m_soldermaskThicknessUnit
wxCheckBox * m_soldermaskFillsGapsCheck
UNIT_SELECTOR_ANGLE * m_choiceUnit_ElecPrm3
UNIT_SELECTOR_LEN * m_SubsPrm6_choiceUnit
wxStaticBitmap * m_translineBitmap
UNIT_SELECTOR_LEN * m_choiceUnit_Param2
UNIT_SELECTOR_FREQUENCY * m_choiceUnit_Frequency
UNIT_SELECTOR_LEN * m_SubsPrm8_choiceUnit
wxTextCtrl * m_soldermaskEpsilonRValue
wxTextCtrl * m_Substrate_prm8_Value
UNIT_SELECTOR_RESISTOR * m_choiceUnit_ElecPrm1
wxStaticText * m_substrate_prm4_label
UNIT_SELECTOR_LEN * m_choiceUnit_Param1
wxStaticText * m_soldermaskThicknessLabel
wxStaticText * m_substrate_prm5_label
wxTextCtrl * m_Value_Frequency_Ctrl
wxTextCtrl * m_Value_SpecFrequency_Ctrl
TRANSLINE * m_currTransLine
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 TranslineTypeSelection(enum TRANSLINE_TYPE_ID aType)
Must be called after selection of a new transline.
void OnTranslineEpsilonR_Button(wxCommandEvent &event) override
Shows a list of current relative dielectric constant(Er) and set the selected value in main dialog fr...
void updateSoldermaskEnables()
Apply the enabled state for the soldermask row based on the present checkbox and the current calculat...
void TransfDlgDataToTranslineParams()
Read values entered in dialog frame, and transfer these values in current transline parameters,...
void OnTranslineSelection(wxCommandEvent &event) override
Called on new transmission line selection.
std::vector< TRANSLINE_IDENT * > m_transline_list
void OnTransLineResetButtonClick(wxCommandEvent &event) override
Called when the user clicks the reset button; sets the parameters to their default values.
void OnTranslineRho_Button(wxCommandEvent &event) override
Show a list of current Specific resistance list (rho) and set the selected value in main dialog frame...
enum TRANSLINE_TYPE_ID m_currTransLineType
A class to handle a list of parameters of a given transline.
TRANSLINE * m_TLine
unsigned GetPrmsCount() const
TRANSLINE_PRM * GetPrm(unsigned aIdx) const
wxArrayString m_Messages
A class to handle one parameter of transline.
double m_NormalizedValue
wxString m_DlgLabel
virtual double GetUnitScale()=0
Function GetUnitScale.
wxArrayString StandardResistivityList()
wxArrayString StandardRelativeDielectricConstantList()
wxArrayString StandardLossTangentList()
#define _(s)
double DoubleFromString(const wxString &TextValue)
bool findMatch(wxArrayString &aList, const wxString &aValue, int &aIdx)
wxStaticText * name
UNIT_SELECTOR * unit
@ SOLDERMASK_FILLS_GAPS_PRM
Definition transline.h:81
@ SOLDERMASK_PRESENT_PRM
Definition transline.h:77
@ DIELECTRIC_MODEL_PRM
Definition transline.h:75
@ EPSILONR_SPEC_FREQ_PRM
Definition transline.h:76
@ SOLDERMASK_TAND_PRM
Definition transline.h:80
@ SOLDERMASK_EPSILONR_PRM
Definition transline.h:79
@ SOLDERMASK_THICKNESS_PRM
Definition transline.h:78
@ DUMMY_PRM
Definition transline.h:61
#define elecprms_cnt
#define substrateprms_cnt
#define frequencyprms_cnt
#define physprms_cnt
@ PRM_TYPE_FREQUENCY
@ PRM_TYPE_SUBS
@ PRM_TYPE_ELEC
@ PRM_TYPE_PHYS
TRANSLINE_TYPE_ID
@ MICROSTRIP_TYPE
@ CPW_TYPE
@ GROUNDED_CPW_TYPE
@ C_MICROSTRIP_TYPE
@ END_OF_LIST_TYPE
@ DEFAULT_TYPE
@ START_OF_LIST_TYPE
@ C_STRIPLINE_TYPE