2016-08-11 12:41:40 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
2022-02-09 00:45:04 +00:00
|
|
|
* Copyright (C) 2022 Mikolaj Wielgus
|
|
|
|
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
|
2016-08-11 12:41:40 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
2016-08-11 12:41:43 +00:00
|
|
|
* as published by the Free Software Foundation; either version 3
|
2016-08-11 12:41:40 +00:00
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, you may find one here:
|
2016-08-11 12:41:43 +00:00
|
|
|
* https://www.gnu.org/licenses/gpl-3.0.html
|
|
|
|
* or you may search the http://www.gnu.org website for the version 3 license,
|
2016-08-11 12:41:40 +00:00
|
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
2022-04-12 14:37:06 +00:00
|
|
|
#include <dialog_sim_model.h>
|
2022-03-09 01:40:59 +00:00
|
|
|
#include <sim/sim_property.h>
|
2022-04-01 04:30:50 +00:00
|
|
|
#include <sim/sim_library_spice.h>
|
2022-03-09 01:40:59 +00:00
|
|
|
#include <widgets/wx_grid.h>
|
|
|
|
#include <kiplatform/ui.h>
|
2016-08-11 12:41:56 +00:00
|
|
|
#include <confirm.h>
|
2022-03-09 01:40:59 +00:00
|
|
|
#include <locale_io.h>
|
2022-04-01 04:30:50 +00:00
|
|
|
#include <wx/filedlg.h>
|
2016-08-11 12:41:40 +00:00
|
|
|
|
2022-04-12 14:37:06 +00:00
|
|
|
using TYPE = SIM_VALUE::TYPE;
|
2022-02-21 03:58:31 +00:00
|
|
|
using CATEGORY = SIM_MODEL::PARAM::CATEGORY;
|
|
|
|
|
2018-09-22 14:05:32 +00:00
|
|
|
|
2022-04-12 14:37:06 +00:00
|
|
|
template class DIALOG_SIM_MODEL<SCH_FIELD>;
|
|
|
|
template class DIALOG_SIM_MODEL<LIB_FIELD>;
|
2018-09-22 14:05:32 +00:00
|
|
|
|
2022-02-09 00:45:04 +00:00
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
DIALOG_SIM_MODEL<T>::DIALOG_SIM_MODEL( wxWindow* aParent, SCH_SYMBOL& aSymbol,
|
2022-02-21 03:58:31 +00:00
|
|
|
std::vector<T>& aFields )
|
2022-04-12 14:37:06 +00:00
|
|
|
: DIALOG_SIM_MODEL_BASE( aParent ),
|
2022-02-09 00:45:04 +00:00
|
|
|
m_symbol( aSymbol ),
|
2022-02-21 03:58:31 +00:00
|
|
|
m_fields( aFields ),
|
2022-04-01 04:30:50 +00:00
|
|
|
m_library( std::make_shared<SIM_LIBRARY_SPICE>() ),
|
|
|
|
m_prevModel( nullptr ),
|
2022-02-21 03:58:31 +00:00
|
|
|
m_firstCategory( nullptr )
|
2018-09-22 14:05:32 +00:00
|
|
|
{
|
2022-04-12 14:37:06 +00:00
|
|
|
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
|
2016-08-11 12:41:40 +00:00
|
|
|
{
|
2022-04-12 14:37:06 +00:00
|
|
|
m_models.push_back( SIM_MODEL::Create( type, m_symbol.GetAllPins().size() ) );
|
2016-08-11 12:41:40 +00:00
|
|
|
|
2022-04-12 14:37:06 +00:00
|
|
|
SIM_MODEL::DEVICE_TYPE deviceType = SIM_MODEL::TypeInfo( type ).deviceType;
|
|
|
|
|
|
|
|
if( !m_curModelTypeOfDeviceType.count( deviceType ) )
|
|
|
|
m_curModelTypeOfDeviceType[deviceType] = type;
|
2022-01-23 17:23:22 +00:00
|
|
|
}
|
2016-08-11 12:41:40 +00:00
|
|
|
|
|
|
|
|
2022-02-09 00:45:04 +00:00
|
|
|
m_typeChoice->Clear();
|
2020-03-23 16:49:21 +00:00
|
|
|
|
2022-02-21 03:58:31 +00:00
|
|
|
for( SIM_MODEL::DEVICE_TYPE deviceType : SIM_MODEL::DEVICE_TYPE_ITERATOR() )
|
|
|
|
m_deviceTypeChoice->Append( SIM_MODEL::DeviceTypeInfo( deviceType ).description );
|
|
|
|
|
2020-03-23 16:49:21 +00:00
|
|
|
|
2022-02-09 00:45:04 +00:00
|
|
|
m_scintillaTricks = std::make_unique<SCINTILLA_TRICKS>( m_codePreview, wxT( "{}" ), false );
|
2016-08-11 12:41:40 +00:00
|
|
|
|
2022-04-12 14:37:06 +00:00
|
|
|
m_paramGridMgr->Bind( wxEVT_PG_SELECTED, &DIALOG_SIM_MODEL::onSelectionChange, this );
|
2022-03-09 01:40:59 +00:00
|
|
|
|
|
|
|
m_paramGrid->SetValidationFailureBehavior( wxPG_VFB_STAY_IN_PROPERTY
|
|
|
|
| wxPG_VFB_BEEP
|
|
|
|
| wxPG_VFB_MARK_CELL );
|
|
|
|
|
|
|
|
m_paramGrid->SetColumnProportion( static_cast<int>( PARAM_COLUMN::DESCRIPTION ), 50 );
|
|
|
|
m_paramGrid->SetColumnProportion( static_cast<int>( PARAM_COLUMN::VALUE ), 18 );
|
|
|
|
m_paramGrid->SetColumnProportion( static_cast<int>( PARAM_COLUMN::UNIT ), 10 );
|
|
|
|
m_paramGrid->SetColumnProportion( static_cast<int>( PARAM_COLUMN::DEFAULT ), 12 );
|
|
|
|
m_paramGrid->SetColumnProportion( static_cast<int>( PARAM_COLUMN::TYPE ), 10 );
|
|
|
|
|
|
|
|
if( wxPropertyGrid* grid = m_paramGrid->GetGrid() )
|
|
|
|
{
|
|
|
|
grid->AddActionTrigger( wxPG_ACTION_EDIT, WXK_RETURN );
|
|
|
|
grid->DedicateKey( WXK_RETURN );
|
|
|
|
grid->AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_RETURN );
|
|
|
|
|
|
|
|
grid->DedicateKey( WXK_UP );
|
|
|
|
grid->DedicateKey( WXK_DOWN );
|
|
|
|
|
|
|
|
// Doesn't work for some reason.
|
|
|
|
//grid->DedicateKey( WXK_TAB );
|
|
|
|
//grid->AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_TAB );
|
|
|
|
//grid->AddActionTrigger( wxPG_ACTION_PREV_PROPERTY, WXK_TAB, wxMOD_SHIFT );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
wxFAIL;
|
|
|
|
|
2022-02-09 00:45:04 +00:00
|
|
|
Layout();
|
2016-08-11 12:41:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-02-09 00:45:04 +00:00
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
bool DIALOG_SIM_MODEL<T>::TransferDataToWindow()
|
2022-01-23 17:23:22 +00:00
|
|
|
{
|
2022-04-12 14:37:06 +00:00
|
|
|
wxString libraryFilename = SIM_MODEL::GetFieldValue( &m_fields,
|
|
|
|
SIM_LIBRARY_SPICE::LIBRARY_FIELD );
|
2022-01-23 17:23:22 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
if( !libraryFilename.IsEmpty() )
|
|
|
|
{
|
|
|
|
// The model is sourced from a library, optionally with instance overrides.
|
|
|
|
loadLibrary( libraryFilename );
|
2022-01-23 17:23:22 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
// Must be set before curModel() is used since the latter checks the combobox value.
|
2022-04-12 14:37:06 +00:00
|
|
|
m_modelNameCombobox->SetStringSelection(
|
|
|
|
SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY_SPICE::NAME_FIELD ) );
|
2022-01-23 17:23:22 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
m_overrideCheckbox->SetValue( curModel().HasNonPrincipalOverrides() );
|
2016-08-11 12:42:09 +00:00
|
|
|
}
|
2022-04-01 04:30:50 +00:00
|
|
|
else
|
2016-08-11 12:41:40 +00:00
|
|
|
{
|
2022-04-01 04:30:50 +00:00
|
|
|
// The model is sourced from the instance.
|
|
|
|
SIM_MODEL::TYPE type = SIM_MODEL::ReadTypeFromFields( m_fields );
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
m_models.at( static_cast<int>( SIM_MODEL::ReadTypeFromFields( m_fields ) ) )
|
|
|
|
= SIM_MODEL::Create( m_symbol.GetAllPins().size(), m_fields );
|
|
|
|
}
|
2022-04-12 14:37:06 +00:00
|
|
|
catch( const KI_PARAM_ERROR& e )
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
|
|
|
DisplayErrorMessage( this, e.What() );
|
2022-04-12 14:37:06 +00:00
|
|
|
return DIALOG_SIM_MODEL_BASE::TransferDataToWindow();
|
2022-04-01 04:30:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
m_curModelType = type;
|
2016-08-11 12:41:40 +00:00
|
|
|
}
|
2016-08-11 12:41:56 +00:00
|
|
|
|
2022-02-09 00:45:04 +00:00
|
|
|
updateWidgets();
|
2016-08-11 12:41:56 +00:00
|
|
|
|
2022-04-12 14:37:06 +00:00
|
|
|
return DIALOG_SIM_MODEL_BASE::TransferDataToWindow();
|
2016-08-11 12:41:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
bool DIALOG_SIM_MODEL<T>::TransferDataFromWindow()
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
2022-04-12 14:37:06 +00:00
|
|
|
if( !DIALOG_SIM_MODEL_BASE::TransferDataFromWindow() )
|
2022-04-01 04:30:50 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if( m_useLibraryModelRadioButton->GetValue() )
|
|
|
|
{
|
2022-04-12 14:37:06 +00:00
|
|
|
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY_SPICE::NAME_FIELD,
|
|
|
|
m_modelNameCombobox->GetValue() );
|
|
|
|
|
|
|
|
wxString path = m_library->GetFilePath();
|
|
|
|
wxFileName fn( path );
|
|
|
|
|
|
|
|
if( fn.MakeRelativeTo( Prj().GetProjectPath() ) && !fn.GetFullPath().StartsWith( ".." ) )
|
|
|
|
path = fn.GetFullPath();
|
|
|
|
|
|
|
|
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY_SPICE::LIBRARY_FIELD, path );
|
2022-04-01 04:30:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
curModel().WriteFields( m_fields );
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-02-09 00:45:04 +00:00
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::updateWidgets()
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
|
|
|
updateModelParamsTab();
|
|
|
|
updateModelCodeTab();
|
|
|
|
updatePinAssignmentsTab();
|
2022-04-01 04:30:50 +00:00
|
|
|
|
|
|
|
m_prevModel = &curModel();
|
2022-03-09 01:40:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::updateModelParamsTab()
|
2016-08-11 12:41:40 +00:00
|
|
|
{
|
2022-04-01 04:30:50 +00:00
|
|
|
if( &curModel() != m_prevModel )
|
2016-08-11 12:41:40 +00:00
|
|
|
{
|
2022-04-01 04:30:50 +00:00
|
|
|
SIM_MODEL::DEVICE_TYPE deviceType = SIM_MODEL::TypeInfo( curModel().GetType() ).deviceType;
|
|
|
|
m_deviceTypeChoice->SetSelection( static_cast<int>( deviceType ) );
|
|
|
|
|
|
|
|
m_typeChoice->Clear();
|
|
|
|
|
|
|
|
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
|
2016-08-11 12:41:40 +00:00
|
|
|
{
|
2022-04-01 04:30:50 +00:00
|
|
|
if( SIM_MODEL::TypeInfo( type ).deviceType == deviceType )
|
|
|
|
{
|
|
|
|
wxString description = SIM_MODEL::TypeInfo( type ).description;
|
2017-10-26 17:54:53 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
if( !description.IsEmpty() )
|
|
|
|
m_typeChoice->Append( description );
|
2017-10-26 17:54:53 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
if( type == curModel().GetType() )
|
|
|
|
m_typeChoice->SetSelection( m_typeChoice->GetCount() - 1 );
|
|
|
|
}
|
2016-08-11 12:41:40 +00:00
|
|
|
}
|
|
|
|
|
2019-11-21 10:28:43 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
// This wxPropertyGridManager column and header stuff has to be here because it segfaults in
|
|
|
|
// the constructor.
|
|
|
|
|
|
|
|
m_paramGridMgr->SetColumnCount( static_cast<int>( PARAM_COLUMN::END_ ) );
|
2018-05-03 09:58:13 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGridMgr->SetColumnTitle( static_cast<int>( PARAM_COLUMN::UNIT ), "Unit" );
|
|
|
|
m_paramGridMgr->SetColumnTitle( static_cast<int>( PARAM_COLUMN::DEFAULT ), "Default" );
|
|
|
|
m_paramGridMgr->SetColumnTitle( static_cast<int>( PARAM_COLUMN::TYPE ), "Type" );
|
2017-10-26 17:54:53 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGridMgr->ShowHeader();
|
2022-02-21 03:58:31 +00:00
|
|
|
|
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGrid->Clear();
|
2022-02-21 03:58:31 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
m_firstCategory = m_paramGrid->Append( new wxPropertyCategory( "DC" ) );
|
|
|
|
m_paramGrid->HideProperty( "DC" );
|
2022-02-21 03:58:31 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGrid->Append( new wxPropertyCategory( "Temperature" ) );
|
|
|
|
m_paramGrid->HideProperty( "Temperature" );
|
2022-02-21 03:58:31 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGrid->Append( new wxPropertyCategory( "Noise" ) );
|
|
|
|
m_paramGrid->HideProperty( "Noise" );
|
2019-01-10 05:42:14 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGrid->Append( new wxPropertyCategory( "Distributed Quantities" ) );
|
|
|
|
m_paramGrid->HideProperty( "Distributed Quantities" );
|
2019-01-10 05:42:14 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGrid->Append( new wxPropertyCategory( "Geometry" ) );
|
|
|
|
m_paramGrid->HideProperty( "Geometry" );
|
2022-02-21 03:58:31 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGrid->Append( new wxPropertyCategory( "Limiting Values" ) );
|
|
|
|
m_paramGrid->HideProperty( "Limiting Values" );
|
2022-02-21 03:58:31 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGrid->Append( new wxPropertyCategory( "Advanced" ) );
|
|
|
|
m_paramGrid->HideProperty( "Advanced" );
|
|
|
|
|
|
|
|
m_paramGrid->Append( new wxPropertyCategory( "Flags" ) );
|
|
|
|
m_paramGrid->HideProperty( "Flags" );
|
|
|
|
|
|
|
|
for( int i = 0; i < curModel().GetParamCount(); ++i )
|
|
|
|
addParamPropertyIfRelevant( i );
|
|
|
|
|
|
|
|
m_paramGrid->CollapseAll();
|
|
|
|
}
|
2022-02-21 03:58:31 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
// Either enable all properties or disable all except the principal ones.
|
|
|
|
for( wxPropertyGridIterator it = m_paramGrid->GetIterator(); !it.AtEnd(); ++it )
|
|
|
|
{
|
|
|
|
SIM_PROPERTY* prop = dynamic_cast<SIM_PROPERTY*>( *it );
|
2022-02-21 03:58:31 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
if( !prop ) // Not all properties are SIM_PROPERTY yet. TODO.
|
|
|
|
continue;
|
2022-02-21 03:58:31 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
// Model values other than the currently edited value may have changed. Update them.
|
|
|
|
// This feature is called "autofill" and present only in certain models. Don't do it for
|
|
|
|
// models that don't have it for performance reasons.
|
|
|
|
if( curModel().HasAutofill() )
|
|
|
|
prop->SetValueFromString( prop->GetParam().value->ToString() );
|
2022-02-21 03:58:31 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
// Most of the values are disabled when the override checkbox is unchecked.
|
|
|
|
prop->Enable( m_useInstanceModelRadioButton->GetValue()
|
|
|
|
|| prop->GetParam().info.category == CATEGORY::PRINCIPAL
|
|
|
|
|| m_overrideCheckbox->GetValue() );
|
|
|
|
}
|
2016-08-11 12:41:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-02-09 00:45:04 +00:00
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::updateModelCodeTab()
|
2016-08-11 12:41:40 +00:00
|
|
|
{
|
2022-04-01 04:30:50 +00:00
|
|
|
wxString modelName = m_modelNameCombobox->GetStringSelection();
|
|
|
|
|
|
|
|
if( m_useInstanceModelRadioButton->GetValue() || modelName.IsEmpty() )
|
|
|
|
modelName = m_fields.at( REFERENCE_FIELD ).GetText();
|
|
|
|
|
|
|
|
m_codePreview->SetText( curModel().GenerateSpicePreview( modelName ) );
|
2022-03-09 01:40:59 +00:00
|
|
|
}
|
2016-08-19 15:33:26 +00:00
|
|
|
|
2016-08-11 12:41:40 +00:00
|
|
|
|
2022-03-09 01:40:59 +00:00
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::updatePinAssignmentsTab()
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
2022-04-01 04:30:50 +00:00
|
|
|
if( &curModel() == m_prevModel )
|
|
|
|
return;
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
m_pinAssignmentsGrid->ClearRows();
|
2022-03-09 01:40:59 +00:00
|
|
|
std::vector<SCH_PIN*> pinList = m_symbol.GetAllPins();
|
|
|
|
|
|
|
|
m_pinAssignmentsGrid->AppendRows( static_cast<int>( pinList.size() ) );
|
|
|
|
|
|
|
|
for( int i = 0; i < m_pinAssignmentsGrid->GetNumberRows(); ++i )
|
|
|
|
{
|
|
|
|
wxString symbolPinString = getSymbolPinString( i + 1 );
|
|
|
|
|
|
|
|
m_pinAssignmentsGrid->SetReadOnly( i, static_cast<int>( PIN_COLUMN::SYMBOL ) );
|
|
|
|
m_pinAssignmentsGrid->SetCellValue( i, static_cast<int>( PIN_COLUMN::SYMBOL ),
|
|
|
|
symbolPinString );
|
|
|
|
|
|
|
|
// Using `new` here shouldn't cause a memory leak because `SetCellEditor()` calls
|
|
|
|
// `DecRef()` on its last editor.
|
|
|
|
m_pinAssignmentsGrid->SetCellEditor( i, static_cast<int>( PIN_COLUMN::MODEL ),
|
|
|
|
new wxGridCellChoiceEditor() );
|
|
|
|
m_pinAssignmentsGrid->SetCellValue( i, static_cast<int>( PIN_COLUMN::MODEL ),
|
|
|
|
"Not Connected" );
|
|
|
|
}
|
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
for( int i = 0; i < curModel().GetPinCount(); ++i )
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
2022-04-01 04:30:50 +00:00
|
|
|
int symbolPinNumber = curModel().GetPin( i ).symbolPinNumber;
|
2022-03-09 01:40:59 +00:00
|
|
|
|
|
|
|
if( symbolPinNumber == SIM_MODEL::PIN::NOT_CONNECTED )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
wxString modelPinString = getModelPinString( i + 1 );
|
|
|
|
wxArrayString choices;
|
|
|
|
|
|
|
|
m_pinAssignmentsGrid->SetCellValue( symbolPinNumber - 1,
|
|
|
|
static_cast<int>( PIN_COLUMN::MODEL ),
|
|
|
|
modelPinString );
|
|
|
|
}
|
|
|
|
|
|
|
|
updatePinAssignmentsGridEditors();
|
|
|
|
|
|
|
|
// TODO: Show a preview of the symbol with the pin numbers shown.
|
|
|
|
// TODO: Maybe show a preview of the code for subcircuits and code models.
|
2016-08-11 12:41:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-02-09 00:45:04 +00:00
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::updatePinAssignmentsGridEditors()
|
2016-08-11 12:41:40 +00:00
|
|
|
{
|
2022-03-09 01:40:59 +00:00
|
|
|
wxString modelPinChoicesString = "";
|
|
|
|
bool isFirst = true;
|
2016-08-19 15:33:26 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
for( int i = 0; i < curModel().GetPinCount(); ++i )
|
2017-10-26 21:59:56 +00:00
|
|
|
{
|
2022-04-01 04:30:50 +00:00
|
|
|
const SIM_MODEL::PIN& modelPin = curModel().GetPin( i );
|
2022-03-09 01:40:59 +00:00
|
|
|
int modelPinNumber = static_cast<int>( i + 1 );
|
|
|
|
|
|
|
|
if( modelPin.symbolPinNumber != SIM_MODEL::PIN::NOT_CONNECTED )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if( isFirst )
|
2022-02-09 00:45:04 +00:00
|
|
|
{
|
2022-03-09 01:40:59 +00:00
|
|
|
modelPinChoicesString << getModelPinString( modelPinNumber );
|
|
|
|
isFirst = false;
|
2022-02-09 00:45:04 +00:00
|
|
|
}
|
2022-03-09 01:40:59 +00:00
|
|
|
else
|
|
|
|
modelPinChoicesString << "," << getModelPinString( modelPinNumber );
|
2017-10-26 21:59:56 +00:00
|
|
|
}
|
2020-03-23 16:49:21 +00:00
|
|
|
|
2022-03-09 01:40:59 +00:00
|
|
|
if( !isFirst )
|
|
|
|
modelPinChoicesString << ",";
|
|
|
|
|
|
|
|
modelPinChoicesString << "Not Connected";
|
|
|
|
|
|
|
|
for( int i = 0; i < m_pinAssignmentsGrid->GetNumberRows(); ++i )
|
|
|
|
{
|
|
|
|
wxGridCellChoiceEditor* editor = static_cast<wxGridCellChoiceEditor*>(
|
|
|
|
m_pinAssignmentsGrid->GetCellEditor( i, static_cast<int>( PIN_COLUMN::MODEL ) ) );
|
|
|
|
|
|
|
|
if( !editor )
|
|
|
|
{
|
|
|
|
// Shouldn't happen.
|
|
|
|
wxFAIL_MSG( "Grid cell editor is null" );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
wxString curModelPinString = m_pinAssignmentsGrid->GetCellValue(
|
|
|
|
i, static_cast<int>( PIN_COLUMN::MODEL ) );
|
|
|
|
|
|
|
|
if( curModelPinString == "Not Connected" )
|
|
|
|
editor->SetParameters( modelPinChoicesString );
|
|
|
|
else
|
|
|
|
editor->SetParameters( curModelPinString + "," + modelPinChoicesString );
|
|
|
|
|
|
|
|
}
|
2020-03-23 16:49:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-02-09 00:45:04 +00:00
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::loadLibrary( const wxString& aFilePath )
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
2022-04-12 14:37:06 +00:00
|
|
|
m_library->ReadFile( Prj().AbsolutePath( aFilePath ) );
|
|
|
|
m_libraryPathInput->SetValue( aFilePath );
|
2022-04-01 04:30:50 +00:00
|
|
|
|
|
|
|
m_libraryModels.clear();
|
|
|
|
for( const SIM_MODEL& baseModel : m_library->GetModels() )
|
2022-04-12 14:37:06 +00:00
|
|
|
m_libraryModels.push_back( SIM_MODEL::Create( baseModel, m_symbol.GetAllPins().size(),
|
|
|
|
m_fields ) );
|
2022-04-01 04:30:50 +00:00
|
|
|
|
|
|
|
m_modelNameCombobox->Clear();
|
|
|
|
for( const wxString& name : m_library->GetModelNames() )
|
|
|
|
m_modelNameCombobox->Append( name );
|
|
|
|
|
|
|
|
m_useLibraryModelRadioButton->SetValue( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::addParamPropertyIfRelevant( int aParamIndex )
|
2022-02-21 03:58:31 +00:00
|
|
|
{
|
2022-04-01 04:30:50 +00:00
|
|
|
if( curModel().GetParam( aParamIndex ).info.dir == SIM_MODEL::PARAM::DIR::OUT )
|
2022-02-21 03:58:31 +00:00
|
|
|
return;
|
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
switch( curModel().GetParam( aParamIndex ).info.category )
|
2022-02-21 03:58:31 +00:00
|
|
|
{
|
|
|
|
case CATEGORY::DC:
|
|
|
|
m_paramGrid->HideProperty( "DC", false );
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGrid->AppendIn( "DC", newParamProperty( aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CATEGORY::CAPACITANCE:
|
|
|
|
m_paramGrid->HideProperty( "Capacitance", false );
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGrid->AppendIn( "Capacitance", newParamProperty( aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CATEGORY::TEMPERATURE:
|
|
|
|
m_paramGrid->HideProperty( "Temperature", false );
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGrid->AppendIn( "Temperature", newParamProperty( aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CATEGORY::NOISE:
|
|
|
|
m_paramGrid->HideProperty( "Noise", false );
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGrid->AppendIn( "Noise", newParamProperty( aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CATEGORY::DISTRIBUTED_QUANTITIES:
|
|
|
|
m_paramGrid->HideProperty( "Distributed Quantities", false );
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGrid->AppendIn( "Distributed Quantities", newParamProperty( aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CATEGORY::GEOMETRY:
|
|
|
|
m_paramGrid->HideProperty( "Geometry", false );
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGrid->AppendIn( "Geometry", newParamProperty( aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CATEGORY::LIMITING_VALUES:
|
|
|
|
m_paramGrid->HideProperty( "Limiting Values", false );
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGrid->AppendIn( "Limiting Values", newParamProperty( aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CATEGORY::ADVANCED:
|
|
|
|
m_paramGrid->HideProperty( "Advanced", false );
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGrid->AppendIn( "Advanced", newParamProperty( aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CATEGORY::FLAGS:
|
|
|
|
m_paramGrid->HideProperty( "Flags", false );
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGrid->AppendIn( "Flags", newParamProperty( aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGrid->Insert( m_firstCategory, newParamProperty( aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CATEGORY::INITIAL_CONDITIONS:
|
|
|
|
case CATEGORY::SUPERFLUOUS:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
wxPGProperty* DIALOG_SIM_MODEL<T>::newParamProperty( int aParamIndex ) const
|
2017-10-26 17:54:53 +00:00
|
|
|
{
|
2022-04-01 04:30:50 +00:00
|
|
|
const SIM_MODEL::PARAM& param = curModel().GetParam( aParamIndex );
|
2022-04-12 14:37:06 +00:00
|
|
|
wxString paramDescription;
|
|
|
|
|
|
|
|
if( !param.info.description.IsEmpty() )
|
|
|
|
paramDescription = wxString::Format( "%s (%s)",
|
|
|
|
param.info.description,
|
|
|
|
param.info.name );
|
|
|
|
else
|
|
|
|
paramDescription = wxString::Format( "%s", param.info.name );
|
|
|
|
|
2022-02-21 03:58:31 +00:00
|
|
|
wxPGProperty* prop = nullptr;
|
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
switch( param.info.type )
|
2022-02-21 03:58:31 +00:00
|
|
|
{
|
|
|
|
case TYPE::INT:
|
2022-04-01 04:30:50 +00:00
|
|
|
prop = new SIM_PROPERTY( paramDescription, param.info.name, m_library, curModelSharedPtr(),
|
2022-04-12 14:37:06 +00:00
|
|
|
aParamIndex, SIM_VALUE::TYPE::INT );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TYPE::FLOAT:
|
2022-04-01 04:30:50 +00:00
|
|
|
prop = new SIM_PROPERTY( paramDescription, param.info.name, m_library, curModelSharedPtr(),
|
2022-04-12 14:37:06 +00:00
|
|
|
aParamIndex, SIM_VALUE::TYPE::FLOAT );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TYPE::BOOL:
|
2022-04-01 04:30:50 +00:00
|
|
|
prop = new wxBoolProperty( paramDescription, param.info.name );
|
2022-02-21 03:58:31 +00:00
|
|
|
prop->SetAttribute( wxPG_BOOL_USE_CHECKBOX, true );
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2022-04-01 04:30:50 +00:00
|
|
|
prop = new wxStringProperty( paramDescription, param.info.name );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
prop->SetAttribute( wxPG_ATTR_UNITS, param.info.unit );
|
2022-02-21 03:58:31 +00:00
|
|
|
|
2022-03-09 01:40:59 +00:00
|
|
|
// Legacy due to the way we extracted the parameters from Ngspice.
|
2022-04-01 04:30:50 +00:00
|
|
|
if( param.isOtherVariant )
|
|
|
|
prop->SetCell( 3, param.info.defaultValueOfOtherVariant );
|
2022-02-21 03:58:31 +00:00
|
|
|
else
|
2022-04-01 04:30:50 +00:00
|
|
|
prop->SetCell( 3, param.info.defaultValue );
|
2022-02-21 03:58:31 +00:00
|
|
|
|
|
|
|
wxString typeStr;
|
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
switch( param.info.type )
|
2022-02-21 03:58:31 +00:00
|
|
|
{
|
|
|
|
case TYPE::BOOL: typeStr = wxString( "Bool" ); break;
|
2022-03-09 01:40:59 +00:00
|
|
|
case TYPE::INT: typeStr = wxString( "Int" ); break;
|
2022-02-21 03:58:31 +00:00
|
|
|
case TYPE::FLOAT: typeStr = wxString( "Float" ); break;
|
|
|
|
case TYPE::COMPLEX: typeStr = wxString( "Complex" ); break;
|
|
|
|
case TYPE::STRING: typeStr = wxString( "String" ); break;
|
|
|
|
case TYPE::BOOL_VECTOR: typeStr = wxString( "Bool Vector" ); break;
|
|
|
|
case TYPE::INT_VECTOR: typeStr = wxString( "Int Vector" ); break;
|
|
|
|
case TYPE::FLOAT_VECTOR: typeStr = wxString( "Float Vector" ); break;
|
|
|
|
case TYPE::COMPLEX_VECTOR: typeStr = wxString( "Complex Vector" ); break;
|
|
|
|
}
|
|
|
|
|
2022-03-09 01:40:59 +00:00
|
|
|
prop->SetCell( static_cast<int>( PARAM_COLUMN::TYPE ), typeStr );
|
2022-02-21 03:58:31 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
if( m_useLibraryModelRadioButton->GetValue()
|
|
|
|
&& !m_overrideCheckbox->GetValue()
|
|
|
|
&& param.info.category != SIM_MODEL::PARAM::CATEGORY::PRINCIPAL )
|
|
|
|
{
|
|
|
|
prop->Enable( false );
|
|
|
|
}
|
|
|
|
|
2022-02-21 03:58:31 +00:00
|
|
|
return prop;
|
2017-10-26 17:54:53 +00:00
|
|
|
}
|
2022-03-09 01:40:59 +00:00
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
SIM_MODEL& DIALOG_SIM_MODEL<T>::curModel() const
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
2022-04-01 04:30:50 +00:00
|
|
|
return *curModelSharedPtr();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
std::shared_ptr<SIM_MODEL> DIALOG_SIM_MODEL<T>::curModelSharedPtr() const
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
|
|
|
if( m_useLibraryModelRadioButton->GetValue()
|
|
|
|
&& m_modelNameCombobox->GetSelection() != wxNOT_FOUND )
|
|
|
|
{
|
|
|
|
return m_libraryModels.at( m_modelNameCombobox->GetSelection() );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return m_models.at( static_cast<int>( m_curModelType ) );
|
2022-03-09 01:40:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
wxString DIALOG_SIM_MODEL<T>::getSymbolPinString( int symbolPinNumber ) const
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
|
|
|
wxString name = "";
|
|
|
|
SCH_PIN* symbolPin = m_symbol.GetAllPins().at( symbolPinNumber - 1 );
|
|
|
|
|
|
|
|
if( symbolPin )
|
|
|
|
name = symbolPin->GetShownName();
|
|
|
|
|
|
|
|
LOCALE_IO toggle;
|
|
|
|
|
|
|
|
if( name.IsEmpty() )
|
|
|
|
return wxString::Format( "%d", symbolPinNumber );
|
|
|
|
else
|
|
|
|
return wxString::Format( "%d (%s)", symbolPinNumber, symbolPin->GetShownName() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
wxString DIALOG_SIM_MODEL<T>::getModelPinString( int modelPinNumber ) const
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
2022-04-01 04:30:50 +00:00
|
|
|
const wxString& pinName = curModel().GetPin( modelPinNumber - 1 ).name;
|
2022-03-09 01:40:59 +00:00
|
|
|
|
|
|
|
LOCALE_IO toggle;
|
|
|
|
|
|
|
|
if( pinName.IsEmpty() )
|
|
|
|
return wxString::Format( "%d", modelPinNumber, pinName );
|
|
|
|
else
|
|
|
|
return wxString::Format( "%d (%s)", modelPinNumber, pinName );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
int DIALOG_SIM_MODEL<T>::getModelPinNumber( const wxString& aModelPinString ) const
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
|
|
|
if( aModelPinString == "Not Connected" )
|
|
|
|
return SIM_MODEL::PIN::NOT_CONNECTED;
|
|
|
|
|
|
|
|
int length = aModelPinString.Find( " " );
|
|
|
|
|
|
|
|
if( length == wxNOT_FOUND )
|
|
|
|
length = static_cast<int>( aModelPinString.Length() );
|
|
|
|
|
|
|
|
long result = 0;
|
|
|
|
aModelPinString.Mid( 0, length ).ToCLong( &result );
|
|
|
|
|
|
|
|
return static_cast<int>( result );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::onRadioButton( wxCommandEvent& aEvent )
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
|
|
|
updateWidgets();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::onBrowseButtonClick( wxCommandEvent& aEvent )
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
2022-04-12 14:37:06 +00:00
|
|
|
wxFileDialog dlg( this, _( "Browse Models" ), Prj().GetProjectPath() );
|
2022-04-01 04:30:50 +00:00
|
|
|
|
|
|
|
if( dlg.ShowModal() == wxID_CANCEL )
|
|
|
|
return;
|
|
|
|
|
2022-04-12 14:37:06 +00:00
|
|
|
wxString path = dlg.GetPath();
|
|
|
|
wxFileName fn( path );
|
|
|
|
|
|
|
|
if( fn.MakeRelativeTo( Prj().GetProjectPath() ) && !fn.GetFullPath().StartsWith( ".." ) )
|
|
|
|
path = fn.GetFullPath();
|
|
|
|
|
|
|
|
loadLibrary( path );
|
2022-04-01 04:30:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::onModelNameCombobox( wxCommandEvent& aEvent )
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
|
|
|
updateWidgets();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::onOverrideCheckbox( wxCommandEvent& aEvent )
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
|
|
|
updateWidgets();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-03-09 01:40:59 +00:00
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::onDeviceTypeChoice( wxCommandEvent& aEvent )
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
|
|
|
SIM_MODEL::DEVICE_TYPE deviceType =
|
|
|
|
static_cast<SIM_MODEL::DEVICE_TYPE>( m_deviceTypeChoice->GetSelection() );
|
|
|
|
|
|
|
|
m_curModelType = m_curModelTypeOfDeviceType.at( deviceType );
|
|
|
|
|
|
|
|
updateWidgets();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::onTypeChoice( wxCommandEvent& aEvent )
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
|
|
|
SIM_MODEL::DEVICE_TYPE deviceType =
|
|
|
|
static_cast<SIM_MODEL::DEVICE_TYPE>( m_deviceTypeChoice->GetSelection() );
|
|
|
|
wxString typeDescription = m_typeChoice->GetString( m_typeChoice->GetSelection() );
|
|
|
|
|
|
|
|
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
|
|
|
|
{
|
|
|
|
if( deviceType == SIM_MODEL::TypeInfo( type ).deviceType
|
|
|
|
&& typeDescription == SIM_MODEL::TypeInfo( type ).description )
|
|
|
|
{
|
|
|
|
m_curModelType = type;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_curModelTypeOfDeviceType.at( deviceType ) = m_curModelType;
|
|
|
|
updateWidgets();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::onParamGridChanged( wxPropertyGridEvent& aEvent )
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
|
|
|
updateWidgets();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-03-09 01:40:59 +00:00
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::onPinAssignmentsGridCellChange( wxGridEvent& aEvent )
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
|
|
|
int symbolPinNumber = aEvent.GetRow() + 1;
|
|
|
|
int oldModelPinNumber = getModelPinNumber( aEvent.GetString() );
|
|
|
|
int modelPinNumber = getModelPinNumber(
|
|
|
|
m_pinAssignmentsGrid->GetCellValue( aEvent.GetRow(), aEvent.GetCol() ) );
|
|
|
|
|
|
|
|
if( oldModelPinNumber != SIM_MODEL::PIN::NOT_CONNECTED )
|
2022-04-01 04:30:50 +00:00
|
|
|
curModel().SetPinSymbolPinNumber( oldModelPinNumber - 1, SIM_MODEL::PIN::NOT_CONNECTED );
|
2022-03-09 01:40:59 +00:00
|
|
|
|
|
|
|
if( modelPinNumber != SIM_MODEL::PIN::NOT_CONNECTED )
|
2022-04-01 04:30:50 +00:00
|
|
|
curModel().SetPinSymbolPinNumber( modelPinNumber - 1, symbolPinNumber );
|
2022-03-09 01:40:59 +00:00
|
|
|
|
|
|
|
updatePinAssignmentsGridEditors();
|
|
|
|
|
|
|
|
aEvent.Skip();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::onPinAssignmentsGridSize( wxSizeEvent& aEvent )
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
|
|
|
wxGridUpdateLocker deferRepaintsTillLeavingScope( m_pinAssignmentsGrid );
|
|
|
|
|
|
|
|
int gridWidth = KIPLATFORM::UI::GetUnobscuredSize( m_pinAssignmentsGrid ).x;
|
|
|
|
m_pinAssignmentsGrid->SetColSize( static_cast<int>( PIN_COLUMN::MODEL ), gridWidth / 2 );
|
|
|
|
m_pinAssignmentsGrid->SetColSize( static_cast<int>( PIN_COLUMN::SYMBOL ), gridWidth / 2 );
|
|
|
|
|
|
|
|
aEvent.Skip();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::onLibraryFilenameInputUpdate( wxUpdateUIEvent& aEvent )
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
|
|
|
aEvent.Enable( m_useLibraryModelRadioButton->GetValue() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::onBrowseButtonUpdate( wxUpdateUIEvent& aEvent )
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
|
|
|
aEvent.Enable( m_useLibraryModelRadioButton->GetValue() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::onModelNameComboboxUpdate( wxUpdateUIEvent& aEvent )
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
|
|
|
aEvent.Enable( m_useLibraryModelRadioButton->GetValue() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::onOverrideCheckboxUpdate( wxUpdateUIEvent& aEvent )
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
|
|
|
aEvent.Enable( m_useLibraryModelRadioButton->GetValue() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::onDeviceTypeChoiceUpdate( wxUpdateUIEvent& aEvent )
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
|
|
|
aEvent.Enable( m_useInstanceModelRadioButton->GetValue() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::onTypeChoiceUpdate( wxUpdateUIEvent& aEvent )
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
|
|
|
aEvent.Enable( m_useInstanceModelRadioButton->GetValue() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-03-09 01:40:59 +00:00
|
|
|
template <typename T>
|
2022-04-12 14:37:06 +00:00
|
|
|
void DIALOG_SIM_MODEL<T>::onSelectionChange( wxPropertyGridEvent& aEvent )
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
|
|
|
// TODO: Activate also when the whole property grid is selected with tab key.
|
|
|
|
|
|
|
|
wxPropertyGrid* grid = m_paramGrid->GetGrid();
|
|
|
|
if( !grid )
|
|
|
|
{
|
|
|
|
wxFAIL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
wxWindow* editorControl = grid->GetEditorControl();
|
|
|
|
if( !editorControl )
|
|
|
|
{
|
|
|
|
wxFAIL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Without this, the user had to press tab before they could edit the field.
|
|
|
|
editorControl->SetFocus();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*template <typename T>
|
|
|
|
void DIALOG_SPICE_MODEL<T>::onPropertyChanged( wxPropertyGridEvent& aEvent )
|
|
|
|
{
|
|
|
|
wxString name = aEvent.GetPropertyName();
|
|
|
|
|
|
|
|
for( SIM_MODEL::PARAM& param : getCurModel().Params() )
|
|
|
|
{
|
|
|
|
if( param.info.name == name )
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
param.value->FromString( m_paramGrid->GetPropertyValueAsString( param.info.name ) );
|
|
|
|
}
|
|
|
|
catch( KI_PARAM_ERROR& e )
|
|
|
|
{
|
|
|
|
DisplayErrorMessage( this, e.What() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}*/
|