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 ) )
256 int idx = m_modelListBox->GetSelection();
257 auto ibismodel =
dynamic_cast<SIM_MODEL_IBIS*
>( &m_libraryModelsMgr.GetModels()[idx].get() );
261 onModelNameChoice( dummyEvent );
265 for(
const std::pair<std::string, std::string>& strs : ibismodel->GetIbisPins() )
271 ibismodel->ChangePin( *ibisLibrary, strs.first );
272 m_pinCombobox->SetSelection(
static_cast<int>( i ) );
278 if( i <
static_cast<int>( ibismodel->GetIbisPins().size() ) )
280 onPinCombobox( dummyEvent );
282 m_pinModelCombobox->SetStringSelection(
288 ibismodel->SwitchSingleEndedDiff(
true );
289 m_differentialCheckbox->SetValue(
true );
293 ibismodel->SwitchSingleEndedDiff(
false );
294 m_differentialCheckbox->SetValue(
false );
303 m_rbBuiltinModel->SetValue(
true );
312 for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
314 if( m_rbBuiltinModel->GetValue() && type == m_curModelType )
317 m_builtinModelsMgr.CreateModel( m_fields, m_sortedPartPins,
false, reporter );
327 m_builtinModelsMgr.CreateModel( type, m_sortedPartPins, reporter );
332 if( !m_curModelTypeOfDeviceType.count( deviceTypeT ) )
333 m_curModelTypeOfDeviceType[deviceTypeT] = type;
337 curModel().SetIsStoredInValue(
true );
339 m_saveInValueCheckbox->SetValue( curModel().IsStoredInValue() );
341 onRadioButton( dummyEvent );
342 return DIALOG_SIM_MODEL_BASE::TransferDataToWindow();
349 m_pinAssignmentsGrid->CommitPendingChanges();
350 m_paramGrid->GetGrid()->CommitChangesFromEditor();
352 if( !DIALOG_SIM_MODEL_BASE::TransferDataFromWindow() )
359 if( m_rbLibraryModel->GetValue() )
361 path = m_libraryPathText->GetValue();
362 wxFileName fn(
path );
364 if( fn.MakeRelativeTo(
Prj().GetProjectPath() ) && !fn.GetFullPath().StartsWith(
".." ) )
365 path = fn.GetFullPath();
367 if( m_modelListBox->GetSelection() >= 0 )
368 name = m_modelListBox->GetStringSelection().ToStdString();
379 &m_libraryModelsMgr.GetModels().at( m_modelListBox->GetSelection() ).get() );
384 std::string modelName = std::string( m_pinModelCombobox->GetValue().c_str() );
385 std::string differential;
387 if( m_pinCombobox->GetSelection() >= 0 )
388 pins = ibismodel->
GetIbisPins().at( m_pinCombobox->GetSelection() ).first;
390 if( ibismodel->
CanDifferential() && m_differentialCheckbox->GetValue() )
399 if( model.
GetType() == SIM_MODEL::TYPE::RAWSPICE )
401 if( m_modelNotebook->GetSelection() == 0 )
402 updateModelCodeTab( &model );
404 wxString code = m_codePreview->GetText().Trim(
true ).Trim(
false );
405 model.
SetParamValue(
"model", std::string( code.ToUTF8() ) );
410 for(
int row = 0; row < m_pinAssignmentsGrid->GetNumberRows(); ++row )
412 wxString modelPinName = m_pinAssignmentsGrid->GetCellValue( row, PIN_COLUMN::MODEL );
413 wxString symbolPinName = m_sortedPartPins.at( row )->GetShownNumber();
416 std::string( symbolPinName.ToUTF8() ) );
419 removeOrphanedPinAssignments( &model );
421 curModel().WriteFields( m_fields );
432 m_browseButton->Enable();
435 bool undetermined = !m_rbLibraryModel->GetValue() && !m_rbBuiltinModel->GetValue();
436 bool enableLibCtrls = m_rbLibraryModel->GetValue() || undetermined;
437 bool enableBuiltinCtrls = m_rbBuiltinModel->GetValue() || undetermined;
439 m_pathLabel->Enable( enableLibCtrls );
440 m_libraryPathText->Enable( enableLibCtrls );
441 m_modelNameLabel->Enable( enableLibCtrls );
442 m_modelFilter->Enable( enableLibCtrls && !isIbisLoaded() );
443 m_modelListBox->Enable( enableLibCtrls );
444 m_pinLabel->Enable( enableLibCtrls );
445 m_pinCombobox->Enable( enableLibCtrls );
446 m_differentialCheckbox->Enable( enableLibCtrls );
447 m_pinModelLabel->Enable( enableLibCtrls );
448 m_pinModelCombobox->Enable( enableLibCtrls );
449 m_waveformLabel->Enable( enableLibCtrls );
450 m_waveformChoice->Enable( enableLibCtrls );
452 m_deviceLabel->Enable( enableBuiltinCtrls );
453 m_deviceChoice->Enable( enableBuiltinCtrls );
454 m_deviceSubtypeLabel->Enable( enableBuiltinCtrls );
455 m_deviceSubtypeChoice->Enable( enableBuiltinCtrls );
459 updateIbisWidgets( model );
460 updateBuiltinModelWidgets( model );
461 updateModelParamsTab( model );
462 updateModelCodeTab( model );
463 updatePinAssignments( model,
false );
467 m_modelPanel->Layout();
468 m_pinAssignmentsPanel->Layout();
469 m_parametersPanel->Layout();
470 m_codePanel->Layout();
472 SendSizeEvent( wxSEND_EVENT_POST );
474 m_prevModel = &curModel();
484 m_pinLabel->Show( isIbisLoaded() );
485 m_pinCombobox->Show( isIbisLoaded() );
486 m_pinModelLabel->Show( isIbisLoaded() );
487 m_pinModelCombobox->Show( isIbisLoaded() );
488 m_waveformLabel->Show( isIbisLoaded() );
489 m_waveformChoice->Show( isIbisLoaded() );
491 if( aModel != m_prevModel )
493 m_waveformChoice->Clear();
497 for( SIM_MODEL::TYPE type : { SIM_MODEL::TYPE::KIBIS_DEVICE,
498 SIM_MODEL::TYPE::KIBIS_DRIVER_DC,
499 SIM_MODEL::TYPE::KIBIS_DRIVER_RECT,
500 SIM_MODEL::TYPE::KIBIS_DRIVER_PRBS } )
510 if( type == aModel->
GetType() )
511 m_waveformChoice->SetSelection( m_waveformChoice->GetCount() - 1 );
517 m_differentialCheckbox->Show( isIbisLoaded() && modelibis && modelibis->
CanDifferential() );
518 m_modelNameLabel->SetLabel( isIbisLoaded() ?
_(
"Component:" ) :
_(
"Model:" ) );
526 if( aModel != m_prevModel )
528 m_deviceChoice->Clear();
529 m_deviceSubtypeChoice->Clear();
531 if( !m_rbLibraryModel->GetValue() )
533 for( SIM_MODEL::DEVICE_T deviceType : SIM_MODEL::DEVICE_T_ITERATOR() )
541 m_deviceChoice->SetSelection( m_deviceChoice->GetCount() - 1 );
544 for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
546 if( type == SIM_MODEL::TYPE::KIBIS_DEVICE
547 || type == SIM_MODEL::TYPE::KIBIS_DRIVER_DC
548 || type == SIM_MODEL::TYPE::KIBIS_DRIVER_RECT
549 || type == SIM_MODEL::TYPE::KIBIS_DRIVER_PRBS )
562 if( type == aModel->
GetType() )
563 m_deviceSubtypeChoice->SetSelection( m_deviceSubtypeChoice->GetCount() - 1 );
568 m_deviceSubtypeLabel->Show( m_deviceSubtypeChoice->GetCount() > 1 );
569 m_deviceSubtypeChoice->Show( m_deviceSubtypeChoice->GetCount() > 1 );
573 m_modelNotebook->SetSelection( 1 );
575 m_modelNotebook->SetSelection( 0 );
581 m_saveInValueCheckbox->SetLabel( wxString::Format(
_(
"Save parameter '%s (%s)' in Value "
585 m_saveInValueCheckbox->Enable(
true );
589 m_saveInValueCheckbox->SetLabel(
_(
"Save primary parameter in Value field" ) );
590 m_saveInValueCheckbox->SetValue(
false );
591 m_saveInValueCheckbox->Enable(
false );
599 if( aModel != m_prevModel )
604 m_paramGridMgr->SetColumnCount( PARAM_COLUMN::END_ );
606 m_paramGridMgr->SetColumnTitle( PARAM_COLUMN::DESCRIPTION,
_(
"Parameter" ) );
607 m_paramGridMgr->SetColumnTitle( PARAM_COLUMN::UNIT,
_(
"Unit" ) );
608 m_paramGridMgr->SetColumnTitle( PARAM_COLUMN::DEFAULT,
_(
"Default" ) );
609 m_paramGridMgr->SetColumnTitle( PARAM_COLUMN::TYPE,
_(
"Type" ) );
611 m_paramGridMgr->ShowHeader();
614 m_paramGrid->Clear();
616 m_firstCategory = m_paramGrid->Append(
new wxPropertyCategory(
"Geometry" ) );
617 m_paramGrid->HideProperty(
"Geometry" );
619 m_paramGrid->Append(
new wxPropertyCategory(
"AC" ) );
620 m_paramGrid->HideProperty(
"AC" );
622 m_paramGrid->Append(
new wxPropertyCategory(
"DC" ) );
623 m_paramGrid->HideProperty(
"DC" );
625 m_paramGrid->Append(
new wxPropertyCategory(
"S-Parameters" ) );
626 m_paramGrid->HideProperty(
"S-Parameters" );
628 m_paramGrid->Append(
new wxPropertyCategory(
"Capacitance" ) );
629 m_paramGrid->HideProperty(
"Capacitance" );
631 m_paramGrid->Append(
new wxPropertyCategory(
"Temperature" ) );
632 m_paramGrid->HideProperty(
"Temperature" );
634 m_paramGrid->Append(
new wxPropertyCategory(
"Noise" ) );
635 m_paramGrid->HideProperty(
"Noise" );
637 m_paramGrid->Append(
new wxPropertyCategory(
"Distributed Quantities" ) );
638 m_paramGrid->HideProperty(
"Distributed Quantities" );
640 m_paramGrid->Append(
new wxPropertyCategory(
"Waveform" ) );
641 m_paramGrid->HideProperty(
"Waveform" );
643 m_paramGrid->Append(
new wxPropertyCategory(
"Limiting Values" ) );
644 m_paramGrid->HideProperty(
"Limiting Values" );
646 m_paramGrid->Append(
new wxPropertyCategory(
"Advanced" ) );
647 m_paramGrid->HideProperty(
"Advanced" );
649 m_paramGrid->Append(
new wxPropertyCategory(
"Flags" ) );
650 m_paramGrid->HideProperty(
"Flags" );
652 m_paramGrid->CollapseAll();
655 addParamPropertyIfRelevant( aModel, i );
657 m_paramGrid->CollapseAll();
658 m_paramGrid->Expand(
"AC" );
659 m_paramGrid->Expand(
"Waveform" );
662 adjustParamGridColumns( m_paramGrid->GetGrid()->GetSize().GetX(),
true );
666 for( wxPropertyGridIterator it = m_paramGrid->GetIterator(); !it.AtEnd(); ++it )
668 wxColour bgCol = m_paramGrid->GetGrid()->GetPropertyDefaultCell().GetBgCol();
669 wxColour fgCol = m_paramGrid->GetGrid()->GetPropertyDefaultCell().GetFgCol();
671 for(
int col = 0; col < m_paramGridMgr->GetColumnCount(); ++col )
673 ( *it )->GetCell( col ).SetBgCol( bgCol );
674 ( *it )->GetCell( col ).SetFgCol( fgCol );
688 ( *it )->SetValueFromString( param.
value );
702 item.
modelName = m_modelListBox->GetStringSelection();
704 if( m_rbBuiltinModel->GetValue() || item.
modelName ==
"" )
709 m_codePreview->SetText(
text );
710 m_codePreview->SelectNone();
717 if( m_pinAssignmentsGrid->GetNumberRows() == 0 )
719 m_pinAssignmentsGrid->AppendRows(
static_cast<int>( m_sortedPartPins.size() ) );
721 for(
int ii = 0; ii < m_pinAssignmentsGrid->GetNumberRows(); ++ii )
723 wxString symbolPinString = getSymbolPinString( ii );
725 m_pinAssignmentsGrid->SetReadOnly( ii, PIN_COLUMN::SYMBOL );
726 m_pinAssignmentsGrid->SetCellValue( ii, PIN_COLUMN::SYMBOL, symbolPinString );
729 aForceUpdatePins =
true;
732 if( aForceUpdatePins )
735 for(
int row = 0; row < m_pinAssignmentsGrid->GetNumberRows(); ++row )
736 m_pinAssignmentsGrid->SetCellValue( row, PIN_COLUMN::MODEL,
_(
"Not Connected" ) );
739 for(
int modelPinIndex = 0; modelPinIndex < aModel->
GetPinCount(); ++modelPinIndex )
743 if( symbolPinNumber ==
"" )
746 int symbolPinRow = findSymbolPinRow( symbolPinNumber );
748 if( symbolPinRow == -1 )
751 wxString modelPinString = getModelPinString( aModel, modelPinIndex );
752 m_pinAssignmentsGrid->SetCellValue( symbolPinRow, PIN_COLUMN::MODEL, modelPinString );
756 for(
int ii = 0; ii < m_pinAssignmentsGrid->GetNumberRows(); ++ii )
759 std::vector<BITMAPS> modelPinIcons;
760 wxArrayString modelPinChoices;
762 for(
int jj = 0; jj < aModel->
GetPinCount(); ++jj )
769 modelPinChoices.Add( getModelPinString( aModel, jj ) );
773 modelPinChoices.Add(
_(
"Not Connected" ) );
777 m_pinAssignmentsGrid->SetCellEditor( ii, PIN_COLUMN::MODEL,
784 if( aModel->
GetType() == SIM_MODEL::TYPE::SUBCKT )
788 m_subckt->SetEditable(
false );
792 m_subcktLabel->Show(
false );
793 m_subckt->Show(
false );
813 if( m_prevLibrary == aLibraryPath && !aForceReload )
816 m_libraryModelsMgr.SetForceFullParse();
817 m_libraryModelsMgr.SetLibrary( aLibraryPath, aReporter );
824 for(
const auto& [baseModelName, baseModel] :
library()->GetModels() )
826 if( baseModelName == modelName )
827 m_libraryModelsMgr.CreateModel( &baseModel, m_sortedPartPins, m_fields, aReporter );
829 m_libraryModelsMgr.CreateModel( &baseModel, m_sortedPartPins, aReporter );
832 m_rbLibraryModel->SetValue(
true );
833 m_libraryPathText->ChangeValue( aLibraryPath );
835 wxArrayString modelNames;
837 for(
const auto& [
name, model] :
library()->GetModels() )
838 modelNames.Add(
name );
842 m_modelListBox->Clear();
843 m_modelListBox->Append( modelNames );
847 wxArrayString emptyArray;
848 m_pinModelCombobox->Set( emptyArray );
849 m_pinCombobox->Set( emptyArray );
850 m_pinModelCombobox->SetSelection( -1 );
851 m_pinCombobox->SetSelection( -1 );
854 m_modelListBox->SetStringSelection( modelName );
856 if( m_modelListBox->GetSelection() < 0 && m_modelListBox->GetCount() > 0 )
857 m_modelListBox->SetSelection( 0 );
859 m_curModelType = curModel().GetType();
861 m_prevLibrary = aLibraryPath;
875 m_paramGrid->HideProperty(
"AC",
false );
876 m_paramGrid->AppendIn(
"AC", newParamProperty( aModel, aParamIndex ) );
880 m_paramGrid->HideProperty(
"DC",
false );
881 m_paramGrid->AppendIn(
"DC", newParamProperty( aModel, aParamIndex ) );
884 case CATEGORY::S_PARAM:
885 m_paramGrid->HideProperty(
"S-Parameters",
false );
886 m_paramGrid->AppendIn(
"S-Parameters", newParamProperty( aModel, aParamIndex ) );
889 case CATEGORY::CAPACITANCE:
890 m_paramGrid->HideProperty(
"Capacitance",
false );
891 m_paramGrid->AppendIn(
"Capacitance", newParamProperty( aModel, aParamIndex ) );
894 case CATEGORY::TEMPERATURE:
895 m_paramGrid->HideProperty(
"Temperature",
false );
896 m_paramGrid->AppendIn(
"Temperature", newParamProperty( aModel, aParamIndex ) );
899 case CATEGORY::NOISE:
900 m_paramGrid->HideProperty(
"Noise",
false );
901 m_paramGrid->AppendIn(
"Noise", newParamProperty( aModel, aParamIndex ) );
904 case CATEGORY::DISTRIBUTED_QUANTITIES:
905 m_paramGrid->HideProperty(
"Distributed Quantities",
false );
906 m_paramGrid->AppendIn(
"Distributed Quantities", newParamProperty( aModel, aParamIndex ) );
909 case CATEGORY::WAVEFORM:
910 m_paramGrid->HideProperty(
"Waveform",
false );
911 m_paramGrid->AppendIn(
"Waveform", newParamProperty( aModel, aParamIndex ) );
914 case CATEGORY::GEOMETRY:
915 m_paramGrid->HideProperty(
"Geometry",
false );
916 m_paramGrid->AppendIn(
"Geometry", newParamProperty( aModel, aParamIndex ) );
919 case CATEGORY::LIMITING_VALUES:
920 m_paramGrid->HideProperty(
"Limiting Values",
false );
921 m_paramGrid->AppendIn(
"Limiting Values", newParamProperty( aModel, aParamIndex ) );
924 case CATEGORY::ADVANCED:
925 m_paramGrid->HideProperty(
"Advanced",
false );
926 m_paramGrid->AppendIn(
"Advanced", newParamProperty( aModel, aParamIndex ) );
929 case CATEGORY::FLAGS:
930 m_paramGrid->HideProperty(
"Flags",
false );
931 m_paramGrid->AppendIn(
"Flags", newParamProperty( aModel, aParamIndex ) );
935 m_paramGrid->Insert( m_firstCategory, newParamProperty( aModel, aParamIndex ) );
938 case CATEGORY::INITIAL_CONDITIONS:
939 case CATEGORY::SUPERFLUOUS:
949 wxString paramDescription;
952 paramDescription = wxString::Format(
"%s", param.
info.
name );
956 wxPGProperty* prop =
nullptr;
963 prop->SetAttribute( wxPG_BOOL_USE_CHECKBOX,
true );
985 wxArrayString inductors;
997 if( item.model->GetDeviceType() == SIM_MODEL::DEVICE_T::L )
998 inductors.push_back( item.refName );
1002 [](
const wxString& a,
const wxString& b ) ->
int
1008 if( inductors.empty() )
1016 aParamIndex, inductors );
1026 wxArrayString values;
1029 values.Add(
string );
1037 prop =
new wxStringProperty( paramDescription, param.
info.
name );
1041 prop->SetAttribute( wxPG_ATTR_UNITS, wxString::FromUTF8( param.
info.
unit.c_str() ) );
1061 prop->SetCell( PARAM_COLUMN::TYPE, typeStr );
1067template <
typename T>
1070 for(
int row = 0; row < static_cast<int>( m_sortedPartPins.size() ); ++row )
1074 if(
pin->GetNumber() == aSymbolPinNumber )
1082template <
typename T>
1085 if( m_rbLibraryModel->GetValue() )
1087 if(
library() && m_modelListBox->GetSelection() >= 0 )
1088 return *
library()->FindModel( m_modelListBox->GetStringSelection().ToStdString() );
1092 if(
static_cast<int>( m_curModelType ) <
static_cast<int>( m_builtinModelsMgr.GetModels().size() ) )
1093 return m_builtinModelsMgr.GetModels().at(
static_cast<int>( m_curModelType ) );
1096 return m_builtinModelsMgr.GetModels().at(
static_cast<int>( SIM_MODEL::TYPE::NONE ) );
1100template <
typename T>
1103 if( m_libraryModelsMgr.GetLibraries().size() == 1 )
1104 return &m_libraryModelsMgr.GetLibraries().begin()->second.get();
1110template <
typename T>
1113 SCH_PIN*
pin = m_sortedPartPins.at( symbolPinIndex );
1119 pinNumber =
pin->GetShownNumber();
1120 pinName =
pin->GetShownName();
1123 if( !pinName.IsEmpty() && pinName != pinNumber )
1124 pinNumber += wxString::Format( wxT(
" (%s)" ), pinName );
1130template <
typename T>
1137 wxString modelPinNumber = wxString::Format(
"%d", aModelPinIndex + 1 );
1139 if( !modelPinName.IsEmpty() && modelPinName != modelPinNumber )
1140 modelPinNumber += wxString::Format( wxT(
" (%s)" ), modelPinName );
1142 return modelPinNumber;
1146template <
typename T>
1149 if( aModelPinString ==
"Not Connected" )
1152 int length = aModelPinString.Find(
" " );
1154 if( length == wxNOT_FOUND )
1155 length =
static_cast<int>( aModelPinString.Length() );
1158 aModelPinString.Mid( 0, length ).ToCLong( &result );
1160 return static_cast<int>( result - 1 );
1164template <
typename T>
1167 m_prevModel =
nullptr;
1172template <
typename T>
1175 m_rbLibraryModel->SetValue(
true );
1179template <
typename T>
1182 m_rbLibraryModel->SetValue(
true );
1185 wxString
path = m_libraryPathText->GetValue();
1187 if( loadLibrary(
path, reporter,
true ) ||
path.IsEmpty() )
1196template <
typename T>
1206 wxCommandEvent
dummy;
1207 onLibraryPathTextEnter(
dummy );
1214template <
typename T>
1217 static wxString s_mruPath;
1220 wxFileDialog dlg(
this,
_(
"Browse Models" ),
path );
1222 if( dlg.ShowModal() == wxID_CANCEL )
1225 m_rbLibraryModel->SetValue(
true );
1227 path = dlg.GetPath();
1228 wxFileName fn(
path );
1230 s_mruPath = fn.GetPath();
1232 if( fn.MakeRelativeTo(
Prj().GetProjectPath() ) && !fn.GetFullPath().StartsWith( wxS(
".." ) ) )
1233 path = fn.GetFullPath();
1237 if( loadLibrary(
path, reporter,
true ) )
1246template <
typename T>
1249 int sel = m_modelListBox->GetSelection();
1251 switch( aKeyStroke.GetKeyCode() )
1254 if( sel == wxNOT_FOUND )
1255 sel = m_modelListBox->GetCount() - 1;
1262 if( sel == wxNOT_FOUND )
1270 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
1278 if( sel >= 0 && sel < (
int) m_modelListBox->GetCount() )
1279 m_modelListBox->SetSelection( sel );
1283template <
typename T>
1286 wxArrayString modelNames;
1287 wxString current = m_modelListBox->GetStringSelection();
1288 wxString
filter = wxT(
"*" ) + m_modelFilter->GetValue() + wxT(
"*" );
1290 for(
const auto& [
name, model] :
library()->GetModels() )
1292 wxString wx_name(
name );
1294 if( wx_name.Matches(
filter ) )
1295 modelNames.Add( wx_name );
1300 m_modelListBox->Clear();
1301 m_modelListBox->Append( modelNames );
1303 if( !m_modelListBox->SetStringSelection( current ) )
1304 m_modelListBox->SetSelection( 0 );
1308template <
typename T>
1311 if( isIbisLoaded() )
1313 wxArrayString pinLabels;
1316 wxCHECK2( modelkibis,
return );
1318 for( std::pair<wxString, wxString> strs : modelkibis->
GetIbisPins() )
1319 pinLabels.Add( strs.first + wxT(
" - " ) + strs.second );
1321 m_pinCombobox->Set( pinLabels );
1323 wxArrayString emptyArray;
1324 m_pinModelCombobox->Set( emptyArray );
1327 m_rbLibraryModel->SetValue(
true );
1331 wxArrayString lines = wxSplit( fallback->GetSpiceCode(),
'\n' );
1334 for(
const wxString& line : lines )
1336 if( !line.StartsWith(
'*' ) )
1338 if( !code.IsEmpty() )
1345 m_infoBar->ShowMessage( wxString::Format(
_(
"Failed to parse:\n\n"
1347 "Using generic SPICE model." ),
1359template <
typename T>
1362 wxArrayString modelLabels;
1366 std::vector<std::pair<std::string, std::string>> strs = ibisModel.
GetIbisPins();
1367 std::string pinNumber = strs.at( m_pinCombobox->GetSelection() ).first;
1371 ibisModel.
ChangePin( *ibisLibrary, pinNumber );
1376 modelLabels.Add( modelName );
1378 m_pinModelCombobox->Set( modelLabels );
1380 if( m_pinModelCombobox->GetCount() == 1 )
1381 m_pinModelCombobox->SetSelection( 0 );
1383 m_pinModelCombobox->SetSelection( -1 );
1389template <
typename T>
1392 m_pinCombobox->SetSelection( m_pinCombobox->FindString( m_pinCombobox->GetValue() ) );
1394 onPinModelCombobox( aEvent );
1398template <
typename T>
1405template <
typename T>
1408 m_pinModelCombobox->SetSelection( m_pinModelCombobox->FindString( m_pinModelCombobox->GetValue() ) );
1411template <
typename T>
1416 bool diff = m_differentialCheckbox->GetValue() && modelibis->CanDifferential();
1417 modelibis->SwitchSingleEndedDiff( diff );
1424template <
typename T>
1427 m_rbBuiltinModel->SetValue(
true );
1429 for( SIM_MODEL::DEVICE_T deviceType : SIM_MODEL::DEVICE_T_ITERATOR() )
1433 m_curModelType = m_curModelTypeOfDeviceType.at( deviceType );
1442template <
typename T>
1445 SIM_MODEL::DEVICE_T deviceType = curModel().GetDeviceType();
1446 wxString typeDescription = m_waveformChoice->GetStringSelection();
1448 for( SIM_MODEL::TYPE type : { SIM_MODEL::TYPE::KIBIS_DEVICE,
1449 SIM_MODEL::TYPE::KIBIS_DRIVER_DC,
1450 SIM_MODEL::TYPE::KIBIS_DRIVER_RECT,
1451 SIM_MODEL::TYPE::KIBIS_DRIVER_PRBS } )
1456 int idx = m_modelListBox->GetSelection();
1458 auto& baseModel =
static_cast<SIM_MODEL_IBIS&
>( m_libraryModelsMgr.GetModels()[idx].get() );
1460 m_libraryModelsMgr.SetModel( idx, std::make_unique<SIM_MODEL_IBIS>( type, baseModel ) );
1464 m_libraryModelsMgr.GetModels()[idx].get().
ReadDataFields( &m_fields, m_sortedPartPins );
1471 m_curModelType = type;
1476 m_curModelTypeOfDeviceType.at( deviceType ) = m_curModelType;
1481template <
typename T>
1484 SIM_MODEL::DEVICE_T deviceType = curModel().GetDeviceType();
1485 wxString typeDescription = m_deviceSubtypeChoice->GetStringSelection();
1487 for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
1492 m_curModelType = type;
1497 m_curModelTypeOfDeviceType.at( deviceType ) = m_curModelType;
1502template <
typename T>
1505 updateModelCodeTab( &curModel() );
1509template <
typename T>
1512 int symbolPinIndex = aEvent.GetRow();
1513 wxString oldModelPinName = aEvent.GetString();
1514 wxString modelPinName = m_pinAssignmentsGrid->GetCellValue( aEvent.GetRow(), aEvent.GetCol() );
1516 int oldModelPinIndex = getModelPinIndex( oldModelPinName );
1517 int modelPinIndex = getModelPinIndex( modelPinName );
1520 curModel().AssignSymbolPinNumberToModelPin( oldModelPinIndex,
"" );
1524 SCH_PIN* symbolPin = m_sortedPartPins.at( symbolPinIndex );
1526 curModel().AssignSymbolPinNumberToModelPin( modelPinIndex, symbolPin->
GetShownNumber() );
1535template <
typename T>
1538 wxGridUpdateLocker deferRepaintsTillLeavingScope( m_pinAssignmentsGrid );
1541 m_pinAssignmentsGrid->SetColSize( PIN_COLUMN::MODEL, gridWidth / 2 );
1542 m_pinAssignmentsGrid->SetColSize( PIN_COLUMN::SYMBOL, gridWidth / 2 );
1548template <
typename T>
1554 wxPropertyGrid*
grid = m_paramGrid->GetGrid();
1555 wxPGProperty* selected =
grid->GetSelection();
1558 selected =
grid->wxPropertyGridInterface::GetFirst();
1560#if wxCHECK_VERSION( 3, 3, 0 )
1562 grid->DoSelectProperty( selected, wxPGSelectPropertyFlags::Focus );
1565 grid->DoSelectProperty( selected, wxPG_SEL_FOCUS );
1572template <
typename T>
1575 wxPropertyGrid*
grid = m_paramGrid->GetGrid();
1578 if(
grid->GetSelection() &&
grid->GetSelection()->IsCategory() )
1580 wxPGProperty* selection =
grid->GetSelection();
1585 wxPropertyGridIterator it =
grid->GetIterator( wxPG_ITERATE_VISIBLE, selection );
1588 wxKeyEvent* keyEvent =
new wxKeyEvent( wxEVT_KEY_DOWN );
1590 if( *it == m_prevParamGridSelection )
1592 if( !selection->IsExpanded() )
1594 grid->Expand( selection );
1595 keyEvent->m_keyCode = WXK_DOWN;
1596 wxQueueEvent(
grid, keyEvent );
1604 keyEvent->m_keyCode = WXK_UP;
1605 wxQueueEvent(
grid, keyEvent );
1610 if( !selection->IsExpanded() )
1611 grid->Expand( selection );
1613 keyEvent->m_keyCode = WXK_DOWN;
1614 wxQueueEvent(
grid, keyEvent );
1617 m_prevParamGridSelection =
grid->GetSelection();
1621 wxWindow* editorControl =
grid->GetEditorControl();
1623 if( !editorControl )
1625 m_prevParamGridSelection =
grid->GetSelection();
1630 editorControl->SetFocus();
1631 m_prevParamGridSelection =
grid->GetSelection();
1635template <
typename T>
1646 wxPropertyGrid*
grid = m_paramGrid->GetGrid();
1647 wxTextCtrl* ctrl =
grid->GetEditorTextCtrl();
1651 wxRect ctrlRect = ctrl->GetScreenRect();
1652 wxRect gridRect =
grid->GetScreenRect();
1654 if( ctrlRect.GetTop() < gridRect.GetTop() || ctrlRect.GetBottom() > gridRect.GetBottom() )
1655 grid->ClearSelection();
1661template <
typename T>
1664 wxPropertyGrid*
grid = m_paramGridMgr->GetGrid();
1668 if( aWidth != m_lastParamGridWidth || aForce )
1670 m_lastParamGridWidth = aWidth;
1674 std::vector<int> colWidths;
1676 for(
size_t ii = 0; ii <
grid->GetColumnCount(); ii++ )
1678 if( ii == PARAM_COLUMN::DESCRIPTION )
1679 colWidths.push_back(
grid->GetState()->GetColumnWidth( ii ) + margin + indent );
1680 else if( ii == PARAM_COLUMN::VALUE )
1681 colWidths.push_back( std::max( 72,
grid->GetState()->GetColumnWidth( ii ) ) + margin );
1683 colWidths.push_back( 60 + margin );
1685 aWidth -= colWidths[ ii ];
1688 for(
size_t ii = 0; ii <
grid->GetColumnCount(); ii++ )
1689 grid->SetColumnProportion( ii, colWidths[ ii ] );
1691 grid->ResetColumnSizes();
1692 grid->RefreshEditor();
1697template <
typename T>
1700 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
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)
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".