Update simulator with NUMERIC_EVAL, decimal separator processing, etc.
Also includes fixes for instance data and resolving of textvar references. Also includes virtual d'tors for IBIS parser to get rid of all the compile warnings on CLang. Fixes https://gitlab.com/kicad/code/kicad/issues/12357
This commit is contained in:
parent
54dd494ff2
commit
b7d41e0e56
|
@ -59,11 +59,12 @@ expr(A) ::= expr(B) PLUS expr(C). { A.dValue = B.dValue + C.dValue; A.va
|
|||
expr(A) ::= expr(B) MINUS expr(C). { A.dValue = B.dValue - C.dValue; A.valid=C.valid; }
|
||||
expr(A) ::= expr(B) MULT expr(C). { A.dValue = B.dValue * C.dValue; A.valid=C.valid; }
|
||||
expr(A) ::= expr(B) DIVIDE expr(C). {
|
||||
if (C.dValue != 0.0) {
|
||||
if( C.dValue != 0.0 )
|
||||
A.dValue = B.dValue / C.dValue;
|
||||
}
|
||||
else pEval->parseError("Div by zero");
|
||||
A.valid=C.valid;
|
||||
}
|
||||
expr(A) ::= PARENL expr(B) PARENR. { A.dValue = B.dValue; A.valid=B.valid; }
|
||||
else
|
||||
pEval->parseError( "Divide by zero" );
|
||||
|
||||
A.valid = C.valid;
|
||||
}
|
||||
expr(A) ::= PARENL expr(B) PARENR. { A.dValue = B.dValue; A.valid = B.valid; }
|
||||
|
||||
|
|
|
@ -87,6 +87,7 @@ void NUMERIC_EVALUATOR::SetDefaultUnits( EDA_UNITS aUnits )
|
|||
case EDA_UNITS::MILS: m_defaultUnits = Unit::Mil; break;
|
||||
case EDA_UNITS::INCHES: m_defaultUnits = Unit::Inch; break;
|
||||
case EDA_UNITS::DEGREES: m_defaultUnits = Unit::Degrees; break;
|
||||
case EDA_UNITS::UNSCALED: m_defaultUnits = Unit::SI; break;
|
||||
default: m_defaultUnits = Unit::MM; break;
|
||||
}
|
||||
}
|
||||
|
@ -196,47 +197,82 @@ NUMERIC_EVALUATOR::Token NUMERIC_EVALUATOR::getToken()
|
|||
if( m_token.pos >= m_token.inputLen )
|
||||
return retval;
|
||||
|
||||
// Support for old school decimal separators (ie: "2K2")
|
||||
auto isOldSchoolDecimalSeparator =
|
||||
[]( char ch, double* siScaler ) -> bool
|
||||
{
|
||||
switch( ch )
|
||||
{
|
||||
case 'a': *siScaler = 1.0e-18; return true;
|
||||
case 'f': *siScaler = 1.0e-15; return true;
|
||||
case 'p': *siScaler = 1.0e-12; return true;
|
||||
case 'n': *siScaler = 1.0e-9; return true;
|
||||
case 'u': *siScaler = 1.0e-6; return true;
|
||||
case 'm': *siScaler = 1.0e-3; return true;
|
||||
case 'k':
|
||||
case 'K': *siScaler = 1.0e3; return true;
|
||||
case 'M': *siScaler = 1.0e6; return true;
|
||||
case 'G': *siScaler = 1.0e9; return true;
|
||||
case 'T': *siScaler = 1.0e12; return true;
|
||||
case 'P': *siScaler = 1.0e15; return true;
|
||||
case 'E': *siScaler = 1.0e18; return true;
|
||||
default: return false;
|
||||
}
|
||||
};
|
||||
|
||||
auto isDecimalSeparator =
|
||||
[&]( char ch ) -> bool
|
||||
{
|
||||
return ( ch == m_localeDecimalSeparator || ch == '.' || ch == ',' );
|
||||
double dummy;
|
||||
|
||||
if( ch == m_localeDecimalSeparator || ch == '.' || ch == ',' )
|
||||
return true;
|
||||
|
||||
if( m_defaultUnits == Unit::SI && isOldSchoolDecimalSeparator( ch, &dummy ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
// Lambda: get value as string, store into clToken.token and update current index.
|
||||
auto extractNumber =
|
||||
[&]()
|
||||
[&]( double* aScaler )
|
||||
{
|
||||
bool haveSeparator = false;
|
||||
idx = 0;
|
||||
double siScaler = 1.0;
|
||||
char ch = m_token.input[ m_token.pos ];
|
||||
|
||||
idx = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if( isDecimalSeparator( ch ) && haveSeparator )
|
||||
break;
|
||||
|
||||
m_token.token[ idx++ ] = ch;
|
||||
|
||||
if( isDecimalSeparator( ch ) )
|
||||
{
|
||||
if( haveSeparator )
|
||||
break;
|
||||
else
|
||||
haveSeparator = true;
|
||||
|
||||
if( isOldSchoolDecimalSeparator( ch, &siScaler ) )
|
||||
*aScaler = siScaler;
|
||||
|
||||
m_token.token[ idx++ ] = m_localeDecimalSeparator;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_token.token[ idx++ ] = ch;
|
||||
}
|
||||
|
||||
ch = m_token.input[ ++m_token.pos ];
|
||||
} while( isdigit( ch ) || isDecimalSeparator( ch ) );
|
||||
|
||||
m_token.token[ idx ] = 0;
|
||||
|
||||
// Ensure that the systems decimal separator is used
|
||||
for( int i = strlen( m_token.token ); i; i-- )
|
||||
{
|
||||
if( isDecimalSeparator( m_token.token[ i - 1 ] ) )
|
||||
m_token.token[ i - 1 ] = m_localeDecimalSeparator;
|
||||
}
|
||||
};
|
||||
|
||||
// Lamda: Get unit for current token.
|
||||
// Valid units are ", in, mm, mil and thou. Returns Unit::Invalid otherwise.
|
||||
auto checkUnit =
|
||||
[this]() -> Unit
|
||||
[&]( double* siScaler ) -> Unit
|
||||
{
|
||||
char ch = m_token.input[ m_token.pos ];
|
||||
|
||||
|
@ -289,6 +325,13 @@ NUMERIC_EVALUATOR::Token NUMERIC_EVALUATOR::getToken()
|
|||
return Unit::Mil;
|
||||
}
|
||||
|
||||
if( m_defaultUnits == Unit::SI && sizeLeft >= 1
|
||||
&& isOldSchoolDecimalSeparator( ch, siScaler ) )
|
||||
{
|
||||
m_token.pos++;
|
||||
return Unit::SI;
|
||||
}
|
||||
|
||||
return Unit::Invalid;
|
||||
};
|
||||
|
||||
|
@ -305,20 +348,21 @@ NUMERIC_EVALUATOR::Token NUMERIC_EVALUATOR::getToken()
|
|||
break;
|
||||
}
|
||||
|
||||
double siScaler;
|
||||
Unit convertFrom;
|
||||
|
||||
if( ch == 0 )
|
||||
{
|
||||
/* End of input */
|
||||
}
|
||||
else if( isdigit( ch ) || isDecimalSeparator( ch ))
|
||||
else if( isdigit( ch ) || isDecimalSeparator( ch ) )
|
||||
{
|
||||
// VALUE
|
||||
extractNumber();
|
||||
extractNumber( &siScaler );
|
||||
retval.token = VALUE;
|
||||
retval.value.dValue = atof( m_token.token );
|
||||
retval.value.dValue = atof( m_token.token ) * siScaler;
|
||||
}
|
||||
else if( ( convertFrom = checkUnit() ) != Unit::Invalid )
|
||||
else if( ( convertFrom = checkUnit( &siScaler ) ) != Unit::Invalid )
|
||||
{
|
||||
// UNIT
|
||||
// Units are appended to a VALUE.
|
||||
|
@ -368,6 +412,10 @@ NUMERIC_EVALUATOR::Token NUMERIC_EVALUATOR::getToken()
|
|||
{
|
||||
retval.value.dValue = 1.0;
|
||||
}
|
||||
else if( m_defaultUnits == Unit::SI )
|
||||
{
|
||||
retval.value.dValue = siScaler;
|
||||
}
|
||||
}
|
||||
else if( isalpha( ch ) )
|
||||
{
|
||||
|
|
|
@ -243,6 +243,10 @@ template <typename T>
|
|||
bool DIALOG_SIM_MODEL<T>::TransferDataFromWindow()
|
||||
{
|
||||
m_pinAssignmentsGrid->CommitPendingChanges();
|
||||
|
||||
// This should have been done in wxPGTextCtrlEditor::OnTextCtrlEvent(), but something must
|
||||
// be clearing it before we get here, resulting in CommitChangesFromEditor() doing nothing
|
||||
m_paramGrid->GetGrid()->EditorsValueWasModified();
|
||||
m_paramGrid->GetGrid()->CommitChangesFromEditor();
|
||||
|
||||
if( !DIALOG_SIM_MODEL_BASE::TransferDataFromWindow() )
|
||||
|
@ -277,12 +281,14 @@ bool DIALOG_SIM_MODEL<T>::TransferDataFromWindow()
|
|||
SIM_MODEL::SetFieldValue(
|
||||
m_fields, SIM_LIBRARY_KIBIS::PIN_FIELD,
|
||||
kibismodel->GetIbisPins().at( m_ibisPinCombobox->GetSelection() ).first );
|
||||
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY_KIBIS::MODEL_FIELD,
|
||||
|
||||
SIM_MODEL::SetFieldValue(
|
||||
m_fields, SIM_LIBRARY_KIBIS::MODEL_FIELD,
|
||||
std::string( m_ibisModelCombobox->GetValue().c_str() ) );
|
||||
|
||||
SIM_MODEL::SetFieldValue(
|
||||
m_fields, SIM_LIBRARY_KIBIS::DIFF_FIELD,
|
||||
( kibismodel->CanDifferential() && m_differentialCheckbox->GetValue() ) ? "1"
|
||||
: "" );
|
||||
( kibismodel->CanDifferential() && m_differentialCheckbox->GetValue() ) ? "1" : "" );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -644,13 +650,14 @@ void DIALOG_SIM_MODEL<T>::loadLibrary( const wxString& aLibraryPath, bool aForce
|
|||
try
|
||||
{
|
||||
std::string modelName = SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY::NAME_FIELD );
|
||||
int pinCount = m_symbol.GetRawPins().size();
|
||||
|
||||
for( auto& [baseModelName, baseModel] : library()->GetModels() )
|
||||
{
|
||||
if( baseModelName == modelName )
|
||||
m_libraryModelsMgr.CreateModel( baseModel, m_symbol.GetRawPins().size(), m_fields );
|
||||
m_libraryModelsMgr.CreateModel( baseModel, pinCount, m_fields );
|
||||
else
|
||||
m_libraryModelsMgr.CreateModel( baseModel, m_symbol.GetRawPins().size() );
|
||||
m_libraryModelsMgr.CreateModel( baseModel, pinCount );
|
||||
}
|
||||
}
|
||||
catch( const IO_ERROR& e )
|
||||
|
@ -800,7 +807,7 @@ wxPGProperty* DIALOG_SIM_MODEL<T>::newParamProperty( int aParamIndex ) const
|
|||
else
|
||||
{
|
||||
prop = new SIM_ENUM_PROPERTY( paramDescription, param.info.name, curModel(),
|
||||
aParamIndex, SIM_VALUE::TYPE_STRING );
|
||||
aParamIndex );
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -939,32 +946,6 @@ int DIALOG_SIM_MODEL<T>::getModelPinIndex( const wxString& aModelPinString ) con
|
|||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void DIALOG_SIM_MODEL<T>::onKeyDown( wxKeyEvent& aEvent )
|
||||
{
|
||||
// Because wxPropertyGrid has special handling for the tab key, wxPropertyGrid::DedicateKey()
|
||||
// and wxPropertyGrid::AddActionTrigger() don't work for it. So instead we translate it to an
|
||||
// (up or down) arrow key, which has proper handling (select next or previous property) defined
|
||||
// by the aforementioned functions.
|
||||
|
||||
if( aEvent.GetKeyCode() == WXK_TAB )
|
||||
{
|
||||
wxWindow* focus = FindFocus();
|
||||
wxPropertyGrid* pg = focus ? dynamic_cast<wxPropertyGrid*>( focus->GetParent() ) : nullptr;
|
||||
|
||||
if( pg )
|
||||
{
|
||||
pg->CommitChangesFromEditor();
|
||||
|
||||
aEvent.m_keyCode = aEvent.ShiftDown() ? WXK_UP : WXK_DOWN;
|
||||
aEvent.m_shiftDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void DIALOG_SIM_MODEL<T>::onRadioButton( wxCommandEvent& aEvent )
|
||||
{
|
||||
|
@ -1187,8 +1168,7 @@ void DIALOG_SIM_MODEL<T>::onTypeChoice( wxCommandEvent& aEvent )
|
|||
m_libraryModelsMgr.GetModels().at( m_modelNameCombobox->GetSelection() ).get() );
|
||||
|
||||
m_libraryModelsMgr.SetModel( m_modelNameCombobox->GetSelection(),
|
||||
std::make_unique<SIM_MODEL_KIBIS>( type,
|
||||
kibisModel,
|
||||
std::make_unique<SIM_MODEL_KIBIS>( type, kibisModel,
|
||||
m_fields ) );
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,6 @@ private:
|
|||
wxString getModelPinString( int aModelPinIndex ) const;
|
||||
int getModelPinIndex( const wxString& aModelPinString ) const;
|
||||
|
||||
void onKeyDown( wxKeyEvent& aEvent ) override;
|
||||
void onRadioButton( wxCommandEvent& aEvent ) override;
|
||||
void onLibraryPathTextEnter( wxCommandEvent& aEvent ) override;
|
||||
void onLibraryPathTextKillFocus( wxFocusEvent& aEvent ) override;
|
||||
|
|
|
@ -197,6 +197,9 @@ DIALOG_SIM_MODEL_BASE::DIALOG_SIM_MODEL_BASE( wxWindow* parent, wxWindowID id, c
|
|||
bSizerMargins->Add( m_saveInValueCheckbox, 0, wxALL, 6 );
|
||||
|
||||
|
||||
bSizerMargins->Add( 0, 3, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizerPanel->Add( bSizerMargins, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
|
@ -244,7 +247,7 @@ DIALOG_SIM_MODEL_BASE::DIALOG_SIM_MODEL_BASE( wxWindow* parent, wxWindowID id, c
|
|||
bSizer10->Fit( m_pinAssignmentsPanel );
|
||||
m_notebook->AddPage( m_pinAssignmentsPanel, _("Pin Assignments"), false );
|
||||
|
||||
bSizer8->Add( m_notebook, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
bSizer8->Add( m_notebook, 1, wxEXPAND|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
wxBoxSizer* bSizer81;
|
||||
bSizer81 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
@ -275,7 +278,6 @@ DIALOG_SIM_MODEL_BASE::DIALOG_SIM_MODEL_BASE( wxWindow* parent, wxWindowID id, c
|
|||
this->Centre( wxBOTH );
|
||||
|
||||
// Connect Events
|
||||
this->Connect( wxEVT_KEY_DOWN, wxKeyEventHandler( DIALOG_SIM_MODEL_BASE::onKeyDown ) );
|
||||
m_useLibraryModelRadioButton->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onRadioButton ), NULL, this );
|
||||
m_pathLabel->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onLibraryPathLabelUpdate ), NULL, this );
|
||||
m_libraryPathText->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_SIM_MODEL_BASE::onLibraryPathTextKillFocus ), NULL, this );
|
||||
|
@ -317,7 +319,6 @@ DIALOG_SIM_MODEL_BASE::DIALOG_SIM_MODEL_BASE( wxWindow* parent, wxWindowID id, c
|
|||
DIALOG_SIM_MODEL_BASE::~DIALOG_SIM_MODEL_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
this->Disconnect( wxEVT_KEY_DOWN, wxKeyEventHandler( DIALOG_SIM_MODEL_BASE::onKeyDown ) );
|
||||
m_useLibraryModelRadioButton->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onRadioButton ), NULL, this );
|
||||
m_pathLabel->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onLibraryPathLabelUpdate ), NULL, this );
|
||||
m_libraryPathText->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_SIM_MODEL_BASE::onLibraryPathTextKillFocus ), NULL, this );
|
||||
|
|
|
@ -56,7 +56,6 @@
|
|||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnKeyDown">onKeyDown</event>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer8</property>
|
||||
|
@ -64,7 +63,7 @@
|
|||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
|
||||
<property name="flag">wxEXPAND|wxRIGHT|wxLEFT</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxNotebook" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
|
@ -1519,11 +1518,11 @@
|
|||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="notebookpage" expanded="0">
|
||||
<object class="notebookpage" expanded="1">
|
||||
<property name="bitmap"></property>
|
||||
<property name="label">Code</property>
|
||||
<property name="select">0</property>
|
||||
<object class="wxPanel" expanded="0">
|
||||
<object class="wxPanel" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
|
@ -1574,7 +1573,7 @@
|
|||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style">wxTAB_TRAVERSAL</property>
|
||||
<object class="wxBoxSizer" expanded="0">
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer5</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
|
@ -1717,6 +1716,16 @@
|
|||
<event name="OnCheckBox">onSaveInValueCheckbox</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="spacer" expanded="1">
|
||||
<property name="height">3</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">0</property>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
|
|
|
@ -84,7 +84,6 @@ class DIALOG_SIM_MODEL_BASE : public DIALOG_SHIM
|
|||
wxButton* m_sdbSizer1Cancel;
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void onKeyDown( wxKeyEvent& event ) { event.Skip(); }
|
||||
virtual void onRadioButton( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onLibraryPathLabelUpdate( wxUpdateUIEvent& event ) { event.Skip(); }
|
||||
virtual void onLibraryPathTextKillFocus( wxFocusEvent& event ) { event.Skip(); }
|
||||
|
|
|
@ -217,11 +217,16 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
|
|||
|
||||
SPICE_ITEM spiceItem;
|
||||
|
||||
// This is a little bit dangerous as any value fetched from the fields will not
|
||||
// be instance-data aware, and will just fetch the value of some random sheet
|
||||
// (whatever sheet the user happens to be looking at). However, we currently only
|
||||
// use it to fetch "Sim_*" fields, which have no instance data.
|
||||
spiceItem.fields = &symbol->GetFields();
|
||||
for( int i = 0; i < symbol->GetFieldCount(); ++i )
|
||||
{
|
||||
spiceItem.fields.emplace_back( VECTOR2I(), i, symbol,
|
||||
symbol->GetFields()[ i ].GetName() );
|
||||
|
||||
if( i == REFERENCE_FIELD )
|
||||
spiceItem.fields.back().SetText( symbol->GetRef( &sheet ) );
|
||||
else
|
||||
spiceItem.fields.back().SetText( symbol->GetFields()[i].GetShownText( 0, false ) );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -371,7 +376,7 @@ bool NETLIST_EXPORTER_SPICE::readRefName( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aS
|
|||
void NETLIST_EXPORTER_SPICE::readModel( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aSymbol,
|
||||
SPICE_ITEM& aItem )
|
||||
{
|
||||
SIM_LIBRARY::MODEL libModel = m_libMgr.CreateModel( aSymbol );
|
||||
SIM_LIBRARY::MODEL libModel = m_libMgr.CreateModel( &aSheet, aSymbol );
|
||||
|
||||
aItem.baseModelName = libModel.name;
|
||||
aItem.model = &libModel.model;
|
||||
|
|
|
@ -210,7 +210,12 @@ public:
|
|||
class IbisComponentPin : public IBIS_INPUT
|
||||
{
|
||||
public:
|
||||
IbisComponentPin( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ){};
|
||||
IbisComponentPin( IBIS_REPORTER* aReporter ) :
|
||||
IBIS_INPUT( aReporter )
|
||||
{};
|
||||
|
||||
virtual ~IbisComponentPin()
|
||||
{};
|
||||
|
||||
std::string m_pinName;
|
||||
std::string m_signalName;
|
||||
|
@ -232,7 +237,13 @@ public:
|
|||
class IbisComponentPinMapping : public IBIS_INPUT
|
||||
{
|
||||
public:
|
||||
IbisComponentPinMapping( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ){};
|
||||
IbisComponentPinMapping( IBIS_REPORTER* aReporter ) :
|
||||
IBIS_INPUT( aReporter )
|
||||
{};
|
||||
|
||||
virtual ~IbisComponentPinMapping()
|
||||
{};
|
||||
|
||||
std::string m_pinName;
|
||||
std::string m_PDref;
|
||||
std::string m_PUref;
|
||||
|
@ -247,7 +258,13 @@ public:
|
|||
class IbisDiffPinEntry : public IBIS_INPUT
|
||||
{
|
||||
public:
|
||||
IbisDiffPinEntry( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ), tdelay( aReporter ){};
|
||||
IbisDiffPinEntry( IBIS_REPORTER* aReporter ) :
|
||||
IBIS_INPUT( aReporter ),
|
||||
tdelay( aReporter )
|
||||
{};
|
||||
|
||||
virtual ~IbisDiffPinEntry()
|
||||
{};
|
||||
|
||||
std::string pinA;
|
||||
std::string pinB;
|
||||
|
@ -259,7 +276,10 @@ public:
|
|||
class IbisDiffPin : IBIS_INPUT
|
||||
{
|
||||
public:
|
||||
IbisDiffPin( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ){};
|
||||
IbisDiffPin( IBIS_REPORTER* aReporter ) :
|
||||
IBIS_INPUT( aReporter )
|
||||
{};
|
||||
|
||||
std::vector<IbisDiffPinEntry> m_entries;
|
||||
};
|
||||
|
||||
|
@ -272,6 +292,9 @@ public:
|
|||
m_diffPin( aReporter )
|
||||
{};
|
||||
|
||||
virtual ~IbisComponent()
|
||||
{};
|
||||
|
||||
std::string m_name = "";
|
||||
std::string m_manufacturer = "";
|
||||
IbisComponentPackage m_package;
|
||||
|
@ -297,7 +320,13 @@ public:
|
|||
class IbisModelSelector : public IBIS_INPUT
|
||||
{
|
||||
public:
|
||||
IbisModelSelector( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ){};
|
||||
IbisModelSelector( IBIS_REPORTER* aReporter ) :
|
||||
IBIS_INPUT( aReporter )
|
||||
{};
|
||||
|
||||
virtual ~IbisModelSelector()
|
||||
{};
|
||||
|
||||
std::string m_name;
|
||||
std::vector<IbisModelSelectorEntry> m_models;
|
||||
|
||||
|
@ -308,7 +337,14 @@ public:
|
|||
class IVtableEntry : public IBIS_INPUT
|
||||
{
|
||||
public:
|
||||
IVtableEntry( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ), I( aReporter ){};
|
||||
IVtableEntry( IBIS_REPORTER* aReporter ) :
|
||||
IBIS_INPUT( aReporter ),
|
||||
I( aReporter )
|
||||
{};
|
||||
|
||||
virtual ~IVtableEntry()
|
||||
{};
|
||||
|
||||
double V = 0;
|
||||
TypMinMaxValue I;
|
||||
};
|
||||
|
@ -317,7 +353,10 @@ public:
|
|||
class IVtable : public IBIS_INPUT
|
||||
{
|
||||
public:
|
||||
IVtable( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ){};
|
||||
IVtable( IBIS_REPORTER* aReporter ) :
|
||||
IBIS_INPUT( aReporter )
|
||||
{};
|
||||
|
||||
std::vector<IVtableEntry> m_entries;
|
||||
|
||||
bool Check() override;
|
||||
|
@ -353,7 +392,14 @@ private:
|
|||
class VTtableEntry : public IBIS_INPUT
|
||||
{
|
||||
public:
|
||||
VTtableEntry( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ), V( aReporter ){};
|
||||
VTtableEntry( IBIS_REPORTER* aReporter ) :
|
||||
IBIS_INPUT( aReporter ),
|
||||
V( aReporter )
|
||||
{};
|
||||
|
||||
virtual ~VTtableEntry()
|
||||
{};
|
||||
|
||||
double t = 0;
|
||||
TypMinMaxValue V = 0;
|
||||
};
|
||||
|
@ -361,7 +407,10 @@ public:
|
|||
class VTtable : public IBIS_INPUT
|
||||
{
|
||||
public:
|
||||
VTtable( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ){};
|
||||
VTtable( IBIS_REPORTER* aReporter ) :
|
||||
IBIS_INPUT( aReporter )
|
||||
{};
|
||||
|
||||
std::vector<VTtableEntry> m_entries;
|
||||
};
|
||||
|
||||
|
@ -468,7 +517,8 @@ enum class IBIS_MODEL_POLARITY
|
|||
class IbisModel : IBIS_INPUT
|
||||
{
|
||||
public:
|
||||
IbisModel( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ),
|
||||
IbisModel( IBIS_REPORTER* aReporter ) :
|
||||
IBIS_INPUT( aReporter ),
|
||||
m_C_comp( aReporter ),
|
||||
m_voltageRange( aReporter ),
|
||||
m_temperatureRange( aReporter ),
|
||||
|
@ -487,6 +537,9 @@ public:
|
|||
m_ramp( aReporter )
|
||||
{};
|
||||
|
||||
virtual ~IbisModel()
|
||||
{};
|
||||
|
||||
std::string m_name;
|
||||
IBIS_MODEL_TYPE m_type = IBIS_MODEL_TYPE::UNDEFINED;
|
||||
/* The Polarity, Enable, Vinl, Vinh, Vmeas, Cref, Rref, and Vref subparameters are optional. */
|
||||
|
@ -527,7 +580,12 @@ public:
|
|||
class IbisPackageModel : public IBIS_INPUT
|
||||
{
|
||||
public:
|
||||
IbisPackageModel( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ){};
|
||||
IbisPackageModel( IBIS_REPORTER* aReporter ) :
|
||||
IBIS_INPUT( aReporter )
|
||||
{};
|
||||
|
||||
virtual ~IbisPackageModel()
|
||||
{};
|
||||
|
||||
std::string m_name;
|
||||
std::string m_manufacturer;
|
||||
|
@ -546,7 +604,13 @@ public:
|
|||
class IbisFile : public IBIS_INPUT
|
||||
{
|
||||
public:
|
||||
IbisFile( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ), m_header( aReporter ){};
|
||||
IbisFile( IBIS_REPORTER* aReporter ) :
|
||||
IBIS_INPUT( aReporter ),
|
||||
m_header( aReporter )
|
||||
{};
|
||||
|
||||
virtual ~IbisFile()
|
||||
{};
|
||||
|
||||
IbisHeader m_header;
|
||||
std::vector<IbisComponent> m_components;
|
||||
|
|
|
@ -95,9 +95,21 @@ template SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL& aBaseModel, int a
|
|||
const std::vector<LIB_FIELD>& aFields );
|
||||
|
||||
|
||||
SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( SCH_SYMBOL& aSymbol )
|
||||
SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const SCH_SHEET_PATH* aSheetPath, SCH_SYMBOL& aSymbol )
|
||||
{
|
||||
return CreateModel( aSymbol.GetFields(), static_cast<int>( aSymbol.GetRawPins().size() ) );
|
||||
std::vector<SCH_FIELD> fields;
|
||||
|
||||
for( int i = 0; i < aSymbol.GetFieldCount(); ++i )
|
||||
{
|
||||
fields.emplace_back( VECTOR2I(), i, &aSymbol, aSymbol.GetFields()[ i ].GetName() );
|
||||
|
||||
if( i == REFERENCE_FIELD )
|
||||
fields.back().SetText( aSymbol.GetRef( aSheetPath ) );
|
||||
else
|
||||
fields.back().SetText( aSymbol.GetFields()[ i ].GetShownText( 0, false ) );
|
||||
}
|
||||
|
||||
return CreateModel( fields, static_cast<int>( aSymbol.GetRawPins().size() ) );
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -154,8 +166,8 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const std::string& aLibraryPath,
|
|||
|
||||
if( !baseModel )
|
||||
{
|
||||
THROW_IO_ERROR(
|
||||
wxString::Format( _( "Error loading simulation model: could not find base model '%s' in library '%s'" ),
|
||||
THROW_IO_ERROR( wxString::Format( _( "Error loading simulation model: could not find "
|
||||
"base model '%s' in library '%s'" ),
|
||||
aBaseModelName,
|
||||
absolutePath ) );
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ public:
|
|||
const std::vector<T>& aFields );
|
||||
|
||||
// TODO: The argument can be made const.
|
||||
SIM_LIBRARY::MODEL CreateModel( SCH_SYMBOL& aSymbol );
|
||||
SIM_LIBRARY::MODEL CreateModel( const SCH_SHEET_PATH* aSheetPath, SCH_SYMBOL& aSymbol );
|
||||
|
||||
template <typename T>
|
||||
SIM_LIBRARY::MODEL CreateModel( const std::vector<T>& aFields, int aSymbolPinCount );
|
||||
|
|
|
@ -499,8 +499,7 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( TYPE aType, unsigned aSymbolPinCou
|
|||
}
|
||||
|
||||
|
||||
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
|
||||
unsigned aSymbolPinCount )
|
||||
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel, unsigned aSymbolPinCount )
|
||||
{
|
||||
std::unique_ptr<SIM_MODEL> model = Create( aBaseModel.GetType() );
|
||||
|
||||
|
|
|
@ -395,9 +395,9 @@ public:
|
|||
template <typename T>
|
||||
static TYPE InferTypeFromLegacyFields( const std::vector<T>& aFields );
|
||||
|
||||
|
||||
static std::unique_ptr<SIM_MODEL> Create( TYPE aType, unsigned aSymbolPinCount );
|
||||
static std::unique_ptr<SIM_MODEL> Create( const SIM_MODEL& aBaseModel,
|
||||
unsigned aSymbolPinCount );
|
||||
static std::unique_ptr<SIM_MODEL> Create( const SIM_MODEL& aBaseModel, unsigned aSymbolPinCount );
|
||||
|
||||
template <typename T>
|
||||
static std::unique_ptr<SIM_MODEL> Create( const SIM_MODEL& aBaseModel, unsigned aSymbolPinCount,
|
||||
|
|
|
@ -61,11 +61,11 @@ std::vector<std::string> SPICE_GENERATOR_KIBIS::CurrentNames( const SPICE_ITEM&
|
|||
std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem, const std::string aCwd,
|
||||
const std::string aCacheDir ) const
|
||||
{
|
||||
std::string ibisLibFilename = SIM_MODEL::GetFieldValue( aItem.fields, SIM_LIBRARY::LIBRARY_FIELD );
|
||||
std::string ibisCompName = SIM_MODEL::GetFieldValue( aItem.fields, SIM_LIBRARY::NAME_FIELD );
|
||||
std::string ibisPinName = SIM_MODEL::GetFieldValue( aItem.fields, SIM_LIBRARY_KIBIS::PIN_FIELD );
|
||||
std::string ibisModelName = SIM_MODEL::GetFieldValue( aItem.fields, SIM_LIBRARY_KIBIS::MODEL_FIELD );
|
||||
bool diffMode = SIM_MODEL::GetFieldValue( aItem.fields, SIM_LIBRARY_KIBIS::DIFF_FIELD ) == "1";
|
||||
std::string ibisLibFilename = SIM_MODEL::GetFieldValue( &aItem.fields, SIM_LIBRARY::LIBRARY_FIELD );
|
||||
std::string ibisCompName = SIM_MODEL::GetFieldValue( &aItem.fields, SIM_LIBRARY::NAME_FIELD );
|
||||
std::string ibisPinName = SIM_MODEL::GetFieldValue( &aItem.fields, SIM_LIBRARY_KIBIS::PIN_FIELD );
|
||||
std::string ibisModelName = SIM_MODEL::GetFieldValue( &aItem.fields, SIM_LIBRARY_KIBIS::MODEL_FIELD );
|
||||
bool diffMode = SIM_MODEL::GetFieldValue( &aItem.fields, SIM_LIBRARY_KIBIS::DIFF_FIELD ) == "1";
|
||||
|
||||
wxFileName libPath = wxFileName( wxString( ibisLibFilename ) );
|
||||
|
||||
|
@ -77,8 +77,7 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem, const st
|
|||
|
||||
if( !kibis.m_valid )
|
||||
{
|
||||
THROW_IO_ERROR( wxString::Format( _( "Invalid IBIS file '%s'" ),
|
||||
ibisLibFilename ) );
|
||||
THROW_IO_ERROR( wxString::Format( _( "Invalid IBIS file '%s'" ), ibisLibFilename ) );
|
||||
}
|
||||
|
||||
KIBIS_COMPONENT* kcomp = kibis.GetComponent( std::string( ibisCompName ) );
|
||||
|
@ -267,7 +266,8 @@ void SIM_MODEL_KIBIS::SwitchSingleEndedDiff( bool aDiff )
|
|||
}
|
||||
}
|
||||
|
||||
SIM_MODEL_KIBIS::SIM_MODEL_KIBIS( TYPE aType, const SIM_MODEL_KIBIS& aSource ) : SIM_MODEL_KIBIS( aType )
|
||||
SIM_MODEL_KIBIS::SIM_MODEL_KIBIS( TYPE aType, const SIM_MODEL_KIBIS& aSource ) :
|
||||
SIM_MODEL_KIBIS( aType )
|
||||
{
|
||||
for( PARAM& param1 : m_params )
|
||||
{
|
||||
|
|
|
@ -592,6 +592,7 @@ void SIM_PLOT_FRAME::AddTuner( SCH_SYMBOL* aSymbol )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void SIM_PLOT_FRAME::UpdateTunerValue( SCH_SYMBOL* aSymbol, const wxString& aValue )
|
||||
{
|
||||
for( EDA_ITEM* item : m_schematicFrame->GetScreen()->Items().OfType( SCH_SYMBOL_T ) )
|
||||
|
@ -599,7 +600,8 @@ void SIM_PLOT_FRAME::UpdateTunerValue( SCH_SYMBOL* aSymbol, const wxString& aVal
|
|||
if( item == aSymbol )
|
||||
{
|
||||
SIM_LIB_MGR mgr( Prj() );
|
||||
SIM_MODEL& model = mgr.CreateModel( *aSymbol ).model;
|
||||
SIM_MODEL& model = mgr.CreateModel( &m_schematicFrame->GetCurrentSheet(),
|
||||
*aSymbol ).model;
|
||||
|
||||
const SIM_MODEL::PARAM* tunerParam = model.GetTunerParam();
|
||||
|
||||
|
|
|
@ -22,10 +22,7 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <confirm.h>
|
||||
#include <wx/combo.h>
|
||||
#include <wx/combobox.h>
|
||||
#include <wx/notebook.h>
|
||||
|
||||
// Include simulator headers after wxWidgets headers to avoid conflicts with Windows headers
|
||||
// (especially on msys2 + wxWidgets 3.0.x)
|
||||
|
@ -34,229 +31,11 @@
|
|||
#include <ki_exception.h>
|
||||
|
||||
|
||||
wxBEGIN_EVENT_TABLE( SIM_VALIDATOR, wxValidator )
|
||||
EVT_KEY_DOWN( SIM_VALIDATOR::onKeyDown )
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
|
||||
void SIM_VALIDATOR::navigate( int flags )
|
||||
{
|
||||
wxWindow* textCtrl = GetWindow();
|
||||
if( !textCtrl )
|
||||
return;
|
||||
|
||||
wxPropertyGrid* paramGrid = dynamic_cast<wxPropertyGrid*>( textCtrl->GetParent() );
|
||||
if( !paramGrid )
|
||||
return;
|
||||
|
||||
wxPropertyGridManager* paramGridMgr =
|
||||
dynamic_cast<wxPropertyGridManager*>( paramGrid->GetParent() );
|
||||
if( !paramGridMgr )
|
||||
return;
|
||||
|
||||
#ifdef __WXGTK__
|
||||
// Workaround for wxWindow::Navigate() working differently on GTK. Same workaround is
|
||||
// in the WxWidgets source code.
|
||||
if( flags == wxNavigationKeyEvent::IsBackward )
|
||||
{
|
||||
if( wxWindow* sibling = paramGridMgr->GetPrevSibling() )
|
||||
{
|
||||
sibling->SetFocusFromKbd();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if( flags == wxNavigationKeyEvent::IsForward )
|
||||
{
|
||||
if( wxWindow* sibling = paramGridMgr->GetNextSibling() )
|
||||
{
|
||||
sibling->SetFocusFromKbd();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// We didn't find the sibling, so instead we try another workaround by by finding the notebook
|
||||
// we are in, and jumping out of it.
|
||||
for( wxWindow* window = paramGridMgr; window; window = window->GetParent() )
|
||||
{
|
||||
if( wxNotebook* notebook = dynamic_cast<wxNotebook*>( window ) )
|
||||
{
|
||||
if( flags == wxNavigationKeyEvent::IsBackward )
|
||||
{
|
||||
for( wxWindow* sibling = notebook->GetNextSibling();
|
||||
sibling;
|
||||
sibling = sibling->GetNextSibling() )
|
||||
{
|
||||
if( sibling->IsFocusable() )
|
||||
{
|
||||
sibling->SetFocusFromKbd();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( flags == wxNavigationKeyEvent::IsForward )
|
||||
{
|
||||
for( wxWindow* sibling = notebook->GetNextSibling();
|
||||
sibling;
|
||||
sibling = sibling->GetNextSibling() )
|
||||
{
|
||||
if( sibling->IsFocusable() )
|
||||
{
|
||||
sibling->SetFocusFromKbd();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
paramGridMgr->Navigate( flags );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void SIM_VALIDATOR::onKeyDown( wxKeyEvent& aEvent )
|
||||
{
|
||||
// Because wxPropertyGrid has special handling for the tab key, wxPropertyGrid::DedicateKey()
|
||||
// and wxPropertyGrid::AddActionTrigger() don't work for it. So instead we translate it to an
|
||||
// (up or down) arrow key, which has proper handling (select next or previous property) defined
|
||||
// by the aforementioned functions.
|
||||
|
||||
if( aEvent.GetKeyCode() == WXK_TAB )
|
||||
{
|
||||
// However, before that, if this is the first or last property, we instead want to navigate
|
||||
// to the next or previous widget.
|
||||
wxWindow* textCtrl = GetWindow();
|
||||
if( !textCtrl )
|
||||
{
|
||||
aEvent.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
wxPropertyGrid* paramGrid = dynamic_cast<wxPropertyGrid*>( textCtrl->GetParent() );
|
||||
if( !paramGrid )
|
||||
{
|
||||
aEvent.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
wxPropertyGridIterator it = paramGrid->GetIterator( wxPG_ITERATE_VISIBLE,
|
||||
paramGrid->GetSelection() );
|
||||
if( !it.AtEnd() )
|
||||
it.Next();
|
||||
|
||||
bool isFirst = paramGrid->GetSelection() == paramGrid->wxPropertyGridInterface::GetFirst();
|
||||
bool isLast = it.AtEnd();
|
||||
|
||||
if( isFirst && aEvent.ShiftDown() )
|
||||
{
|
||||
navigate( wxNavigationKeyEvent::IsBackward );
|
||||
return;
|
||||
}
|
||||
|
||||
if( isLast && !aEvent.ShiftDown() )
|
||||
{
|
||||
navigate( wxNavigationKeyEvent::IsForward );
|
||||
return;
|
||||
}
|
||||
|
||||
if( aEvent.GetModifiers() == wxMOD_SHIFT )
|
||||
{
|
||||
aEvent.m_shiftDown = false;
|
||||
aEvent.m_keyCode = WXK_UP;
|
||||
}
|
||||
else
|
||||
aEvent.m_keyCode = WXK_DOWN;
|
||||
}
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
wxBEGIN_EVENT_TABLE( SIM_BOOL_VALIDATOR, SIM_VALIDATOR )
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
|
||||
bool SIM_BOOL_VALIDATOR::Validate( wxWindow* aParent )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SIM_STRING_VALIDATOR::SIM_STRING_VALIDATOR( SIM_VALUE::TYPE aValueType,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation )
|
||||
: SIM_VALIDATOR(),
|
||||
m_valueType( aValueType ),
|
||||
m_notation( aNotation )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
wxObject* SIM_STRING_VALIDATOR::Clone() const
|
||||
{
|
||||
return new SIM_STRING_VALIDATOR( *this );
|
||||
}
|
||||
|
||||
|
||||
bool SIM_STRING_VALIDATOR::Validate( wxWindow* aParent )
|
||||
{
|
||||
if( !m_validatorWindow->IsEnabled() )
|
||||
return true;
|
||||
|
||||
wxTextEntry* const textEntry = getTextEntry();
|
||||
|
||||
if( !textEntry )
|
||||
return false;
|
||||
|
||||
return isValid( textEntry->GetValue() );
|
||||
}
|
||||
|
||||
|
||||
bool SIM_STRING_VALIDATOR::TransferToWindow()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SIM_STRING_VALIDATOR::TransferFromWindow()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SIM_STRING_VALIDATOR::isValid( const wxString& aString )
|
||||
{
|
||||
return SIM_VALUE_GRAMMAR::IsValid( aString.ToStdString(), m_valueType, m_notation );
|
||||
}
|
||||
|
||||
|
||||
wxTextEntry* SIM_STRING_VALIDATOR::getTextEntry()
|
||||
{
|
||||
if( !m_validatorWindow )
|
||||
return nullptr;
|
||||
|
||||
// Taken from wxTextValidator.
|
||||
|
||||
if( wxDynamicCast( m_validatorWindow, wxTextCtrl ) )
|
||||
return ( wxTextCtrl* ) m_validatorWindow;
|
||||
|
||||
if( wxDynamicCast( m_validatorWindow, wxComboBox ) )
|
||||
return ( wxComboBox* ) m_validatorWindow;
|
||||
|
||||
if( wxDynamicCast( m_validatorWindow, wxComboCtrl ) )
|
||||
return ( wxComboCtrl* ) m_validatorWindow;
|
||||
|
||||
wxFAIL_MSG(
|
||||
"SIM_STRING_VALIDATOR can only be used with wxTextCtrl, wxComboBox, or wxComboCtrl"
|
||||
);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
SIM_PROPERTY::SIM_PROPERTY( SIM_MODEL& aModel, int aParamIndex ) :
|
||||
m_model( aModel ),
|
||||
m_paramIndex( aParamIndex ),
|
||||
m_needsEval( false ),
|
||||
m_eval( EDA_UNITS::UNSCALED ),
|
||||
m_disabled( false )
|
||||
{
|
||||
}
|
||||
|
@ -269,9 +48,8 @@ void SIM_PROPERTY::Disable()
|
|||
|
||||
|
||||
SIM_BOOL_PROPERTY::SIM_BOOL_PROPERTY( const wxString& aLabel, const wxString& aName,
|
||||
SIM_MODEL& aModel,
|
||||
int aParamIndex )
|
||||
: wxBoolProperty( aLabel, aName ),
|
||||
SIM_MODEL& aModel, int aParamIndex ) :
|
||||
wxBoolProperty( aLabel, aName ),
|
||||
SIM_PROPERTY( aModel, aParamIndex )
|
||||
{
|
||||
auto simValue = dynamic_cast<SIM_VALUE_INST<bool>*>(
|
||||
|
@ -285,7 +63,7 @@ SIM_BOOL_PROPERTY::SIM_BOOL_PROPERTY( const wxString& aLabel, const wxString& aN
|
|||
|
||||
wxValidator* SIM_BOOL_PROPERTY::DoGetValidator() const
|
||||
{
|
||||
return new SIM_BOOL_VALIDATOR();
|
||||
return new SIM_VALIDATOR();
|
||||
}
|
||||
|
||||
|
||||
|
@ -309,11 +87,10 @@ void SIM_BOOL_PROPERTY::OnSetValue()
|
|||
|
||||
|
||||
SIM_STRING_PROPERTY::SIM_STRING_PROPERTY( const wxString& aLabel, const wxString& aName,
|
||||
SIM_MODEL& aModel,
|
||||
int aParamIndex,
|
||||
SIM_MODEL& aModel, int aParamIndex,
|
||||
SIM_VALUE::TYPE aValueType,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation )
|
||||
: wxStringProperty( aLabel, aName ),
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation ) :
|
||||
wxStringProperty( aLabel, aName ),
|
||||
SIM_PROPERTY( aModel, aParamIndex ),
|
||||
m_valueType( aValueType ),
|
||||
m_notation( aNotation )
|
||||
|
@ -322,9 +99,61 @@ SIM_STRING_PROPERTY::SIM_STRING_PROPERTY( const wxString& aLabel, const wxString
|
|||
}
|
||||
|
||||
|
||||
bool SIM_STRING_PROPERTY::OnEvent( wxPropertyGrid* propgrid, wxWindow* wnd_primary, wxEvent& event )
|
||||
{
|
||||
if( event.GetEventType() == wxEVT_SET_FOCUS )
|
||||
{
|
||||
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wnd_primary );
|
||||
|
||||
if( textEntry )
|
||||
{
|
||||
wxString oldStr = m_eval.OriginalText();
|
||||
|
||||
if( oldStr.length() && oldStr != textEntry->GetValue() )
|
||||
{
|
||||
SetValueInEvent( oldStr );
|
||||
textEntry->SetValue( oldStr );
|
||||
}
|
||||
|
||||
m_needsEval = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if( event.GetEventType() == wxEVT_KILL_FOCUS )
|
||||
{
|
||||
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wnd_primary );
|
||||
|
||||
if( textEntry && m_eval.Process( textEntry->GetValue() ) )
|
||||
{
|
||||
SetValueInEvent( m_eval.Result() );
|
||||
m_needsEval = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if( event.GetEventType() == wxEVT_KEY_DOWN )
|
||||
{
|
||||
wxKeyEvent& keyEvent = dynamic_cast<wxKeyEvent&>( event );
|
||||
wxPropertyGrid* propGrid = dynamic_cast<wxPropertyGrid*>( wnd_primary->GetParent() );
|
||||
|
||||
if( propGrid )
|
||||
{
|
||||
if( keyEvent.GetKeyCode() == WXK_TAB )
|
||||
{
|
||||
propGrid->CommitChangesFromEditor();
|
||||
|
||||
keyEvent.m_keyCode = keyEvent.ShiftDown() ? WXK_UP : WXK_DOWN;
|
||||
keyEvent.m_shiftDown = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
wxValidator* SIM_STRING_PROPERTY::DoGetValidator() const
|
||||
{
|
||||
return new SIM_STRING_VALIDATOR( m_valueType, m_notation );
|
||||
return new SIM_VALIDATOR();
|
||||
}
|
||||
|
||||
|
||||
|
@ -334,28 +163,18 @@ bool SIM_STRING_PROPERTY::StringToValue( wxVariant& aVariant, const wxString& aT
|
|||
if( m_disabled )
|
||||
return false;
|
||||
|
||||
wxString baseParamValue = m_model.GetBaseParam( m_paramIndex ).value->ToString();
|
||||
aVariant = aText;
|
||||
wxString evaledText;
|
||||
|
||||
// TODO: Don't use string comparison.
|
||||
if( m_model.GetBaseModel() && ( aText == "" || aText == baseParamValue ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
m_model.SetParamValue( m_paramIndex, "" ); // Nullify.
|
||||
}
|
||||
catch( const IO_ERROR& )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
aVariant = baseParamValue; // Use the inherited value (if it exists) if null.
|
||||
}
|
||||
if( m_needsEval && m_eval.Process( aText ) )
|
||||
evaledText = m_eval.Result();
|
||||
else
|
||||
{
|
||||
m_model.SetParamValue( m_paramIndex, std::string( aText.ToUTF8() ) );
|
||||
evaledText = aText;
|
||||
|
||||
wxString baseParamValue = m_model.GetBaseParam( m_paramIndex ).value->ToString();
|
||||
aVariant = evaledText;
|
||||
|
||||
m_model.SetParamValue( m_paramIndex, std::string( evaledText.ToUTF8() ) );
|
||||
aVariant = GetParam().value->ToString();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -373,12 +192,8 @@ static wxArrayString convertStringsToWx( const std::vector<std::string>& aString
|
|||
|
||||
|
||||
SIM_ENUM_PROPERTY::SIM_ENUM_PROPERTY( const wxString& aLabel, const wxString& aName,
|
||||
SIM_MODEL& aModel,
|
||||
int aParamIndex,
|
||||
SIM_VALUE::TYPE aValueType,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation )
|
||||
: wxEnumProperty( aLabel, aName,
|
||||
convertStringsToWx( aModel.GetParam( aParamIndex ).info.enumValues ) ),
|
||||
SIM_MODEL& aModel, int aParamIndex ) :
|
||||
wxEnumProperty( aLabel, aName, convertStringsToWx( aModel.GetParam( aParamIndex ).info.enumValues ) ),
|
||||
SIM_PROPERTY( aModel, aParamIndex )
|
||||
{
|
||||
auto it = std::find( GetParam().info.enumValues.begin(), GetParam().info.enumValues.end(),
|
||||
|
|
|
@ -31,51 +31,15 @@
|
|||
#include <wx/propgrid/props.h>
|
||||
|
||||
#include <sim/sim_model.h>
|
||||
#include "libeval/numeric_evaluator.h"
|
||||
|
||||
|
||||
class SIM_VALIDATOR : public wxValidator
|
||||
{
|
||||
private:
|
||||
void navigate( int flags );
|
||||
|
||||
void onKeyDown( wxKeyEvent& aEvent );
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
|
||||
class SIM_STRING_VALIDATOR : public SIM_VALIDATOR
|
||||
{
|
||||
public:
|
||||
SIM_STRING_VALIDATOR( SIM_VALUE::TYPE aValueType, SIM_VALUE_GRAMMAR::NOTATION aNotation );
|
||||
SIM_STRING_VALIDATOR( const SIM_STRING_VALIDATOR& aValidator ) = default;
|
||||
|
||||
wxObject* Clone() const override;
|
||||
|
||||
bool Validate( wxWindow* aParent ) override;
|
||||
bool TransferToWindow() override;
|
||||
bool TransferFromWindow() override;
|
||||
|
||||
private:
|
||||
bool isValid( const wxString& aString );
|
||||
|
||||
wxTextEntry* getTextEntry();
|
||||
|
||||
SIM_VALUE::TYPE m_valueType;
|
||||
SIM_VALUE_GRAMMAR::NOTATION m_notation;
|
||||
};
|
||||
|
||||
|
||||
class SIM_BOOL_VALIDATOR : public SIM_VALIDATOR
|
||||
{
|
||||
public:
|
||||
SIM_BOOL_VALIDATOR() : SIM_VALIDATOR() {}
|
||||
SIM_BOOL_VALIDATOR( const SIM_BOOL_VALIDATOR& aValidator ) = default;
|
||||
|
||||
bool Validate( wxWindow* aParent ) override;
|
||||
|
||||
private:
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
bool Validate( wxWindow* aParent ) override { return true; }
|
||||
bool TransferToWindow() override { return true; }
|
||||
bool TransferFromWindow() override { return true; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -91,7 +55,11 @@ public:
|
|||
protected:
|
||||
SIM_MODEL& m_model;
|
||||
int m_paramIndex;
|
||||
bool m_disabled; // If true, never access the models.
|
||||
|
||||
bool m_needsEval;
|
||||
mutable NUMERIC_EVALUATOR m_eval;
|
||||
|
||||
bool m_disabled; ///< If true, never access the models.
|
||||
};
|
||||
|
||||
|
||||
|
@ -124,6 +92,8 @@ public:
|
|||
bool StringToValue( wxVariant& aVariant, const wxString& aText, int aArgFlags = 0 )
|
||||
const override;
|
||||
|
||||
bool OnEvent( wxPropertyGrid* propgrid, wxWindow* wnd_primary, wxEvent& event ) override;
|
||||
|
||||
protected:
|
||||
SIM_VALUE::TYPE m_valueType;
|
||||
SIM_VALUE_GRAMMAR::NOTATION m_notation;
|
||||
|
@ -133,11 +103,8 @@ protected:
|
|||
class SIM_ENUM_PROPERTY : public wxEnumProperty, public SIM_PROPERTY
|
||||
{
|
||||
public:
|
||||
SIM_ENUM_PROPERTY( const wxString& aLabel, const wxString& aName,
|
||||
SIM_MODEL& aModel,
|
||||
int aParamIndex,
|
||||
SIM_VALUE::TYPE aValueType = SIM_VALUE::TYPE_FLOAT,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation = SIM_VALUE_GRAMMAR::NOTATION::SI );
|
||||
SIM_ENUM_PROPERTY( const wxString& aLabel, const wxString& aName, SIM_MODEL& aModel,
|
||||
int aParamIndex );
|
||||
|
||||
bool IntToValue( wxVariant& aVariant, int aNumber, int aArgFlags = 0 ) const override;
|
||||
};
|
||||
|
|
|
@ -482,7 +482,13 @@ bool SIM_VALUE_INT::FromString( const std::string& aString, NOTATION aNotation )
|
|||
template <>
|
||||
bool SIM_VALUE_FLOAT::FromString( const std::string& aString, NOTATION aNotation )
|
||||
{
|
||||
SIM_VALUE_PARSER::PARSE_RESULT parseResult = SIM_VALUE_PARSER::Parse( aString, aNotation );
|
||||
wxString buf( aString );
|
||||
|
||||
// Convert any entered decimal point separators to the one our PEGTL grammar expects
|
||||
buf.Replace( wxT( "," ), wxT( "." ) );
|
||||
|
||||
SIM_VALUE_PARSER::PARSE_RESULT parseResult = SIM_VALUE_PARSER::Parse( buf.ToStdString(),
|
||||
aNotation );
|
||||
m_value = std::nullopt;
|
||||
|
||||
if( !parseResult.isOk )
|
||||
|
@ -513,8 +519,7 @@ bool SIM_VALUE_FLOAT::FromString( const std::string& aString, NOTATION aNotation
|
|||
|
||||
|
||||
template <>
|
||||
bool SIM_VALUE_COMPLEX::FromString( const std::string& aString,
|
||||
NOTATION aNotation )
|
||||
bool SIM_VALUE_COMPLEX::FromString( const std::string& aString, NOTATION aNotation )
|
||||
{
|
||||
// TODO
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ struct SPICE_ITEM
|
|||
std::string baseModelName;
|
||||
std::string modelName;
|
||||
const SIM_MODEL* model = nullptr;
|
||||
const std::vector<SCH_FIELD>* fields = nullptr;
|
||||
std::vector<SCH_FIELD> fields;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -33,7 +33,12 @@ class SIM_LIBRARY_SPICE;
|
|||
class SPICE_LIBRARY_PARSER
|
||||
{
|
||||
public:
|
||||
SPICE_LIBRARY_PARSER( SIM_LIBRARY_SPICE& aLibrary ) : m_library( aLibrary ) {}
|
||||
SPICE_LIBRARY_PARSER( SIM_LIBRARY_SPICE& aLibrary ) :
|
||||
m_library( aLibrary )
|
||||
{};
|
||||
|
||||
virtual ~SPICE_LIBRARY_PARSER()
|
||||
{};
|
||||
|
||||
virtual void ReadFile( const std::string& aFilePath );
|
||||
|
||||
|
|
|
@ -866,6 +866,7 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent )
|
|||
{
|
||||
EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
|
||||
EDA_ITEM* item = selTool->GetNode( aPosition );
|
||||
SCH_SHEET_PATH& sheet = m_frame->GetCurrentSheet();
|
||||
|
||||
if( !item )
|
||||
return false;
|
||||
|
@ -879,10 +880,10 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent )
|
|||
std::vector<LIB_PIN*> pins = symbol->GetLibPins();
|
||||
|
||||
SIM_LIB_MGR mgr( m_frame->Prj() );
|
||||
SIM_MODEL& model = mgr.CreateModel( *symbol ).model;
|
||||
SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol ).model;
|
||||
|
||||
SPICE_ITEM spiceItem;
|
||||
spiceItem.refName = std::string( symbol->GetRef( &m_frame->GetCurrentSheet() ).ToUTF8() );
|
||||
spiceItem.refName = std::string( symbol->GetRef( &sheet ).ToUTF8() );
|
||||
std::vector<std::string> currentNames =
|
||||
model.SpiceGenerator().CurrentNames( spiceItem );
|
||||
|
||||
|
|
|
@ -76,7 +76,6 @@ Supported units are millimeters (mm), Mil (mil) and inch (")
|
|||
// This namespace is used for the lemon parser
|
||||
namespace numEval
|
||||
{
|
||||
|
||||
struct TokenType
|
||||
{
|
||||
union
|
||||
|
@ -93,7 +92,7 @@ namespace numEval
|
|||
|
||||
class NUMERIC_EVALUATOR
|
||||
{
|
||||
enum class Unit { Invalid, MM, CM, Inch, Mil, Degrees };
|
||||
enum class Unit { Invalid, MM, CM, Inch, Mil, Degrees, SI };
|
||||
|
||||
public:
|
||||
NUMERIC_EVALUATOR( EDA_UNITS aUnits );
|
||||
|
@ -162,16 +161,19 @@ private:
|
|||
struct TokenStat
|
||||
{
|
||||
TokenStat() :
|
||||
input( nullptr ), token( nullptr ), inputLen( 0 ), outputLen( 0 ), pos( 0 )
|
||||
{ /* empty */ }
|
||||
input( nullptr ),
|
||||
token( nullptr ),
|
||||
inputLen( 0 ),
|
||||
outputLen( 0 ),
|
||||
pos( 0 )
|
||||
{};
|
||||
|
||||
const char* input; // current input string ("var=4")
|
||||
char* token; // output token ("var", type:VAR; "4", type:VALUE)
|
||||
size_t inputLen; // strlen(input)
|
||||
size_t outputLen; // At least 64, up to input length
|
||||
size_t pos; // current index
|
||||
}
|
||||
m_token;
|
||||
} m_token;
|
||||
|
||||
char m_localeDecimalSeparator;
|
||||
|
||||
|
|
|
@ -36,8 +36,10 @@
|
|||
#include <string_utils.h>
|
||||
|
||||
|
||||
PCB_PROPERTIES_PANEL::PCB_PROPERTIES_PANEL( wxWindow* aParent, PCB_EDIT_FRAME* aFrame )
|
||||
: PROPERTIES_PANEL( aParent, aFrame ), m_frame( aFrame ), m_propMgr( PROPERTY_MANAGER::Instance() )
|
||||
PCB_PROPERTIES_PANEL::PCB_PROPERTIES_PANEL( wxWindow* aParent, PCB_EDIT_FRAME* aFrame ) :
|
||||
PROPERTIES_PANEL( aParent, aFrame ),
|
||||
m_frame( aFrame ),
|
||||
m_propMgr( PROPERTY_MANAGER::Instance() )
|
||||
{
|
||||
m_propMgr.Rebuild();
|
||||
bool found = false;
|
||||
|
|
Loading…
Reference in New Issue