42#include <wx/filedlg.h>
43#include <fmt/format.h>
51#define FORCE_UPDATE_PINS true
54bool equivalent( SIM_MODEL::DEVICE_T a, SIM_MODEL::DEVICE_T b )
65 std::vector<SCH_FIELD>& aFields ) :
70 m_libraryModelsMgr( &
Prj() ),
71 m_builtinModelsMgr( &
Prj() ),
72 m_prevModel( nullptr ),
74 m_scintillaTricksCode( nullptr ),
75 m_scintillaTricksSubckt( nullptr ),
76 m_firstCategory( nullptr ),
77 m_prevParamGridSelection( nullptr ),
78 m_lastParamGridWidth( 0 )
86 if( !
pin->GetParentSymbol()->HasAlternateBodyStyle() ||
pin->GetBodyStyle() < 2 )
94 return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0;
109 grid->SetCellDisabledTextColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
114 grid->DedicateKey( WXK_RETURN );
115 grid->DedicateKey( WXK_NUMPAD_ENTER );
116 grid->DedicateKey( WXK_UP );
117 grid->DedicateKey( WXK_DOWN );
119#if wxCHECK_VERSION( 3, 3, 0 )
120 grid->AddActionTrigger( wxPGKeyboardAction::Edit, WXK_RETURN );
121 grid->AddActionTrigger( wxPGKeyboardAction::NextProperty, WXK_RETURN );
122 grid->AddActionTrigger( wxPGKeyboardAction::Edit, WXK_NUMPAD_ENTER );
123 grid->AddActionTrigger( wxPGKeyboardAction::NextProperty, WXK_NUMPAD_ENTER );
125 grid->AddActionTrigger( wxPG_ACTION_EDIT, WXK_RETURN );
126 grid->AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_RETURN );
127 grid->AddActionTrigger( wxPG_ACTION_EDIT, WXK_NUMPAD_ENTER );
128 grid->AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_NUMPAD_ENTER );
146 for( wxPropertyGridIterator it = m_paramGrid->GetIterator(); !it.AtEnd(); ++it )
157 m_pinAssignmentsGrid->PopEventHandler(
true );
159 delete m_scintillaTricksCode;
160 delete m_scintillaTricksSubckt;
167 wxCommandEvent dummyEvent;
170 wxString modelParams;
172 bool storeInValue =
false;
177 [&](
const wxString& aFieldName,
const wxString& aValue )
181 if( field.GetName() == aFieldName )
183 field.SetText( aValue );
188 m_fields.emplace_back( &m_symbol, -1, aFieldName );
189 m_fields.back().SetText( aValue );
194 &deviceType, &modelType, &modelParams, &pinMap ) )
198 if( !modelType.IsEmpty() )
209 m_fields[
VALUE_FIELD ].SetText( wxT(
"${SIM.PARAMS}" ) );
214 if( libraryFilename !=
"" )
217 m_rbLibraryModel->SetValue(
true );
219 if( !loadLibrary( libraryFilename, reporter ) )
224 m_libraryPathText->ChangeValue( libraryFilename );
227 m_libraryModelsMgr.CreateModel(
nullptr, m_sortedPartPins, m_fields, reporter );
229 m_modelListBox->Append(
_(
"<unknown>" ) );
230 m_modelListBox->SetSelection( 0 );
235 int modelIdx = m_modelListBox->FindString( modelName );
237 if( modelIdx == wxNOT_FOUND )
239 m_infoBar->ShowMessage( wxString::Format(
_(
"No model named '%s' in library." ),
243 m_modelListBox->SetSelection( 0 );
248 m_modelListBox->SetSelection( modelIdx );
251 m_curModelType = curModel().GetType();
254 if( isIbisLoaded() && ( m_modelListBox->GetSelection() >= 0 ) )
257 wxString sel = m_modelListBox->GetStringSelection();
259 if( m_modelListBoxEntryToLibraryIdx.contains( sel ) )
260 idx = m_modelListBoxEntryToLibraryIdx.at( sel );
263 dynamic_cast<SIM_MODEL_IBIS*
>( &m_libraryModelsMgr.GetModels()[idx].get() );
267 onModelNameChoice( dummyEvent );
271 for(
const std::pair<std::string, std::string>& strs : ibismodel->GetIbisPins() )
278 ibismodel->ChangePin( *ibisLibrary, strs.first );
279 m_pinCombobox->SetSelection(
static_cast<int>( i ) );
285 if( i <
static_cast<int>( ibismodel->GetIbisPins().size() ) )
287 onPinCombobox( dummyEvent );
289 m_pinModelCombobox->SetStringSelection(
295 ibismodel->SwitchSingleEndedDiff(
true );
296 m_differentialCheckbox->SetValue(
true );
300 ibismodel->SwitchSingleEndedDiff(
false );
301 m_differentialCheckbox->SetValue(
false );
310 m_rbBuiltinModel->SetValue(
true );
319 for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
321 if( m_rbBuiltinModel->GetValue() && type == m_curModelType )
324 m_builtinModelsMgr.CreateModel( m_fields, m_sortedPartPins,
false, reporter );
334 m_builtinModelsMgr.CreateModel( type, m_sortedPartPins, reporter );
339 if( !m_curModelTypeOfDeviceType.count( deviceTypeT ) )
340 m_curModelTypeOfDeviceType[deviceTypeT] = type;
344 curModel().SetIsStoredInValue(
true );
346 m_saveInValueCheckbox->SetValue( curModel().IsStoredInValue() );
348 onRadioButton( dummyEvent );
349 return DIALOG_SIM_MODEL_BASE::TransferDataToWindow();
356 m_pinAssignmentsGrid->CommitPendingChanges();
357 m_paramGrid->GetGrid()->CommitChangesFromEditor();
359 if( !DIALOG_SIM_MODEL_BASE::TransferDataFromWindow() )
366 if( m_rbLibraryModel->GetValue() )
368 path = m_libraryPathText->GetValue();
369 wxFileName fn(
path );
371 if( fn.MakeRelativeTo(
Prj().GetProjectPath() ) && !fn.GetFullPath().StartsWith(
".." ) )
372 path = fn.GetFullPath();
374 if( m_modelListBox->GetSelection() >= 0 )
375 name = m_modelListBox->GetStringSelection().ToStdString();
386 wxString sel = m_modelListBox->GetStringSelection();
388 if( m_modelListBoxEntryToLibraryIdx.contains( sel ) )
389 idx = m_modelListBoxEntryToLibraryIdx.at( sel );
392 static_cast<SIM_MODEL_IBIS*
>( &m_libraryModelsMgr.GetModels().at( idx ).get() );
397 std::string modelName = std::string( m_pinModelCombobox->GetValue().c_str() );
398 std::string differential;
400 if( m_pinCombobox->GetSelection() >= 0 )
401 pins = ibismodel->GetIbisPins().at( m_pinCombobox->GetSelection() ).first;
403 if( ibismodel->CanDifferential() && m_differentialCheckbox->GetValue() )
412 if( model.
GetType() == SIM_MODEL::TYPE::RAWSPICE )
414 if( m_modelNotebook->GetSelection() == 0 )
415 updateModelCodeTab( &model );
417 wxString code = m_codePreview->GetText().Trim(
true ).Trim(
false );
418 model.
SetParamValue(
"model", std::string( code.ToUTF8() ) );
423 for(
int row = 0; row < m_pinAssignmentsGrid->GetNumberRows(); ++row )
425 wxString modelPinName = m_pinAssignmentsGrid->GetCellValue( row, PIN_COLUMN::MODEL );
426 wxString symbolPinName = m_sortedPartPins.at( row )->GetShownNumber();
429 std::string( symbolPinName.ToUTF8() ) );
432 removeOrphanedPinAssignments( &model );
434 curModel().WriteFields( m_fields );
445 m_browseButton->Enable();
448 bool undetermined = !m_rbLibraryModel->GetValue() && !m_rbBuiltinModel->GetValue();
449 bool enableLibCtrls = m_rbLibraryModel->GetValue() || undetermined;
450 bool enableBuiltinCtrls = m_rbBuiltinModel->GetValue() || undetermined;
452 m_pathLabel->Enable( enableLibCtrls );
453 m_libraryPathText->Enable( enableLibCtrls );
454 m_modelNameLabel->Enable( enableLibCtrls );
455 m_modelFilter->Enable( enableLibCtrls && !isIbisLoaded() );
456 m_modelListBox->Enable( enableLibCtrls );
457 m_pinLabel->Enable( enableLibCtrls );
458 m_pinCombobox->Enable( enableLibCtrls );
459 m_differentialCheckbox->Enable( enableLibCtrls );
460 m_pinModelLabel->Enable( enableLibCtrls );
461 m_pinModelCombobox->Enable( enableLibCtrls );
462 m_waveformLabel->Enable( enableLibCtrls );
463 m_waveformChoice->Enable( enableLibCtrls );
465 m_deviceLabel->Enable( enableBuiltinCtrls );
466 m_deviceChoice->Enable( enableBuiltinCtrls );
467 m_deviceSubtypeLabel->Enable( enableBuiltinCtrls );
468 m_deviceSubtypeChoice->Enable( enableBuiltinCtrls );
472 updateIbisWidgets( model );
473 updateBuiltinModelWidgets( model );
474 updateModelParamsTab( model );
475 updateModelCodeTab( model );
476 updatePinAssignments( model, model != m_prevModel );
480 m_modelPanel->Layout();
481 m_pinAssignmentsPanel->Layout();
482 m_parametersPanel->Layout();
483 m_codePanel->Layout();
485 SendSizeEvent( wxSEND_EVENT_POST );
487 m_prevModel = &curModel();
497 m_pinLabel->Show( isIbisLoaded() );
498 m_pinCombobox->Show( isIbisLoaded() );
499 m_pinModelLabel->Show( isIbisLoaded() );
500 m_pinModelCombobox->Show( isIbisLoaded() );
501 m_waveformLabel->Show( isIbisLoaded() );
502 m_waveformChoice->Show( isIbisLoaded() );
504 if( aModel != m_prevModel )
506 m_waveformChoice->Clear();
510 for( SIM_MODEL::TYPE type : { SIM_MODEL::TYPE::KIBIS_DEVICE,
511 SIM_MODEL::TYPE::KIBIS_DRIVER_DC,
512 SIM_MODEL::TYPE::KIBIS_DRIVER_RECT,
513 SIM_MODEL::TYPE::KIBIS_DRIVER_PRBS } )
523 if( type == aModel->
GetType() )
524 m_waveformChoice->SetSelection( m_waveformChoice->GetCount() - 1 );
530 m_differentialCheckbox->Show( isIbisLoaded() && modelibis && modelibis->
CanDifferential() );
531 m_modelNameLabel->SetLabel( isIbisLoaded() ?
_(
"Component:" ) :
_(
"Model:" ) );
539 if( aModel != m_prevModel )
541 m_deviceChoice->Clear();
542 m_deviceSubtypeChoice->Clear();
544 if( !m_rbLibraryModel->GetValue() )
546 for( SIM_MODEL::DEVICE_T deviceType : SIM_MODEL::DEVICE_T_ITERATOR() )
554 m_deviceChoice->SetSelection( m_deviceChoice->GetCount() - 1 );
557 for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
559 if( type == SIM_MODEL::TYPE::KIBIS_DEVICE
560 || type == SIM_MODEL::TYPE::KIBIS_DRIVER_DC
561 || type == SIM_MODEL::TYPE::KIBIS_DRIVER_RECT
562 || type == SIM_MODEL::TYPE::KIBIS_DRIVER_PRBS )
575 if( type == aModel->
GetType() )
576 m_deviceSubtypeChoice->SetSelection( m_deviceSubtypeChoice->GetCount()
582 m_deviceSubtypeLabel->Show( m_deviceSubtypeChoice->GetCount() > 1 );
583 m_deviceSubtypeChoice->Show( m_deviceSubtypeChoice->GetCount() > 1 );
587 m_modelNotebook->SetSelection( 1 );
589 m_modelNotebook->SetSelection( 0 );
595 m_saveInValueCheckbox->SetLabel( wxString::Format(
_(
"Save parameter '%s (%s)' in Value "
599 m_saveInValueCheckbox->Enable(
true );
603 m_saveInValueCheckbox->SetLabel(
_(
"Save primary parameter in Value field" ) );
604 m_saveInValueCheckbox->SetValue(
false );
605 m_saveInValueCheckbox->Enable(
false );
613 if( aModel != m_prevModel )
618 m_paramGridMgr->SetColumnCount( PARAM_COLUMN::END_ );
620 m_paramGridMgr->SetColumnTitle( PARAM_COLUMN::DESCRIPTION,
_(
"Parameter" ) );
621 m_paramGridMgr->SetColumnTitle( PARAM_COLUMN::UNIT,
_(
"Unit" ) );
622 m_paramGridMgr->SetColumnTitle( PARAM_COLUMN::DEFAULT,
_(
"Default" ) );
623 m_paramGridMgr->SetColumnTitle( PARAM_COLUMN::TYPE,
_(
"Type" ) );
625 m_paramGridMgr->ShowHeader();
628 m_paramGrid->Clear();
630 m_firstCategory = m_paramGrid->Append(
new wxPropertyCategory(
"Geometry" ) );
631 m_paramGrid->HideProperty(
"Geometry" );
633 m_paramGrid->Append(
new wxPropertyCategory(
"AC" ) );
634 m_paramGrid->HideProperty(
"AC" );
636 m_paramGrid->Append(
new wxPropertyCategory(
"DC" ) );
637 m_paramGrid->HideProperty(
"DC" );
639 m_paramGrid->Append(
new wxPropertyCategory(
"S-Parameters" ) );
640 m_paramGrid->HideProperty(
"S-Parameters" );
642 m_paramGrid->Append(
new wxPropertyCategory(
"Capacitance" ) );
643 m_paramGrid->HideProperty(
"Capacitance" );
645 m_paramGrid->Append(
new wxPropertyCategory(
"Temperature" ) );
646 m_paramGrid->HideProperty(
"Temperature" );
648 m_paramGrid->Append(
new wxPropertyCategory(
"Noise" ) );
649 m_paramGrid->HideProperty(
"Noise" );
651 m_paramGrid->Append(
new wxPropertyCategory(
"Distributed Quantities" ) );
652 m_paramGrid->HideProperty(
"Distributed Quantities" );
654 m_paramGrid->Append(
new wxPropertyCategory(
"Waveform" ) );
655 m_paramGrid->HideProperty(
"Waveform" );
657 m_paramGrid->Append(
new wxPropertyCategory(
"Limiting Values" ) );
658 m_paramGrid->HideProperty(
"Limiting Values" );
660 m_paramGrid->Append(
new wxPropertyCategory(
"Advanced" ) );
661 m_paramGrid->HideProperty(
"Advanced" );
663 m_paramGrid->Append(
new wxPropertyCategory(
"Flags" ) );
664 m_paramGrid->HideProperty(
"Flags" );
666 m_paramGrid->CollapseAll();
669 addParamPropertyIfRelevant( aModel, i );
671 m_paramGrid->CollapseAll();
672 m_paramGrid->Expand(
"AC" );
673 m_paramGrid->Expand(
"Waveform" );
676 adjustParamGridColumns( m_paramGrid->GetGrid()->GetSize().GetX(),
true );
680 for( wxPropertyGridIterator it = m_paramGrid->GetIterator(); !it.AtEnd(); ++it )
682 wxColour bgCol = m_paramGrid->GetGrid()->GetPropertyDefaultCell().GetBgCol();
683 wxColour fgCol = m_paramGrid->GetGrid()->GetPropertyDefaultCell().GetFgCol();
685 for(
int col = 0; col < m_paramGridMgr->GetColumnCount(); ++col )
687 ( *it )->GetCell( col ).SetBgCol( bgCol );
688 ( *it )->GetCell( col ).SetFgCol( fgCol );
702 ( *it )->SetValueFromString( param.
value );
716 item.
modelName = m_modelListBox->GetStringSelection();
718 if( m_rbBuiltinModel->GetValue() || item.
modelName ==
"" )
723 m_codePreview->SetText(
text );
724 m_codePreview->SelectNone();
731 if( m_pinAssignmentsGrid->GetNumberRows() == 0 )
733 m_pinAssignmentsGrid->AppendRows(
static_cast<int>( m_sortedPartPins.size() ) );
735 for(
int ii = 0; ii < m_pinAssignmentsGrid->GetNumberRows(); ++ii )
737 wxString symbolPinString = getSymbolPinString( ii );
739 m_pinAssignmentsGrid->SetReadOnly( ii, PIN_COLUMN::SYMBOL );
740 m_pinAssignmentsGrid->SetCellValue( ii, PIN_COLUMN::SYMBOL, symbolPinString );
743 aForceUpdatePins =
true;
746 if( aForceUpdatePins )
749 for(
int row = 0; row < m_pinAssignmentsGrid->GetNumberRows(); ++row )
750 m_pinAssignmentsGrid->SetCellValue( row, PIN_COLUMN::MODEL,
_(
"Not Connected" ) );
753 for(
int modelPinIndex = 0; modelPinIndex < aModel->
GetPinCount(); ++modelPinIndex )
757 if( symbolPinNumber ==
"" )
760 int symbolPinRow = findSymbolPinRow( symbolPinNumber );
762 if( symbolPinRow == -1 )
765 wxString modelPinString = getModelPinString( aModel, modelPinIndex );
766 m_pinAssignmentsGrid->SetCellValue( symbolPinRow, PIN_COLUMN::MODEL, modelPinString );
770 for(
int ii = 0; ii < m_pinAssignmentsGrid->GetNumberRows(); ++ii )
773 std::vector<BITMAPS> modelPinIcons;
774 wxArrayString modelPinChoices;
776 for(
int jj = 0; jj < aModel->
GetPinCount(); ++jj )
783 modelPinChoices.Add( getModelPinString( aModel, jj ) );
787 modelPinChoices.Add(
_(
"Not Connected" ) );
791 m_pinAssignmentsGrid->SetCellEditor( ii, PIN_COLUMN::MODEL,
798 if( aModel->
GetType() == SIM_MODEL::TYPE::SUBCKT )
802 m_subckt->SetEditable(
false );
806 m_subcktLabel->Show(
false );
807 m_subckt->Show(
false );
827 if( m_prevLibrary == aLibraryPath && !aForceReload )
830 m_libraryModelsMgr.SetForceFullParse();
831 m_libraryModelsMgr.SetLibrary( aLibraryPath, aReporter );
838 for(
const auto& [baseModelName, baseModel] :
library()->GetModels() )
840 if( baseModelName == modelName )
841 m_libraryModelsMgr.CreateModel( &baseModel, m_sortedPartPins, m_fields, aReporter );
843 m_libraryModelsMgr.CreateModel( &baseModel, m_sortedPartPins, aReporter );
846 m_rbLibraryModel->SetValue(
true );
847 m_libraryPathText->ChangeValue( aLibraryPath );
849 m_modelListBoxEntryToLibraryIdx.clear();
850 wxArrayString modelNames;
852 bool modelNameExists =
false;
853 for(
const auto& [
name, model] :
library()->GetModels() )
855 modelNames.Add(
name );
856 m_modelListBoxEntryToLibraryIdx[
name] = m_modelListBoxEntryToLibraryIdx.size();
857 if(
name == modelName )
858 modelNameExists =
true;
863 m_modelListBox->Clear();
864 m_modelListBox->Append( modelNames );
866 if( !modelNameExists )
868 m_infoBar->ShowMessage(
869 wxString::Format(
_(
"No model named '%s' in '%s'." ), modelName, aLibraryPath ) );
875 wxArrayString emptyArray;
876 m_pinModelCombobox->Set( emptyArray );
877 m_pinCombobox->Set( emptyArray );
878 m_pinModelCombobox->SetSelection( -1 );
879 m_pinCombobox->SetSelection( -1 );
882 m_modelListBox->SetStringSelection( modelName );
884 if( m_modelListBox->GetSelection() < 0 && m_modelListBox->GetCount() > 0 )
885 m_modelListBox->SetSelection( 0 );
887 m_curModelType = curModel().GetType();
889 m_prevLibrary = aLibraryPath;
903 m_paramGrid->HideProperty(
"AC",
false );
904 m_paramGrid->AppendIn(
"AC", newParamProperty( aModel, aParamIndex ) );
908 m_paramGrid->HideProperty(
"DC",
false );
909 m_paramGrid->AppendIn(
"DC", newParamProperty( aModel, aParamIndex ) );
912 case CATEGORY::S_PARAM:
913 m_paramGrid->HideProperty(
"S-Parameters",
false );
914 m_paramGrid->AppendIn(
"S-Parameters", newParamProperty( aModel, aParamIndex ) );
917 case CATEGORY::CAPACITANCE:
918 m_paramGrid->HideProperty(
"Capacitance",
false );
919 m_paramGrid->AppendIn(
"Capacitance", newParamProperty( aModel, aParamIndex ) );
922 case CATEGORY::TEMPERATURE:
923 m_paramGrid->HideProperty(
"Temperature",
false );
924 m_paramGrid->AppendIn(
"Temperature", newParamProperty( aModel, aParamIndex ) );
927 case CATEGORY::NOISE:
928 m_paramGrid->HideProperty(
"Noise",
false );
929 m_paramGrid->AppendIn(
"Noise", newParamProperty( aModel, aParamIndex ) );
932 case CATEGORY::DISTRIBUTED_QUANTITIES:
933 m_paramGrid->HideProperty(
"Distributed Quantities",
false );
934 m_paramGrid->AppendIn(
"Distributed Quantities", newParamProperty( aModel, aParamIndex ) );
937 case CATEGORY::WAVEFORM:
938 m_paramGrid->HideProperty(
"Waveform",
false );
939 m_paramGrid->AppendIn(
"Waveform", newParamProperty( aModel, aParamIndex ) );
942 case CATEGORY::GEOMETRY:
943 m_paramGrid->HideProperty(
"Geometry",
false );
944 m_paramGrid->AppendIn(
"Geometry", newParamProperty( aModel, aParamIndex ) );
947 case CATEGORY::LIMITING_VALUES:
948 m_paramGrid->HideProperty(
"Limiting Values",
false );
949 m_paramGrid->AppendIn(
"Limiting Values", newParamProperty( aModel, aParamIndex ) );
952 case CATEGORY::ADVANCED:
953 m_paramGrid->HideProperty(
"Advanced",
false );
954 m_paramGrid->AppendIn(
"Advanced", newParamProperty( aModel, aParamIndex ) );
957 case CATEGORY::FLAGS:
958 m_paramGrid->HideProperty(
"Flags",
false );
959 m_paramGrid->AppendIn(
"Flags", newParamProperty( aModel, aParamIndex ) );
963 m_paramGrid->Insert( m_firstCategory, newParamProperty( aModel, aParamIndex ) );
966 case CATEGORY::INITIAL_CONDITIONS:
967 case CATEGORY::SUPERFLUOUS:
977 wxString paramDescription;
980 paramDescription = wxString::Format(
"%s", param.
info.
name );
984 wxPGProperty* prop =
nullptr;
991 prop->SetAttribute( wxPG_BOOL_USE_CHECKBOX,
true );
1013 wxArrayString inductors;
1025 if( item.model->GetDeviceType() == SIM_MODEL::DEVICE_T::L )
1026 inductors.push_back( item.refName );
1030 [](
const wxString& a,
const wxString& b ) ->
int
1036 if( inductors.empty() )
1044 aParamIndex, inductors );
1054 wxArrayString values;
1057 values.Add(
string );
1065 prop =
new wxStringProperty( paramDescription, param.
info.
name );
1069 prop->SetAttribute( wxPG_ATTR_UNITS, wxString::FromUTF8( param.
info.
unit.c_str() ) );
1089 prop->SetCell( PARAM_COLUMN::TYPE, typeStr );
1095template <
typename T>
1098 for(
int row = 0; row < static_cast<int>( m_sortedPartPins.size() ); ++row )
1102 if(
pin->GetNumber() == aSymbolPinNumber )
1110template <
typename T>
1113 if( m_rbLibraryModel->GetValue() )
1115 wxString sel = m_modelListBox->GetStringSelection();
1117 if( m_modelListBoxEntryToLibraryIdx.contains( sel ) )
1118 return m_libraryModelsMgr.GetModels()
1119 .at( m_modelListBoxEntryToLibraryIdx.at( sel ) )
1124 if(
static_cast<int>( m_curModelType )
1125 <
static_cast<int>( m_builtinModelsMgr.GetModels().size() ) )
1126 return m_builtinModelsMgr.GetModels().at(
static_cast<int>( m_curModelType ) );
1129 return m_builtinModelsMgr.GetModels().at(
static_cast<int>( SIM_MODEL::TYPE::NONE ) );
1133template <
typename T>
1136 if( m_libraryModelsMgr.GetLibraries().size() == 1 )
1137 return &m_libraryModelsMgr.GetLibraries().begin()->second.get();
1143template <
typename T>
1146 SCH_PIN*
pin = m_sortedPartPins.at( symbolPinIndex );
1152 pinNumber =
pin->GetShownNumber();
1153 pinName =
pin->GetShownName();
1156 if( !pinName.IsEmpty() && pinName != pinNumber )
1157 pinNumber += wxString::Format( wxT(
" (\"%s\")" ), pinName );
1163template <
typename T>
1170 wxString modelPinNumber = wxString::Format(
"%d", aModelPinIndex + 1 );
1172 if( !modelPinName.IsEmpty() && modelPinName != modelPinNumber )
1173 modelPinNumber += wxString::Format( wxT(
" (\"%s\")" ), modelPinName );
1175 return modelPinNumber;
1179template <
typename T>
1182 if( aModelPinString ==
"Not Connected" )
1185 int length = aModelPinString.Find(
" " );
1187 if( length == wxNOT_FOUND )
1188 length =
static_cast<int>( aModelPinString.Length() );
1191 aModelPinString.Mid( 0, length ).ToCLong( &result );
1193 return static_cast<int>( result - 1 );
1197template <
typename T>
1200 m_prevModel =
nullptr;
1205template <
typename T>
1208 m_rbLibraryModel->SetValue(
true );
1212template <
typename T>
1215 m_rbLibraryModel->SetValue(
true );
1218 wxString
path = m_libraryPathText->GetValue();
1220 if( loadLibrary(
path, reporter,
true ) ||
path.IsEmpty() )
1229template <
typename T>
1239 wxCommandEvent
dummy;
1240 onLibraryPathTextEnter(
dummy );
1247template <
typename T>
1250 static wxString s_mruPath;
1253 wxFileDialog dlg(
this,
_(
"Browse Models" ),
path );
1255 if( dlg.ShowModal() == wxID_CANCEL )
1258 m_rbLibraryModel->SetValue(
true );
1260 path = dlg.GetPath();
1261 wxFileName fn(
path );
1263 s_mruPath = fn.GetPath();
1265 if( fn.MakeRelativeTo(
Prj().GetProjectPath() ) && !fn.GetFullPath().StartsWith( wxS(
".." ) ) )
1266 path = fn.GetFullPath();
1270 if( loadLibrary(
path, reporter,
true ) )
1279template <
typename T>
1282 int sel = m_modelListBox->GetSelection();
1284 switch( aKeyStroke.GetKeyCode() )
1287 if( sel == wxNOT_FOUND )
1288 sel = m_modelListBox->GetCount() - 1;
1295 if( sel == wxNOT_FOUND )
1303 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
1311 if( sel >= 0 && sel < (
int) m_modelListBox->GetCount() )
1312 m_modelListBox->SetSelection( sel );
1316template <
typename T>
1319 wxArrayString modelNames;
1320 wxString current = m_modelListBox->GetStringSelection();
1321 wxString
filter = wxT(
"*" ) + m_modelFilter->GetValue() + wxT(
"*" );
1323 for(
const auto& [
name, model] :
library()->GetModels() )
1325 wxString wx_name(
name );
1327 if( wx_name.Matches(
filter ) )
1328 modelNames.Add( wx_name );
1333 m_modelListBox->Clear();
1334 m_modelListBox->Append( modelNames );
1336 if( !m_modelListBox->SetStringSelection( current ) )
1337 m_modelListBox->SetSelection( 0 );
1341template <
typename T>
1344 if( isIbisLoaded() )
1346 wxArrayString pinLabels;
1349 wxCHECK2( modelkibis,
return );
1351 for( std::pair<wxString, wxString> strs : modelkibis->
GetIbisPins() )
1352 pinLabels.Add( strs.first + wxT(
" - " ) + strs.second );
1354 m_pinCombobox->Set( pinLabels );
1356 wxArrayString emptyArray;
1357 m_pinModelCombobox->Set( emptyArray );
1360 m_rbLibraryModel->SetValue(
true );
1365 wxArrayString lines = wxSplit( fallback->GetSpiceCode(),
'\n' );
1368 for(
const wxString& line : lines )
1370 if( !line.StartsWith(
'*' ) )
1372 if( !code.IsEmpty() )
1379 m_infoBar->ShowMessage( wxString::Format(
_(
"Failed to parse:\n\n"
1381 "Using generic SPICE model." ),
1393template <
typename T>
1396 wxArrayString modelLabels;
1400 std::vector<std::pair<std::string, std::string>> strs = ibisModel.
GetIbisPins();
1401 std::string pinNumber = strs.at( m_pinCombobox->GetSelection() ).first;
1405 ibisModel.
ChangePin( *ibisLibrary, pinNumber );
1410 modelLabels.Add( modelName );
1412 m_pinModelCombobox->Set( modelLabels );
1414 if( m_pinModelCombobox->GetCount() == 1 )
1415 m_pinModelCombobox->SetSelection( 0 );
1417 m_pinModelCombobox->SetSelection( -1 );
1423template <
typename T>
1426 m_pinCombobox->SetSelection( m_pinCombobox->FindString( m_pinCombobox->GetValue() ) );
1428 onPinModelCombobox( aEvent );
1432template <
typename T>
1439template <
typename T>
1442 m_pinModelCombobox->SetSelection(
1443 m_pinModelCombobox->FindString( m_pinModelCombobox->GetValue() ) );
1447template <
typename T>
1452 bool diff = m_differentialCheckbox->GetValue() && modelibis->CanDifferential();
1453 modelibis->SwitchSingleEndedDiff( diff );
1460template <
typename T>
1463 m_rbBuiltinModel->SetValue(
true );
1465 for( SIM_MODEL::DEVICE_T deviceType : SIM_MODEL::DEVICE_T_ITERATOR() )
1468 == m_deviceChoice->GetStringSelection() )
1470 m_curModelType = m_curModelTypeOfDeviceType.at( deviceType );
1479template <
typename T>
1482 SIM_MODEL::DEVICE_T deviceType = curModel().GetDeviceType();
1483 wxString typeDescription = m_waveformChoice->GetStringSelection();
1485 for( SIM_MODEL::TYPE type : { SIM_MODEL::TYPE::KIBIS_DEVICE,
1486 SIM_MODEL::TYPE::KIBIS_DRIVER_DC,
1487 SIM_MODEL::TYPE::KIBIS_DRIVER_RECT,
1488 SIM_MODEL::TYPE::KIBIS_DRIVER_PRBS } )
1494 wxString sel = m_modelListBox->GetStringSelection();
1496 if( m_modelListBoxEntryToLibraryIdx.contains( sel ) )
1497 idx = m_modelListBoxEntryToLibraryIdx.at( sel );
1500 static_cast<SIM_MODEL_IBIS&
>( m_libraryModelsMgr.GetModels()[idx].get() );
1502 m_libraryModelsMgr.SetModel( idx, std::make_unique<SIM_MODEL_IBIS>( type, baseModel ) );
1506 m_libraryModelsMgr.GetModels()[idx].get().
ReadDataFields( &m_fields,
1514 m_curModelType = type;
1519 m_curModelTypeOfDeviceType.at( deviceType ) = m_curModelType;
1524template <
typename T>
1527 SIM_MODEL::DEVICE_T deviceType = curModel().GetDeviceType();
1528 wxString typeDescription = m_deviceSubtypeChoice->GetStringSelection();
1530 for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
1535 m_curModelType = type;
1540 m_curModelTypeOfDeviceType.at( deviceType ) = m_curModelType;
1545template <
typename T>
1548 updateModelCodeTab( &curModel() );
1552template <
typename T>
1555 int symbolPinIndex = aEvent.GetRow();
1556 wxString oldModelPinName = aEvent.GetString();
1557 wxString modelPinName = m_pinAssignmentsGrid->GetCellValue( aEvent.GetRow(), aEvent.GetCol() );
1559 int oldModelPinIndex = getModelPinIndex( oldModelPinName );
1560 int modelPinIndex = getModelPinIndex( modelPinName );
1563 curModel().AssignSymbolPinNumberToModelPin( oldModelPinIndex,
"" );
1567 SCH_PIN* symbolPin = m_sortedPartPins.at( symbolPinIndex );
1569 curModel().AssignSymbolPinNumberToModelPin( modelPinIndex, symbolPin->
GetShownNumber() );
1578template <
typename T>
1581 wxGridUpdateLocker deferRepaintsTillLeavingScope( m_pinAssignmentsGrid );
1584 m_pinAssignmentsGrid->SetColSize( PIN_COLUMN::MODEL, gridWidth / 2 );
1585 m_pinAssignmentsGrid->SetColSize( PIN_COLUMN::SYMBOL, gridWidth / 2 );
1591template <
typename T>
1597 wxPropertyGrid*
grid = m_paramGrid->GetGrid();
1598 wxPGProperty* selected =
grid->GetSelection();
1601 selected =
grid->wxPropertyGridInterface::GetFirst();
1603#if wxCHECK_VERSION( 3, 3, 0 )
1605 grid->DoSelectProperty( selected, wxPGSelectPropertyFlags::Focus );
1608 grid->DoSelectProperty( selected, wxPG_SEL_FOCUS );
1615template <
typename T>
1618 wxPropertyGrid*
grid = m_paramGrid->GetGrid();
1621 if(
grid->GetSelection() &&
grid->GetSelection()->IsCategory() )
1623 wxPGProperty* selection =
grid->GetSelection();
1628 wxPropertyGridIterator it =
grid->GetIterator( wxPG_ITERATE_VISIBLE, selection );
1631 wxKeyEvent* keyEvent =
new wxKeyEvent( wxEVT_KEY_DOWN );
1633 if( *it == m_prevParamGridSelection )
1635 if( !selection->IsExpanded() )
1637 grid->Expand( selection );
1638 keyEvent->m_keyCode = WXK_DOWN;
1639 wxQueueEvent(
grid, keyEvent );
1647 keyEvent->m_keyCode = WXK_UP;
1648 wxQueueEvent(
grid, keyEvent );
1653 if( !selection->IsExpanded() )
1654 grid->Expand( selection );
1656 keyEvent->m_keyCode = WXK_DOWN;
1657 wxQueueEvent(
grid, keyEvent );
1660 m_prevParamGridSelection =
grid->GetSelection();
1664 wxWindow* editorControl =
grid->GetEditorControl();
1666 if( !editorControl )
1668 m_prevParamGridSelection =
grid->GetSelection();
1673 editorControl->SetFocus();
1674 m_prevParamGridSelection =
grid->GetSelection();
1678template <
typename T>
1689 wxPropertyGrid*
grid = m_paramGrid->GetGrid();
1690 wxTextCtrl* ctrl =
grid->GetEditorTextCtrl();
1694 wxRect ctrlRect = ctrl->GetScreenRect();
1695 wxRect gridRect =
grid->GetScreenRect();
1697 if( ctrlRect.GetTop() < gridRect.GetTop() || ctrlRect.GetBottom() > gridRect.GetBottom() )
1698 grid->ClearSelection();
1704template <
typename T>
1707 wxPropertyGrid*
grid = m_paramGridMgr->GetGrid();
1711 if( aWidth != m_lastParamGridWidth || aForce )
1713 m_lastParamGridWidth = aWidth;
1717 std::vector<int> colWidths;
1719 for(
size_t ii = 0; ii <
grid->GetColumnCount(); ii++ )
1721 if( ii == PARAM_COLUMN::DESCRIPTION )
1722 colWidths.push_back(
grid->GetState()->GetColumnWidth( ii ) + margin + indent );
1723 else if( ii == PARAM_COLUMN::VALUE )
1724 colWidths.push_back( std::max( 72,
1725 grid->GetState()->GetColumnWidth( ii ) ) + margin );
1727 colWidths.push_back( 60 + margin );
1729 aWidth -= colWidths[ ii ];
1732 for(
size_t ii = 0; ii <
grid->GetColumnCount(); ii++ )
1733 grid->SetColumnProportion( ii, colWidths[ ii ] );
1735 grid->ResetColumnSizes();
1736 grid->RefreshEditor();
1741template <
typename T>
1744 adjustParamGridColumns( event.GetSize().GetX(),
false );
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
Class DIALOG_SIM_MODEL_BASE.
wxStaticText * m_subcktLabel
wxPropertyGridManager * m_paramGridMgr
wxChoice * m_deviceSubtypeChoice
wxChoice * m_deviceChoice
wxChoice * m_waveformChoice
WX_GRID * m_pinAssignmentsGrid
STD_BITMAP_BUTTON * m_browseButton
wxStyledTextCtrl * m_subckt
wxPropertyGridPage * m_paramGrid
wxStyledTextCtrl * m_codePreview
void onTypeChoice(wxCommandEvent &aEvent) override
void onLibraryPathTextKillFocus(wxFocusEvent &aEvent) override
wxString getSymbolPinString(int aSymbolPinNumber) const
void updateBuiltinModelWidgets(SIM_MODEL *aModel)
void onPinAssignmentsGridCellChange(wxGridEvent &aEvent) override
void onFilterCharHook(wxKeyEvent &aKeyStroke) override
int findSymbolPinRow(const wxString &aSymbolPinNumber) const
void onModelNameChoice(wxCommandEvent &aEvent) override
void onRadioButton(wxCommandEvent &aEvent) override
SCINTILLA_TRICKS * m_scintillaTricksSubckt
bool loadLibrary(const wxString &aLibraryPath, REPORTER &aReporter, bool aForceReload=false)
int getModelPinIndex(const wxString &aModelPinString) const
void onModelFilter(wxCommandEvent &aEvent) override
void onLibraryPathText(wxCommandEvent &aEvent) override
void onDifferentialCheckbox(wxCommandEvent &event) override
void onParamGridSelectionChange(wxPropertyGridEvent &aEvent)
void removeOrphanedPinAssignments(SIM_MODEL *aModel)
void adjustParamGridColumns(int aWidth, bool aForce)
std::vector< SCH_PIN * > m_sortedPartPins
Pins of the current part.
wxPGProperty * newParamProperty(SIM_MODEL *aModel, int aParamIndex) const
void onPinModelCombobox(wxCommandEvent &event) override
const SIM_LIBRARY * library() const
SIM_MODEL & curModel() const
void onBrowseButtonClick(wxCommandEvent &aEvent) override
void onPinComboboxTextEnter(wxCommandEvent &event) override
void onPinCombobox(wxCommandEvent &event) override
SCINTILLA_TRICKS * m_scintillaTricksCode
void updatePinAssignments(SIM_MODEL *aModel, bool aForceUpdatePins)
void onUpdateUI(wxUpdateUIEvent &aEvent)
DIALOG_SIM_MODEL(wxWindow *aParent, EDA_BASE_FRAME *aFrame, T &aSymbol, std::vector< SCH_FIELD > &aFields)
wxString getModelPinString(SIM_MODEL *aModel, int aModelPinIndex) const
void onPinAssignmentsGridSize(wxSizeEvent &aEvent) override
void updateIbisWidgets(SIM_MODEL *aModel)
void onParamGridSetFocus(wxFocusEvent &aEvent)
void updateModelParamsTab(SIM_MODEL *aModel)
bool TransferDataFromWindow() override
void updateModelCodeTab(SIM_MODEL *aModel)
void onSizeParamGrid(wxSizeEvent &event) override
void onPageChanging(wxNotebookEvent &event) override
void onWaveformChoice(wxCommandEvent &aEvent) override
void onPinModelComboboxTextEnter(wxCommandEvent &event) override
void onLibraryPathTextEnter(wxCommandEvent &aEvent) override
void onDeviceTypeChoice(wxCommandEvent &aEvent) override
bool TransferDataToWindow() override
void addParamPropertyIfRelevant(SIM_MODEL *aModel, int aParamIndex)
The base frame for deriving all KiCad main window classes.
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
virtual bool ReadSchematicAndLibraries(unsigned aNetlistOptions, REPORTER &aReporter)
Process the schematic and Spice libraries to create net mapping and a list of SPICE_ITEMs.
const std::list< SPICE_ITEM > & GetItems() const
Return the list of items representing schematic symbols in the Spice world.
A singleton reporter that reports to nowhere.
virtual const wxString GetProjectPath() const
Return the full path of the project.
A pure virtual class used to derive REPORTER objects from.
virtual bool HasMessageOfSeverity(int aSeverityMask) const
Returns true if the reporter has one or more messages matching the specified severity mask.
Schematic editor (Eeschema) main window.
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
wxString GetShownNumber() const
Add cut/copy/paste, dark theme, autocomplete and brace highlighting to a wxStyleTextCtrl instance.
static constexpr auto MODEL_FIELD
static constexpr auto PIN_FIELD
static constexpr auto DIFF_FIELD
bool isPinDiff(const std::string &aComp, const std::string &aPinNumber) const
static constexpr auto LIBRARY_FIELD
static constexpr auto NAME_FIELD
std::vector< std::pair< std::string, std::string > > GetIbisPins() const
bool CanDifferential() const
std::vector< std::string > GetIbisModels() const
bool ChangePin(const SIM_LIBRARY_IBIS &aLib, const std::string &aPinNumber)
update the list of available models based on the pin number.
std::string GetComponentName() const
std::string GetSpiceCode() const
static TYPE ReadTypeFromFields(const std::vector< SCH_FIELD > &aFields, REPORTER &aReporter)
static INFO TypeInfo(TYPE aType)
static void SetFieldValue(std::vector< SCH_FIELD > &aFields, const wxString &aFieldName, const std::string &aValue, bool aIsVisible=true)
void ReadDataFields(const std::vector< SCH_FIELD > *aFields, const std::vector< SCH_PIN * > &aPins)
const SPICE_GENERATOR & SpiceGenerator() const
virtual const PARAM & GetParam(unsigned aParamIndex) const
static bool InferSimModel(T &aSymbol, std::vector< SCH_FIELD > *aFields, bool aResolve, SIM_VALUE_GRAMMAR::NOTATION aNotation, wxString *aDeviceType, wxString *aModelType, wxString *aModelParams, wxString *aPinMap)
static std::string GetFieldValue(const std::vector< SCH_FIELD > *aFields, const wxString &aFieldName, bool aResolve=true)
int GetParamCount() const
void AssignSymbolPinNumberToModelPin(int aPinIndex, const wxString &aSymbolPinNumber)
DEVICE_INFO GetDeviceInfo() const
DEVICE_T GetDeviceType() const
static DEVICE_INFO DeviceInfo(DEVICE_T aDeviceType)
virtual bool HasAutofill() const
void SetParamValue(int aParamIndex, const std::string &aValue, SIM_VALUE::NOTATION aNotation=SIM_VALUE::NOTATION::SI)
const SIM_MODEL_PIN & GetPin(unsigned aIndex) const
void SetIsStoredInValue(bool aIsStoredInValue)
virtual bool HasPrimaryValue() const
const SIM_MODEL::PARAM & GetParam() const
Special netlist exporter flavor that allows one to override simulation commands.
virtual std::string Preview(const SPICE_ITEM &aItem) const
void ClearRows()
wxWidgets recently added an ASSERT which fires if the position is greater than or equal to the number...
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
A wrapper for reporting to a wxString object.
bool HasMessage() const override
Returns true if the reporter client is non-empty.
const wxString & GetMessages() const
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
This file is part of the common library.
static bool empty(const wxTextEntryBase *aCtrl)
bool equivalent(SIM_MODEL::DEVICE_T a, SIM_MODEL::DEVICE_T b)
#define FORCE_UPDATE_PINS
KICOMMON_API wxFont GetInfoFont(wxWindow *aWindow)
BITMAPS PinShapeGetBitmap(GRAPHIC_PINSHAPE aShape)
@ NONE
No connection to this item.
#define SIM_REFERENCE_FIELD
#define SIM_DEVICE_SUBTYPE_FIELD
std::vector< FAB_LAYER_COLOR > dummy
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
std::vector< std::string > enumValues
static constexpr auto NOT_CONNECTED
const std::string modelPinName
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".