42#include <wx/filedlg.h>
43#include <fmt/format.h>
48#include <wx/filedlg.h>
53#define FORCE_REFRESH_FROM_MODEL true
56bool equivalent( SIM_MODEL::DEVICE_T a, SIM_MODEL::DEVICE_T b )
67 std::vector<SCH_FIELD>& aFields ) :
72 m_libraryModelsMgr( &
Prj() ),
73 m_builtinModelsMgr( &
Prj() ),
74 m_prevModel( nullptr ),
76 m_scintillaTricksCode( nullptr ),
77 m_scintillaTricksSubckt( nullptr ),
78 m_firstCategory( nullptr ),
79 m_prevParamGridSelection( nullptr ),
80 m_lastParamGridWidth( 0 )
85 if constexpr (std::is_same_v<T, SCH_SYMBOL>)
99 if( !
pin->GetParentSymbol()->HasAlternateBodyStyle() ||
pin->GetBodyStyle() < 2 )
107 return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0;
120 grid->SetCellDisabledTextColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
124 grid->DedicateKey( WXK_RETURN );
125 grid->DedicateKey( WXK_NUMPAD_ENTER );
126 grid->DedicateKey( WXK_UP );
127 grid->DedicateKey( WXK_DOWN );
129#if wxCHECK_VERSION( 3, 3, 0 )
130 grid->AddActionTrigger( wxPGKeyboardAction::Edit, WXK_RETURN );
131 grid->AddActionTrigger( wxPGKeyboardAction::NextProperty, WXK_RETURN );
132 grid->AddActionTrigger( wxPGKeyboardAction::Edit, WXK_NUMPAD_ENTER );
133 grid->AddActionTrigger( wxPGKeyboardAction::NextProperty, WXK_NUMPAD_ENTER );
135 grid->AddActionTrigger( wxPG_ACTION_EDIT, WXK_RETURN );
136 grid->AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_RETURN );
137 grid->AddActionTrigger( wxPG_ACTION_EDIT, WXK_NUMPAD_ENTER );
138 grid->AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_NUMPAD_ENTER );
154 for( wxPropertyGridIterator it = m_paramGrid->GetIterator(); !it.AtEnd(); ++it )
161 m_pinAssignmentsGrid->PopEventHandler(
true );
163 delete m_scintillaTricksCode;
164 delete m_scintillaTricksSubckt;
171 wxCommandEvent dummyEvent;
174 wxString modelParams;
176 bool storeInValue =
false;
182 &deviceType, &modelType, &modelParams, &pinMap ) )
186 if( !modelType.IsEmpty() )
201 wxFileName tmp( libraryFilename );
203 if( !tmp.GetFullName().IsEmpty() )
206 m_rbLibraryModel->SetValue(
true );
208 if( !loadLibrary( libraryFilename, reporter ) )
213 m_libraryPathText->ChangeValue( libraryFilename );
216 m_libraryModelsMgr.CreateModel(
nullptr, m_sortedPartPins, m_fields,
true, 0, reporter );
218 m_modelListBox->Clear();
219 m_modelListBox->Append(
_(
"<unknown>" ) );
220 m_modelListBox->SetSelection( 0 );
225 int modelIdx = m_modelListBox->FindString( modelName );
227 if( modelIdx == wxNOT_FOUND )
229 m_infoBar->ShowMessage( wxString::Format(
_(
"No model named '%s' in library." ),
233 m_modelListBox->SetSelection( 0 );
238 m_modelListBox->SetSelection( modelIdx );
241 m_curModelType = curModel().GetType();
244 if( isIbisLoaded() && ( m_modelListBox->GetSelection() >= 0 ) )
247 wxString sel = m_modelListBox->GetStringSelection();
249 if( m_modelListBoxEntryToLibraryIdx.contains( sel ) )
250 idx = m_modelListBoxEntryToLibraryIdx.at( sel );
256 onModelNameChoice( dummyEvent );
260 for(
const std::pair<std::string, std::string>& strs : ibismodel->
GetIbisPins() )
266 ibismodel->
ChangePin( *ibisLibrary, strs.first );
267 m_pinCombobox->SetSelection(
static_cast<int>( i ) );
273 if( i <
static_cast<int>( ibismodel->
GetIbisPins().size() ) )
275 onPinCombobox( dummyEvent );
278 m_pinModelCombobox->SetStringSelection( ibisModel );
284 m_differentialCheckbox->SetValue(
true );
289 m_differentialCheckbox->SetValue(
false );
298 m_rbBuiltinModel->SetValue(
true );
307 for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
309 if( m_rbBuiltinModel->GetValue() && type == m_curModelType )
312 m_builtinModelsMgr.CreateModel( m_fields,
true, 0, m_sortedPartPins, reporter );
322 m_builtinModelsMgr.CreateModel( type, m_sortedPartPins, reporter );
327 if( !m_curModelTypeOfDeviceType.count( deviceTypeT ) )
328 m_curModelTypeOfDeviceType[deviceTypeT] = type;
332 curModel().SetIsStoredInValue(
true );
334 m_saveInValueCheckbox->SetValue( curModel().IsStoredInValue() );
336 onRadioButton( dummyEvent );
337 return DIALOG_SIM_MODEL_BASE::TransferDataToWindow();
344 if( !m_pinAssignmentsGrid->CommitPendingChanges() )
347 if( !m_paramGrid->GetGrid()->CommitChangesFromEditor() )
350 if( !DIALOG_SIM_MODEL_BASE::TransferDataFromWindow() )
357 if( m_rbLibraryModel->GetValue() )
359 path = m_libraryPathText->GetValue();
360 wxFileName fn(
path );
363 && !fn.GetFullPath().StartsWith(
".." ) )
365 path = fn.GetFullPath();
368 if( m_modelListBox->GetSelection() >= 0 )
369 name = m_modelListBox->GetStringSelection().ToStdString();
380 wxString sel = m_modelListBox->GetStringSelection();
382 if( m_modelListBoxEntryToLibraryIdx.contains( sel ) )
383 idx = m_modelListBoxEntryToLibraryIdx.at( sel );
386 static_cast<SIM_MODEL_IBIS*
>( &m_libraryModelsMgr.GetModels().at( idx ).get() );
391 std::string modelName = std::string( m_pinModelCombobox->GetValue().c_str() );
392 std::string differential;
394 if( m_pinCombobox->GetSelection() >= 0 )
395 pins = ibismodel->GetIbisPins().at( m_pinCombobox->GetSelection() ).first;
397 if( ibismodel->CanDifferential() && m_differentialCheckbox->GetValue() )
406 if( model.
GetType() == SIM_MODEL::TYPE::RAWSPICE )
408 if( m_modelNotebook->GetSelection() == 0 )
409 updateModelCodeTab( &model );
411 wxString code = m_codePreview->GetText().Trim(
true ).Trim(
false );
412 model.
SetParamValue(
"model", std::string( code.ToUTF8() ) );
417 for(
int row = 0; row < m_pinAssignmentsGrid->GetNumberRows(); ++row )
419 wxString modelPinName = m_pinAssignmentsGrid->GetCellValue( row, PIN_COLUMN::MODEL );
420 wxString symbolPinName = m_sortedPartPins.at( row )->GetShownNumber();
423 std::string( symbolPinName.ToUTF8() ) );
426 removeOrphanedPinAssignments( &model );
428 curModel().WriteFields( m_fields );
439 m_browseButton->Enable();
442 bool undetermined = !m_rbLibraryModel->GetValue() && !m_rbBuiltinModel->GetValue();
443 bool enableLibCtrls = m_rbLibraryModel->GetValue() || undetermined;
444 bool enableBuiltinCtrls = m_rbBuiltinModel->GetValue() || undetermined;
446 m_pathLabel->Enable( enableLibCtrls );
447 m_libraryPathText->Enable( enableLibCtrls );
448 m_modelNameLabel->Enable( enableLibCtrls );
449 m_modelFilter->Enable( enableLibCtrls && !isIbisLoaded() );
450 m_modelListBox->Enable( enableLibCtrls );
451 m_pinLabel->Enable( enableLibCtrls );
452 m_pinCombobox->Enable( enableLibCtrls );
453 m_differentialCheckbox->Enable( enableLibCtrls );
454 m_pinModelLabel->Enable( enableLibCtrls );
455 m_pinModelCombobox->Enable( enableLibCtrls );
456 m_waveformLabel->Enable( enableLibCtrls );
457 m_waveformChoice->Enable( enableLibCtrls );
459 m_deviceLabel->Enable( enableBuiltinCtrls );
460 m_deviceChoice->Enable( enableBuiltinCtrls );
461 m_deviceSubtypeLabel->Enable( enableBuiltinCtrls );
462 m_deviceSubtypeChoice->Enable( enableBuiltinCtrls );
466 updateIbisWidgets( model );
467 updateBuiltinModelWidgets( model );
468 updateModelParamsTab( model );
469 updateModelCodeTab( model );
470 updatePinAssignments( model,
false );
474 m_modelPanel->Layout();
475 m_pinAssignmentsPanel->Layout();
476 m_parametersPanel->Layout();
477 m_codePanel->Layout();
479 SendSizeEvent( wxSEND_EVENT_POST );
481 m_prevModel = &curModel();
490 m_pinLabel->Show( isIbisLoaded() );
491 m_pinCombobox->Show( isIbisLoaded() );
492 m_pinModelLabel->Show( isIbisLoaded() );
493 m_pinModelCombobox->Show( isIbisLoaded() );
494 m_waveformLabel->Show( isIbisLoaded() );
495 m_waveformChoice->Show( isIbisLoaded() );
497 if( aModel != m_prevModel )
499 m_waveformChoice->Clear();
503 for( SIM_MODEL::TYPE type : { SIM_MODEL::TYPE::KIBIS_DEVICE,
504 SIM_MODEL::TYPE::KIBIS_DRIVER_DC,
505 SIM_MODEL::TYPE::KIBIS_DRIVER_RECT,
506 SIM_MODEL::TYPE::KIBIS_DRIVER_PRBS } )
516 if( type == aModel->
GetType() )
517 m_waveformChoice->SetSelection( m_waveformChoice->GetCount() - 1 );
523 m_differentialCheckbox->Show( isIbisLoaded() && modelibis && modelibis->
CanDifferential() );
524 m_modelNameLabel->SetLabel( isIbisLoaded() ?
_(
"Component:" ) :
_(
"Model:" ) );
532 if( aModel != m_prevModel )
534 m_deviceChoice->Clear();
535 m_deviceSubtypeChoice->Clear();
537 if( !m_rbLibraryModel->GetValue() )
539 for( SIM_MODEL::DEVICE_T deviceType : SIM_MODEL::DEVICE_T_ITERATOR() )
547 m_deviceChoice->SetSelection( m_deviceChoice->GetCount() - 1 );
550 for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
552 if( type == SIM_MODEL::TYPE::KIBIS_DEVICE
553 || type == SIM_MODEL::TYPE::KIBIS_DRIVER_DC
554 || type == SIM_MODEL::TYPE::KIBIS_DRIVER_RECT
555 || type == SIM_MODEL::TYPE::KIBIS_DRIVER_PRBS )
568 if( type == aModel->
GetType() )
569 m_deviceSubtypeChoice->SetSelection( m_deviceSubtypeChoice->GetCount() - 1 );
574 m_deviceSubtypeLabel->Show( m_deviceSubtypeChoice->GetCount() > 1 );
575 m_deviceSubtypeChoice->Show( m_deviceSubtypeChoice->GetCount() > 1 );
579 m_modelNotebook->SetSelection( 1 );
581 m_modelNotebook->SetSelection( 0 );
587 m_saveInValueCheckbox->SetLabel( wxString::Format(
_(
"Save parameter '%s (%s)' in Value "
591 m_saveInValueCheckbox->Enable(
true );
595 m_saveInValueCheckbox->SetLabel(
_(
"Save primary parameter in Value field" ) );
596 m_saveInValueCheckbox->SetValue(
false );
597 m_saveInValueCheckbox->Enable(
false );
605 if( aModel != m_prevModel )
610 m_paramGridMgr->SetColumnCount( PARAM_COLUMN::END_ );
612 m_paramGridMgr->SetColumnTitle( PARAM_COLUMN::DESCRIPTION,
_(
"Parameter" ) );
613 m_paramGridMgr->SetColumnTitle( PARAM_COLUMN::UNIT,
_(
"Unit" ) );
614 m_paramGridMgr->SetColumnTitle( PARAM_COLUMN::DEFAULT,
_(
"Default" ) );
615 m_paramGridMgr->SetColumnTitle( PARAM_COLUMN::TYPE,
_(
"Type" ) );
617 m_paramGridMgr->ShowHeader();
620 m_paramGrid->Clear();
622 m_firstCategory = m_paramGrid->Append(
new wxPropertyCategory(
"Geometry" ) );
623 m_paramGrid->HideProperty(
"Geometry" );
625 m_paramGrid->Append(
new wxPropertyCategory(
"AC" ) );
626 m_paramGrid->HideProperty(
"AC" );
628 m_paramGrid->Append(
new wxPropertyCategory(
"DC" ) );
629 m_paramGrid->HideProperty(
"DC" );
631 m_paramGrid->Append(
new wxPropertyCategory(
"S-Parameters" ) );
632 m_paramGrid->HideProperty(
"S-Parameters" );
634 m_paramGrid->Append(
new wxPropertyCategory(
"Capacitance" ) );
635 m_paramGrid->HideProperty(
"Capacitance" );
637 m_paramGrid->Append(
new wxPropertyCategory(
"Temperature" ) );
638 m_paramGrid->HideProperty(
"Temperature" );
640 m_paramGrid->Append(
new wxPropertyCategory(
"Noise" ) );
641 m_paramGrid->HideProperty(
"Noise" );
643 m_paramGrid->Append(
new wxPropertyCategory(
"Distributed Quantities" ) );
644 m_paramGrid->HideProperty(
"Distributed Quantities" );
646 m_paramGrid->Append(
new wxPropertyCategory(
"Waveform" ) );
647 m_paramGrid->HideProperty(
"Waveform" );
649 m_paramGrid->Append(
new wxPropertyCategory(
"Limiting Values" ) );
650 m_paramGrid->HideProperty(
"Limiting Values" );
652 m_paramGrid->Append(
new wxPropertyCategory(
"Advanced" ) );
653 m_paramGrid->HideProperty(
"Advanced" );
655 m_paramGrid->Append(
new wxPropertyCategory(
"Flags" ) );
656 m_paramGrid->HideProperty(
"Flags" );
658 m_paramGrid->CollapseAll();
661 addParamPropertyIfRelevant( aModel, i );
663 m_paramGrid->CollapseAll();
664 m_paramGrid->Expand(
"AC" );
665 m_paramGrid->Expand(
"Waveform" );
668 adjustParamGridColumns( m_paramGrid->GetGrid()->GetSize().GetX(),
true );
672 for( wxPropertyGridIterator it = m_paramGrid->GetIterator(); !it.AtEnd(); ++it )
674 wxColour bgCol = m_paramGrid->GetGrid()->GetPropertyDefaultCell().GetBgCol();
675 wxColour fgCol = m_paramGrid->GetGrid()->GetPropertyDefaultCell().GetFgCol();
677 for(
int col = 0; col < m_paramGridMgr->GetColumnCount(); ++col )
679 ( *it )->GetCell( col ).SetBgCol( bgCol );
680 ( *it )->GetCell( col ).SetFgCol( fgCol );
694 ( *it )->SetValueFromString( param.
value );
708 item.
modelName = m_modelListBox->GetStringSelection();
710 if( m_rbBuiltinModel->GetValue() || item.
modelName ==
"" )
715 m_codePreview->SetText(
text );
716 m_codePreview->SelectNone();
723 if( m_pinAssignmentsGrid->GetNumberRows() == 0 )
725 m_pinAssignmentsGrid->AppendRows( (
int) m_sortedPartPins.size() );
727 for(
int ii = 0; ii < m_pinAssignmentsGrid->GetNumberRows(); ++ii )
729 wxString symbolPinString = getSymbolPinString( ii );
731 m_pinAssignmentsGrid->SetReadOnly( ii, PIN_COLUMN::SYMBOL );
732 m_pinAssignmentsGrid->SetCellValue( ii, PIN_COLUMN::SYMBOL, symbolPinString );
735 aForceRefreshFromModel =
true;
738 if( aForceRefreshFromModel )
741 for(
int row = 0; row < m_pinAssignmentsGrid->GetNumberRows(); ++row )
742 m_pinAssignmentsGrid->SetCellValue( row, PIN_COLUMN::MODEL,
_(
"Not Connected" ) );
745 for(
int modelPinIndex = 0; modelPinIndex < aModel->
GetPinCount(); ++modelPinIndex )
749 if( symbolPinNumber ==
"" )
752 int symbolPinRow = findSymbolPinRow( symbolPinNumber );
754 if( symbolPinRow == -1 )
757 wxString modelPinString = getModelPinString( aModel, modelPinIndex );
758 m_pinAssignmentsGrid->SetCellValue( symbolPinRow, PIN_COLUMN::MODEL, modelPinString );
762 for(
int ii = 0; ii < m_pinAssignmentsGrid->GetNumberRows(); ++ii )
765 std::vector<BITMAPS> modelPinIcons;
766 wxArrayString modelPinChoices;
768 for(
int jj = 0; jj < aModel->
GetPinCount(); ++jj )
775 modelPinChoices.Add( getModelPinString( aModel, jj ) );
779 modelPinChoices.Add(
_(
"Not Connected" ) );
782 m_pinAssignmentsGrid->SetCellEditor( ii, PIN_COLUMN::MODEL,
786 int modelPinIndex = getModelPinIndex( m_pinAssignmentsGrid->GetCellValue( ii, PIN_COLUMN::MODEL ) );
788 if( modelPinIndex >= 0 )
789 m_pinAssignmentsGrid->SetCellValue( ii, PIN_COLUMN::MODEL, getModelPinString( aModel, modelPinIndex ) );
794 if( aModel->
GetType() == SIM_MODEL::TYPE::SUBCKT )
798 m_subckt->SetEditable(
false );
802 m_subcktLabel->Show(
false );
803 m_subckt->Show(
false );
822 if( m_prevLibrary == aLibraryPath && !aForceReload )
825 m_libraryModelsMgr.SetForceFullParse();
826 m_libraryModelsMgr.SetLibrary( aLibraryPath, aReporter );
827 m_libraryPathText->ChangeValue( aLibraryPath );
828 m_modelListBoxEntryToLibraryIdx.clear();
832 if( m_libraryModelsMgr.GetModels().empty() )
834 if( m_modelListBox->GetSelection() != wxNOT_FOUND )
835 m_modelListBox->SetSelection( wxNOT_FOUND );
837 if( m_modelListBox->GetCount() )
838 m_modelListBox->Clear();
846 for(
const auto& [baseModelName, baseModel] :
library()->GetModels() )
848 if( baseModelName == modelName )
849 m_libraryModelsMgr.CreateModel( &baseModel, m_sortedPartPins, m_fields,
true, 0, aReporter );
851 m_libraryModelsMgr.CreateModel( &baseModel, m_sortedPartPins, aReporter );
854 m_rbLibraryModel->SetValue(
true );
856 wxArrayString modelNames;
858 bool modelNameExists =
false;
859 for(
const auto& [
name, model] :
library()->GetModels() )
861 modelNames.Add(
name );
862 m_modelListBoxEntryToLibraryIdx[
name] = m_modelListBoxEntryToLibraryIdx.size();
864 if(
name == modelName )
865 modelNameExists =
true;
870 m_modelListBox->Clear();
871 m_modelListBox->Append( modelNames );
873 if( !modelNameExists )
875 m_infoBar->ShowMessage( wxString::Format(
_(
"No model named '%s' in '%s'." ),
883 wxArrayString emptyArray;
884 m_pinModelCombobox->Set( emptyArray );
885 m_pinCombobox->Set( emptyArray );
886 m_pinModelCombobox->SetSelection( -1 );
887 m_pinCombobox->SetSelection( -1 );
890 m_modelListBox->SetStringSelection( modelName );
892 if( m_modelListBox->GetSelection() < 0 && m_modelListBox->GetCount() > 0 )
893 m_modelListBox->SetSelection( 0 );
895 m_curModelType = curModel().GetType();
897 m_prevLibrary = aLibraryPath;
911 m_paramGrid->HideProperty(
"AC",
false );
912 m_paramGrid->AppendIn(
"AC", newParamProperty( aModel, aParamIndex ) );
916 m_paramGrid->HideProperty(
"DC",
false );
917 m_paramGrid->AppendIn(
"DC", newParamProperty( aModel, aParamIndex ) );
920 case CATEGORY::S_PARAM:
921 m_paramGrid->HideProperty(
"S-Parameters",
false );
922 m_paramGrid->AppendIn(
"S-Parameters", newParamProperty( aModel, aParamIndex ) );
925 case CATEGORY::CAPACITANCE:
926 m_paramGrid->HideProperty(
"Capacitance",
false );
927 m_paramGrid->AppendIn(
"Capacitance", newParamProperty( aModel, aParamIndex ) );
930 case CATEGORY::TEMPERATURE:
931 m_paramGrid->HideProperty(
"Temperature",
false );
932 m_paramGrid->AppendIn(
"Temperature", newParamProperty( aModel, aParamIndex ) );
935 case CATEGORY::NOISE:
936 m_paramGrid->HideProperty(
"Noise",
false );
937 m_paramGrid->AppendIn(
"Noise", newParamProperty( aModel, aParamIndex ) );
940 case CATEGORY::DISTRIBUTED_QUANTITIES:
941 m_paramGrid->HideProperty(
"Distributed Quantities",
false );
942 m_paramGrid->AppendIn(
"Distributed Quantities", newParamProperty( aModel, aParamIndex ) );
945 case CATEGORY::WAVEFORM:
946 m_paramGrid->HideProperty(
"Waveform",
false );
947 m_paramGrid->AppendIn(
"Waveform", newParamProperty( aModel, aParamIndex ) );
950 case CATEGORY::GEOMETRY:
951 m_paramGrid->HideProperty(
"Geometry",
false );
952 m_paramGrid->AppendIn(
"Geometry", newParamProperty( aModel, aParamIndex ) );
955 case CATEGORY::LIMITING_VALUES:
956 m_paramGrid->HideProperty(
"Limiting Values",
false );
957 m_paramGrid->AppendIn(
"Limiting Values", newParamProperty( aModel, aParamIndex ) );
960 case CATEGORY::ADVANCED:
961 m_paramGrid->HideProperty(
"Advanced",
false );
962 m_paramGrid->AppendIn(
"Advanced", newParamProperty( aModel, aParamIndex ) );
965 case CATEGORY::FLAGS:
966 m_paramGrid->HideProperty(
"Flags",
false );
967 m_paramGrid->AppendIn(
"Flags", newParamProperty( aModel, aParamIndex ) );
971 m_paramGrid->Insert( m_firstCategory, newParamProperty( aModel, aParamIndex ) );
974 case CATEGORY::INITIAL_CONDITIONS:
975 case CATEGORY::SUPERFLUOUS:
985 wxString paramDescription;
988 paramDescription = wxString::Format(
"%s", param.
info.
name );
992 wxPGProperty* prop =
nullptr;
999 prop->SetAttribute( wxPG_BOOL_USE_CHECKBOX,
true );
1021 wxArrayString inductors;
1032 if( item.model->GetDeviceType() == SIM_MODEL::DEVICE_T::L )
1033 inductors.push_back( item.refName );
1037 [](
const wxString& a,
const wxString& b ) ->
int
1043 if( inductors.empty() )
1061 wxArrayString values;
1064 values.Add(
string );
1072 prop =
new wxStringProperty( paramDescription, param.
info.
name );
1076 prop->SetAttribute( wxPG_ATTR_UNITS, wxString::FromUTF8( param.
info.
unit.c_str() ) );
1096 prop->SetCell( PARAM_COLUMN::TYPE, typeStr );
1102template <
typename T>
1105 for(
int row = 0; row < static_cast<int>( m_sortedPartPins.size() ); ++row )
1109 if(
pin->GetNumber() == aSymbolPinNumber )
1117template <
typename T>
1120 if( m_rbLibraryModel->GetValue() )
1122 wxString sel = m_modelListBox->GetStringSelection();
1124 if( m_modelListBoxEntryToLibraryIdx.contains( sel ) )
1125 return m_libraryModelsMgr.GetModels().at( m_modelListBoxEntryToLibraryIdx.at( sel ) ).get();
1129 if( (
int) m_curModelType < (
int) m_builtinModelsMgr.GetModels().size() )
1130 return m_builtinModelsMgr.GetModels().at(
static_cast<int>( m_curModelType ) );
1133 return m_builtinModelsMgr.GetModels().at( (
int) SIM_MODEL::TYPE::NONE );
1137template <
typename T>
1140 if( m_libraryModelsMgr.GetLibraries().size() == 1 )
1141 return &m_libraryModelsMgr.GetLibraries().begin()->second.get();
1147template <
typename T>
1150 SCH_PIN*
pin = m_sortedPartPins.at( symbolPinIndex );
1156 pinNumber =
pin->GetShownNumber();
1157 pinName =
pin->GetShownName();
1160 if( !pinName.IsEmpty() && pinName != pinNumber )
1161 pinNumber += wxString::Format( wxT(
" (\"%s\")" ), pinName );
1167template <
typename T>
1170 wxString modelPinName;
1172 if( aModelPinIndex >= 0 && aModelPinIndex < aModel->GetPinCount() )
1175 wxString modelPinNumber = wxString::Format(
"%d", aModelPinIndex + 1 );
1177 if( !modelPinName.IsEmpty() && modelPinName != modelPinNumber )
1178 modelPinNumber += wxString::Format( wxT(
" (\"%s\")" ), modelPinName );
1180 return modelPinNumber;
1184template <
typename T>
1187 if( aModelPinString ==
"Not Connected" )
1190 int length = aModelPinString.Find(
" " );
1192 if( length == wxNOT_FOUND )
1193 length =
static_cast<int>( aModelPinString.Length() );
1196 aModelPinString.Mid( 0, length ).ToCLong( &result );
1198 return static_cast<int>( result - 1 );
1202template <
typename T>
1205 m_prevModel =
nullptr;
1210template <
typename T>
1213 m_rbLibraryModel->SetValue(
true );
1217template <
typename T>
1220 m_rbLibraryModel->SetValue(
true );
1223 wxString
path = m_libraryPathText->GetValue();
1225 if( loadLibrary(
path, reporter,
true ) ||
path.IsEmpty() )
1234template <
typename T>
1244 wxCommandEvent
dummy;
1245 onLibraryPathTextEnter(
dummy );
1252template <
typename T>
1255 static wxString s_mruPath;
1258 wxFileDialog dlg(
this,
_(
"Browse Models" ),
path );
1261 dlg.SetCustomizeHook( customize );
1263 if( dlg.ShowModal() == wxID_CANCEL )
1266 m_rbLibraryModel->SetValue(
true );
1268 path = dlg.GetPath();
1269 wxFileName fn(
path );
1270 s_mruPath = fn.GetPath();
1277 else if( fn.MakeRelativeTo(
Prj().GetProjectPath() ) && !fn.GetFullPath().StartsWith( wxS(
".." ) ) )
1279 path = fn.GetFullPath();
1284 if( loadLibrary(
path, reporter,
true ) )
1293template <
typename T>
1296 int sel = m_modelListBox->GetSelection();
1298 switch( aKeyStroke.GetKeyCode() )
1301 if( sel == wxNOT_FOUND )
1302 sel = m_modelListBox->GetCount() - 1;
1309 if( sel == wxNOT_FOUND )
1317 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
1325 if( sel >= 0 && sel < (
int) m_modelListBox->GetCount() )
1326 m_modelListBox->SetSelection( sel );
1330template <
typename T>
1336 wxArrayString modelNames;
1337 wxString current = m_modelListBox->GetStringSelection();
1338 wxString
filter = wxT(
"*" ) + m_modelFilter->GetValue() + wxT(
"*" );
1340 for(
const auto& [
name, model] :
library()->GetModels() )
1342 wxString wx_name(
name );
1344 if( wx_name.Matches(
filter ) )
1345 modelNames.Add( wx_name );
1350 m_modelListBox->Clear();
1351 m_modelListBox->Append( modelNames );
1353 if( !m_modelListBox->IsEmpty() )
1355 if( !m_modelListBox->SetStringSelection( current ) )
1356 m_modelListBox->SetSelection( 0 );
1361template <
typename T>
1364 if( isIbisLoaded() )
1366 wxArrayString pinLabels;
1369 wxCHECK2( modelkibis,
return );
1371 for( std::pair<wxString, wxString> strs : modelkibis->
GetIbisPins() )
1372 pinLabels.Add( strs.first + wxT(
" - " ) + strs.second );
1374 m_pinCombobox->Set( pinLabels );
1376 wxArrayString emptyArray;
1377 m_pinModelCombobox->Set( emptyArray );
1380 m_rbLibraryModel->SetValue(
true );
1385 wxArrayString lines = wxSplit( fallback->GetSpiceCode(),
'\n' );
1388 for(
const wxString& line : lines )
1390 if( !line.StartsWith(
'*' ) )
1392 if( !code.IsEmpty() )
1399 m_infoBar->ShowMessage( wxString::Format(
_(
"Failed to parse:\n\n"
1401 "Using generic SPICE model." ),
1413template <
typename T>
1416 wxArrayString modelLabels;
1420 std::vector<std::pair<std::string, std::string>> strs = ibisModel.
GetIbisPins();
1421 std::string pinNumber = strs.at( m_pinCombobox->GetSelection() ).first;
1425 ibisModel.
ChangePin( *ibisLibrary, pinNumber );
1430 modelLabels.Add( modelName );
1432 m_pinModelCombobox->Set( modelLabels );
1434 if( m_pinModelCombobox->GetCount() == 1 )
1435 m_pinModelCombobox->SetSelection( 0 );
1437 m_pinModelCombobox->SetSelection( -1 );
1443template <
typename T>
1446 m_pinCombobox->SetSelection( m_pinCombobox->FindString( m_pinCombobox->GetValue() ) );
1448 onPinModelCombobox( aEvent );
1452template <
typename T>
1459template <
typename T>
1462 m_pinModelCombobox->SetSelection( m_pinModelCombobox->FindString( m_pinModelCombobox->GetValue() ) );
1466template <
typename T>
1471 bool diff = m_differentialCheckbox->GetValue() && modelibis->CanDifferential();
1472 modelibis->SwitchSingleEndedDiff( diff );
1479template <
typename T>
1482 m_rbBuiltinModel->SetValue(
true );
1484 for( SIM_MODEL::DEVICE_T deviceType : SIM_MODEL::DEVICE_T_ITERATOR() )
1488 m_curModelType = m_curModelTypeOfDeviceType.at( deviceType );
1497template <
typename T>
1500 SIM_MODEL::DEVICE_T deviceType = curModel().GetDeviceType();
1501 wxString typeDescription = m_waveformChoice->GetStringSelection();
1503 for( SIM_MODEL::TYPE type : { SIM_MODEL::TYPE::KIBIS_DEVICE,
1504 SIM_MODEL::TYPE::KIBIS_DRIVER_DC,
1505 SIM_MODEL::TYPE::KIBIS_DRIVER_RECT,
1506 SIM_MODEL::TYPE::KIBIS_DRIVER_PRBS } )
1512 wxString sel = m_modelListBox->GetStringSelection();
1514 if( m_modelListBoxEntryToLibraryIdx.contains( sel ) )
1515 idx = m_modelListBoxEntryToLibraryIdx.at( sel );
1519 m_libraryModelsMgr.SetModel( idx, std::make_unique<SIM_MODEL_IBIS>( type, baseModel ) );
1523 m_libraryModelsMgr.GetModels()[idx].get().
ReadDataFields( &m_fields,
true, 0, m_sortedPartPins );
1530 m_curModelType = type;
1535 m_curModelTypeOfDeviceType.at( deviceType ) = m_curModelType;
1540template <
typename T>
1543 SIM_MODEL::DEVICE_T deviceType = curModel().GetDeviceType();
1544 wxString typeDescription = m_deviceSubtypeChoice->GetStringSelection();
1546 for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
1551 m_curModelType = type;
1556 m_curModelTypeOfDeviceType.at( deviceType ) = m_curModelType;
1561template <
typename T>
1564 updateModelCodeTab( &curModel() );
1568template <
typename T>
1571 int symbolPinIndex = aEvent.GetRow();
1572 wxString oldModelPinName = aEvent.GetString();
1573 wxString modelPinName = m_pinAssignmentsGrid->GetCellValue( aEvent.GetRow(), aEvent.GetCol() );
1575 int oldModelPinIndex = getModelPinIndex( oldModelPinName );
1576 int modelPinIndex = getModelPinIndex( modelPinName );
1579 curModel().AssignSymbolPinNumberToModelPin( oldModelPinIndex,
"" );
1583 SCH_PIN* symbolPin = m_sortedPartPins.at( symbolPinIndex );
1585 curModel().AssignSymbolPinNumberToModelPin( modelPinIndex, symbolPin->
GetShownNumber() );
1594template <
typename T>
1597 wxGridUpdateLocker deferRepaintsTillLeavingScope( m_pinAssignmentsGrid );
1600 m_pinAssignmentsGrid->SetColSize( PIN_COLUMN::MODEL, gridWidth / 2 );
1601 m_pinAssignmentsGrid->SetColSize( PIN_COLUMN::SYMBOL, gridWidth / 2 );
1607template <
typename T>
1613 wxPropertyGrid*
grid = m_paramGrid->GetGrid();
1614 wxPGProperty* selected =
grid->GetSelection();
1617 selected =
grid->wxPropertyGridInterface::GetFirst();
1619#if wxCHECK_VERSION( 3, 3, 0 )
1621 grid->DoSelectProperty( selected, wxPGSelectPropertyFlags::Focus );
1624 grid->DoSelectProperty( selected, wxPG_SEL_FOCUS );
1631template <
typename T>
1634 wxPropertyGrid*
grid = m_paramGrid->GetGrid();
1637 if(
grid->GetSelection() &&
grid->GetSelection()->IsCategory() )
1639 wxPGProperty* selection =
grid->GetSelection();
1644 wxPropertyGridIterator it =
grid->GetIterator( wxPG_ITERATE_VISIBLE, selection );
1647 wxKeyEvent* keyEvent =
new wxKeyEvent( wxEVT_KEY_DOWN );
1649 if( *it == m_prevParamGridSelection )
1651 if( !selection->IsExpanded() )
1653 grid->Expand( selection );
1654 keyEvent->m_keyCode = WXK_DOWN;
1655 wxQueueEvent(
grid, keyEvent );
1663 keyEvent->m_keyCode = WXK_UP;
1664 wxQueueEvent(
grid, keyEvent );
1669 if( !selection->IsExpanded() )
1670 grid->Expand( selection );
1672 keyEvent->m_keyCode = WXK_DOWN;
1673 wxQueueEvent(
grid, keyEvent );
1676 m_prevParamGridSelection =
grid->GetSelection();
1680 wxWindow* editorControl =
grid->GetEditorControl();
1682 if( !editorControl )
1684 m_prevParamGridSelection =
grid->GetSelection();
1689 editorControl->SetFocus();
1690 m_prevParamGridSelection =
grid->GetSelection();
1694template <
typename T>
1705 wxPropertyGrid*
grid = m_paramGrid->GetGrid();
1706 wxTextCtrl* ctrl =
grid->GetEditorTextCtrl();
1710 wxRect ctrlRect = ctrl->GetScreenRect();
1711 wxRect gridRect =
grid->GetScreenRect();
1713 if( ctrlRect.GetTop() < gridRect.GetTop() || ctrlRect.GetBottom() > gridRect.GetBottom() )
1714 grid->ClearSelection();
1720template <
typename T>
1723 wxPropertyGrid*
grid = m_paramGridMgr->GetGrid();
1727 if( aWidth != m_lastParamGridWidth || aForce )
1729 m_lastParamGridWidth = aWidth;
1733 std::vector<int> colWidths;
1735 for(
size_t ii = 0; ii <
grid->GetColumnCount(); ii++ )
1737 if( ii == PARAM_COLUMN::DESCRIPTION )
1738 colWidths.push_back(
grid->GetState()->GetColumnWidth( ii ) + margin + indent );
1739 else if( ii == PARAM_COLUMN::VALUE )
1740 colWidths.push_back( std::max( 72,
grid->GetState()->GetColumnWidth( ii ) ) + margin );
1742 colWidths.push_back( 60 + margin );
1744 aWidth -= colWidths[ ii ];
1747 for(
size_t ii = 0; ii <
grid->GetColumnCount(); ii++ )
1748 grid->SetColumnProportion( ii, colWidths[ ii ] );
1750 grid->ResetColumnSizes();
1751 grid->RefreshEditor();
1756template <
typename T>
1759 adjustParamGridColumns( event.GetSize().GetX(),
false );
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
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)
SIM_LIB_MGR m_builtinModelsMgr
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
SIM_LIB_MGR m_libraryModelsMgr
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
std::vector< EMBEDDED_FILES * > m_filesStack
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()
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.
EMBEDDED_FILES * GetEmbeddedFiles() override
Schematic editor (Eeschema) main window.
void SetText(const wxString &aText) override
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
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
void SetFilesStack(std::vector< EMBEDDED_FILES * > aFilesStack)
std::vector< std::pair< std::string, std::string > > GetIbisPins() const
void SwitchSingleEndedDiff(bool aDiff) override
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 INFO TypeInfo(TYPE aType)
void ReadDataFields(const std::vector< SCH_FIELD > *aFields, bool aResolve, int aDepth, const std::vector< SCH_PIN * > &aPins)
static bool InferSimModel(T &aSymbol, std::vector< SCH_FIELD > *aFields, bool aResolve, int aDepth, SIM_VALUE_GRAMMAR::NOTATION aNotation, wxString *aDeviceType, wxString *aModelType, wxString *aModelParams, wxString *aPinMap)
const SPICE_GENERATOR & SpiceGenerator() const
virtual const PARAM & GetParam(unsigned aParamIndex) const
static TYPE ReadTypeFromFields(const std::vector< SCH_FIELD > &aFields, bool aResolve, int aDepth, REPORTER &aReporter)
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_REFRESH_FROM_MODEL
static const std::string KiCadUriPrefix
KICOMMON_API wxFont GetStatusFont(wxWindow *aWindow)
BITMAPS PinShapeGetBitmap(GRAPHIC_PINSHAPE shape)
wxString GetFieldValue(const std::vector< SCH_FIELD > *aFields, FIELD_T aFieldType)
const SCH_FIELD * FindField(const std::vector< SCH_FIELD > &aFields, FIELD_T aFieldId)
void SetFieldValue(std::vector< SCH_FIELD > &aFields, const wxString &aFieldName, const std::string &aValue, bool aIsVisible=true)
#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
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".