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
|
2022-12-09 20:02:47 +00:00
|
|
|
* Copyright (C) 2022 CERN
|
2023-01-03 15:29:45 +00:00
|
|
|
* Copyright (C) 2022-2023 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-11-18 21:07:38 +00:00
|
|
|
#include <dialog_ibis_parser_reporter.h>
|
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-09-27 20:47:00 +00:00
|
|
|
#include <sim/sim_library_kibis.h>
|
2022-04-01 04:30:50 +00:00
|
|
|
#include <sim/sim_library_spice.h>
|
2022-12-09 20:02:47 +00:00
|
|
|
#include <sim/sim_model.h>
|
2022-09-27 20:47:00 +00:00
|
|
|
#include <sim/sim_model_kibis.h>
|
2022-09-18 05:25:56 +00:00
|
|
|
#include <sim/sim_model_raw_spice.h>
|
2022-12-22 20:21:10 +00:00
|
|
|
#include <sim/sim_model_spice_fallback.h>
|
2022-12-31 16:53:37 +00:00
|
|
|
#include <sim/sim_model_subckt.h>
|
2022-10-28 11:43:00 +00:00
|
|
|
#include <grid_tricks.h>
|
|
|
|
#include <widgets/grid_icon_text_helpers.h>
|
2022-12-13 20:47:28 +00:00
|
|
|
#include <widgets/std_bitmap_button.h>
|
2022-03-09 01:40:59 +00:00
|
|
|
#include <kiplatform/ui.h>
|
2016-08-11 12:41:56 +00:00
|
|
|
#include <confirm.h>
|
2022-08-26 01:26:54 +00:00
|
|
|
#include <string_utils.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>
|
2022-09-03 12:55:47 +00:00
|
|
|
#include <wx/textfile.h>
|
2022-12-31 16:53:37 +00:00
|
|
|
#include <fmt/format.h>
|
2016-08-11 12:41:40 +00:00
|
|
|
|
2022-02-21 03:58:31 +00:00
|
|
|
using CATEGORY = SIM_MODEL::PARAM::CATEGORY;
|
|
|
|
|
2018-09-22 14:05:32 +00:00
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
DIALOG_SIM_MODEL<T_symbol, T_field>::DIALOG_SIM_MODEL( wxWindow* aParent, T_symbol& aSymbol,
|
|
|
|
std::vector<T_field>& 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-12-14 13:00:25 +00:00
|
|
|
m_libraryModelsMgr( &Prj() ),
|
|
|
|
m_builtinModelsMgr( &Prj() ),
|
2022-04-01 04:30:50 +00:00
|
|
|
m_prevModel( nullptr ),
|
2022-11-19 00:45:28 +00:00
|
|
|
m_curModelType( SIM_MODEL::TYPE::NONE ),
|
2022-10-28 11:43:00 +00:00
|
|
|
m_scintillaTricks( nullptr ),
|
2022-06-12 03:39:13 +00:00
|
|
|
m_firstCategory( nullptr ),
|
2022-12-07 15:02:35 +00:00
|
|
|
m_prevParamGridSelection( nullptr ),
|
2022-12-08 14:40:01 +00:00
|
|
|
m_lastParamGridWidth( 0 ),
|
2022-12-07 15:02:35 +00:00
|
|
|
m_inKillFocus( false )
|
2018-09-22 14:05:32 +00:00
|
|
|
{
|
2022-06-12 03:39:13 +00:00
|
|
|
m_browseButton->SetBitmap( KiBitmap( BITMAPS::small_folder ) );
|
|
|
|
|
2022-12-16 13:42:49 +00:00
|
|
|
m_sortedPartPins = m_symbol.GetAllLibPins();
|
2022-11-26 00:31:41 +00:00
|
|
|
|
|
|
|
std::sort( m_sortedPartPins.begin(), m_sortedPartPins.end(),
|
2022-08-26 01:26:54 +00:00
|
|
|
[]( const LIB_PIN* lhs, const LIB_PIN* rhs )
|
|
|
|
{
|
|
|
|
// We sort by StrNumCmp because SIM_MODEL_BASE sorts with it too.
|
|
|
|
return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0;
|
|
|
|
} );
|
|
|
|
|
2022-02-09 00:45:04 +00:00
|
|
|
m_typeChoice->Clear();
|
2020-03-23 16:49:21 +00:00
|
|
|
|
2022-10-28 11:43:00 +00:00
|
|
|
m_scintillaTricks = new SCINTILLA_TRICKS( m_codePreview, wxT( "{}" ), false );
|
|
|
|
|
2022-06-21 02:22:52 +00:00
|
|
|
m_paramGridMgr->Bind( wxEVT_PG_SELECTED, &DIALOG_SIM_MODEL::onParamGridSelectionChange, this );
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2022-12-08 14:40:01 +00:00
|
|
|
wxPropertyGrid* grid = m_paramGrid->GetGrid();
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2022-12-08 14:40:01 +00:00
|
|
|
// In wx 3.0 the color will be wrong sometimes.
|
|
|
|
grid->SetCellDisabledTextColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
|
2022-06-21 02:22:52 +00:00
|
|
|
|
2022-12-08 14:40:01 +00:00
|
|
|
grid->Bind( wxEVT_SET_FOCUS, &DIALOG_SIM_MODEL::onParamGridSetFocus, this );
|
2023-02-24 12:43:41 +00:00
|
|
|
grid->Bind( wxEVT_UPDATE_UI, &DIALOG_SIM_MODEL::onUpdateUI, this );
|
2022-06-12 03:39:13 +00:00
|
|
|
|
2022-12-08 14:40:01 +00:00
|
|
|
grid->AddActionTrigger( wxPG_ACTION_EDIT, WXK_RETURN );
|
|
|
|
grid->DedicateKey( WXK_RETURN );
|
|
|
|
grid->AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_RETURN );
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2023-03-10 21:24:21 +00:00
|
|
|
grid->AddActionTrigger( wxPG_ACTION_EDIT, WXK_NUMPAD_ENTER );
|
|
|
|
grid->DedicateKey( WXK_NUMPAD_ENTER );
|
|
|
|
grid->AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_NUMPAD_ENTER );
|
|
|
|
|
2022-12-08 14:40:01 +00:00
|
|
|
grid->DedicateKey( WXK_UP );
|
|
|
|
grid->DedicateKey( WXK_DOWN );
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2022-10-27 23:33:31 +00:00
|
|
|
m_pinAssignmentsGrid->PushEventHandler( new GRID_TRICKS( m_pinAssignmentsGrid ) );
|
|
|
|
|
2022-12-31 16:53:37 +00:00
|
|
|
m_subcktLabel->SetFont( KIUI::GetInfoFont( m_subcktLabel ) );
|
|
|
|
|
2022-08-02 10:52:22 +00:00
|
|
|
// Now all widgets have the size fixed, call FinishDialogSettings
|
|
|
|
finishDialogSettings();
|
2016-08-11 12:41:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
DIALOG_SIM_MODEL<T_symbol, T_field>::~DIALOG_SIM_MODEL()
|
2022-10-27 23:33:31 +00:00
|
|
|
{
|
2022-11-12 02:09:26 +00:00
|
|
|
// Disable all properties. This is necessary because some of their methods are called after
|
|
|
|
// destruction of DIALOG_SIM_MODEL, oddly. When disabled, they never access their models.
|
|
|
|
for( wxPropertyGridIterator it = m_paramGrid->GetIterator(); !it.AtEnd(); ++it )
|
|
|
|
{
|
|
|
|
SIM_PROPERTY* prop = dynamic_cast<SIM_PROPERTY*>( *it );
|
|
|
|
|
|
|
|
if( !prop )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
prop->Disable();
|
|
|
|
}
|
|
|
|
|
2022-10-27 23:33:31 +00:00
|
|
|
// Delete the GRID_TRICKS.
|
|
|
|
m_pinAssignmentsGrid->PopEventHandler( true );
|
2022-10-28 11:43:00 +00:00
|
|
|
|
|
|
|
delete m_scintillaTricks;
|
2022-10-27 23:33:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataToWindow()
|
2022-01-23 17:23:22 +00:00
|
|
|
{
|
2022-10-26 13:03:20 +00:00
|
|
|
wxCommandEvent dummyEvent;
|
2022-12-18 22:53:53 +00:00
|
|
|
wxString deviceType;
|
|
|
|
wxString modelType;
|
|
|
|
wxString modelParams;
|
|
|
|
wxString pinMap;
|
2022-12-23 17:26:16 +00:00
|
|
|
bool storeInValue = false;
|
2022-12-18 22:53:53 +00:00
|
|
|
|
2023-03-16 15:57:27 +00:00
|
|
|
wxString msg;
|
|
|
|
WX_STRING_REPORTER reporter( &msg );
|
|
|
|
|
2022-12-18 22:53:53 +00:00
|
|
|
// Infer RLC and VI models if they aren't specified
|
2022-12-19 18:10:57 +00:00
|
|
|
if( SIM_MODEL::InferSimModel( m_symbol, &m_fields, false, SIM_VALUE_GRAMMAR::NOTATION::SI,
|
|
|
|
&deviceType, &modelType, &modelParams, &pinMap ) )
|
2022-12-09 20:02:47 +00:00
|
|
|
{
|
2023-01-05 14:16:06 +00:00
|
|
|
m_fields.emplace_back( &m_symbol, -1, SIM_DEVICE_TYPE_FIELD );
|
2022-12-18 22:53:53 +00:00
|
|
|
m_fields.back().SetText( deviceType );
|
2022-12-09 20:02:47 +00:00
|
|
|
|
2022-12-18 22:53:53 +00:00
|
|
|
if( !modelType.IsEmpty() )
|
2022-12-09 20:02:47 +00:00
|
|
|
{
|
2023-01-05 14:16:06 +00:00
|
|
|
m_fields.emplace_back( &m_symbol, -1, SIM_TYPE_FIELD );
|
2022-12-18 22:53:53 +00:00
|
|
|
m_fields.back().SetText( modelType );
|
|
|
|
}
|
2022-12-09 20:02:47 +00:00
|
|
|
|
2023-01-05 14:16:06 +00:00
|
|
|
m_fields.emplace_back( &m_symbol, -1, SIM_PARAMS_FIELD );
|
2022-12-18 22:53:53 +00:00
|
|
|
m_fields.back().SetText( modelParams );
|
2022-12-14 23:21:35 +00:00
|
|
|
|
2023-01-05 14:16:06 +00:00
|
|
|
m_fields.emplace_back( &m_symbol, -1, SIM_PINS_FIELD );
|
2022-12-18 22:53:53 +00:00
|
|
|
m_fields.back().SetText( pinMap );
|
2022-12-09 20:22:10 +00:00
|
|
|
|
2022-12-23 17:26:16 +00:00
|
|
|
storeInValue = true;
|
|
|
|
|
|
|
|
// In case the storeInValue checkbox is turned off (if it's left on then we'll overwrite
|
|
|
|
// this field with the actual value):
|
2022-12-18 22:53:53 +00:00
|
|
|
m_fields[ VALUE_FIELD ].SetText( wxT( "${SIM.PARAMS}" ) );
|
2022-12-09 20:02:47 +00:00
|
|
|
}
|
|
|
|
|
2023-02-28 12:20:45 +00:00
|
|
|
std::vector<LIB_PIN*> sourcePins = m_symbol.GetAllLibPins();
|
|
|
|
|
|
|
|
std::sort( sourcePins.begin(), sourcePins.end(),
|
|
|
|
[]( const LIB_PIN* lhs, const LIB_PIN* rhs )
|
|
|
|
{
|
|
|
|
return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0;
|
|
|
|
} );
|
|
|
|
|
2022-10-31 10:30:29 +00:00
|
|
|
std::string libraryFilename = SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY::LIBRARY_FIELD );
|
2022-01-23 17:23:22 +00:00
|
|
|
|
2022-06-21 02:22:52 +00:00
|
|
|
if( libraryFilename != "" )
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
|
|
|
// The model is sourced from a library, optionally with instance overrides.
|
2022-10-26 13:03:20 +00:00
|
|
|
m_useLibraryModelRadioButton->SetValue( true );
|
2022-01-23 17:23:22 +00:00
|
|
|
|
2023-01-18 13:49:50 +00:00
|
|
|
if( !loadLibrary( libraryFilename ) )
|
2022-12-15 14:25:25 +00:00
|
|
|
{
|
2023-01-18 13:49:50 +00:00
|
|
|
m_libraryPathText->ChangeValue( libraryFilename );
|
2023-03-16 15:57:27 +00:00
|
|
|
m_curModelType = SIM_MODEL::ReadTypeFromFields( m_fields, &reporter );
|
2023-02-28 12:20:45 +00:00
|
|
|
m_libraryModelsMgr.CreateModel( nullptr, sourcePins, m_fields );
|
|
|
|
|
|
|
|
m_modelNameChoice->Append( _( "<unknown>" ) );
|
|
|
|
m_modelNameChoice->SetSelection( 0 );
|
2022-12-15 14:25:25 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-01-18 11:50:47 +00:00
|
|
|
std::string modelName = SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY::NAME_FIELD );
|
|
|
|
int modelIdx = m_modelNameChoice->FindString( modelName );
|
|
|
|
|
|
|
|
if( modelIdx == wxNOT_FOUND )
|
|
|
|
{
|
|
|
|
DisplayErrorMessage( this, wxString::Format( _( "No model named '%s' in library." ),
|
|
|
|
modelName ) );
|
|
|
|
|
|
|
|
// Default to first item in library
|
|
|
|
m_modelNameChoice->SetSelection( 0 );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_modelNameChoice->SetSelection( modelIdx );
|
|
|
|
}
|
2023-01-18 13:49:50 +00:00
|
|
|
|
|
|
|
m_curModelType = curModel().GetType();
|
2022-12-15 14:25:25 +00:00
|
|
|
}
|
2022-09-27 20:47:00 +00:00
|
|
|
|
2022-12-15 12:12:36 +00:00
|
|
|
if( isIbisLoaded() && ( m_modelNameChoice->GetSelection() >= 0 ) )
|
2022-09-27 20:47:00 +00:00
|
|
|
{
|
2023-01-18 13:49:50 +00:00
|
|
|
int idx = m_modelNameChoice->GetSelection();
|
|
|
|
auto kibismodel = dynamic_cast<SIM_MODEL_KIBIS*>( &m_libraryModelsMgr.GetModels().at( idx ).get() );
|
2022-09-27 20:47:00 +00:00
|
|
|
|
|
|
|
if( kibismodel )
|
|
|
|
{
|
2022-12-15 12:12:36 +00:00
|
|
|
onModelNameChoice( dummyEvent ); // refresh list of pins
|
2022-09-27 20:47:00 +00:00
|
|
|
|
2022-10-04 21:47:52 +00:00
|
|
|
int i = 0;
|
2022-09-27 20:47:00 +00:00
|
|
|
|
2022-12-15 12:12:36 +00:00
|
|
|
for( const std::pair<std::string, std::string>& strs : kibismodel->GetIbisPins() )
|
2022-09-27 20:47:00 +00:00
|
|
|
{
|
2023-01-12 12:46:52 +00:00
|
|
|
if( strs.first == SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY_KIBIS::PIN_FIELD ) )
|
2022-09-27 20:47:00 +00:00
|
|
|
{
|
2023-01-12 16:29:51 +00:00
|
|
|
auto kibisLibrary = static_cast<const SIM_LIBRARY_KIBIS*>( library() );
|
2022-11-19 00:45:28 +00:00
|
|
|
|
|
|
|
kibismodel->ChangePin( *kibisLibrary, strs.first );
|
2022-10-04 21:47:52 +00:00
|
|
|
m_ibisPinCombobox->SetSelection( static_cast<int>( i ) );
|
2022-09-27 20:47:00 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
2022-10-04 21:47:52 +00:00
|
|
|
if( i < static_cast<int>( kibismodel->GetIbisPins().size() ) )
|
2022-09-27 20:47:00 +00:00
|
|
|
{
|
|
|
|
onIbisPinCombobox( dummyEvent ); // refresh list of models
|
|
|
|
|
|
|
|
m_ibisModelCombobox->SetStringSelection(
|
|
|
|
SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY_KIBIS::MODEL_FIELD ) );
|
|
|
|
}
|
2022-10-25 09:45:40 +00:00
|
|
|
|
|
|
|
if( SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY_KIBIS::DIFF_FIELD ) == "1" )
|
|
|
|
{
|
|
|
|
kibismodel->SwitchSingleEndedDiff( true );
|
|
|
|
m_differentialCheckbox->SetValue( true );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
kibismodel->SwitchSingleEndedDiff( false );
|
|
|
|
m_differentialCheckbox->SetValue( false );
|
|
|
|
}
|
2022-09-27 20:47:00 +00:00
|
|
|
}
|
|
|
|
}
|
2016-08-11 12:42:09 +00:00
|
|
|
}
|
2023-03-25 20:22:04 +00:00
|
|
|
else if( !SIM_MODEL::GetFieldValue( &m_fields, SIM_DEVICE_TYPE_FIELD ).empty()
|
|
|
|
|| !SIM_MODEL::GetFieldValue( &m_fields, SIM_TYPE_FIELD ).empty() )
|
2016-08-11 12:41:40 +00:00
|
|
|
{
|
2022-04-01 04:30:50 +00:00
|
|
|
// The model is sourced from the instance.
|
2022-10-31 06:28:58 +00:00
|
|
|
m_useInstanceModelRadioButton->SetValue( true );
|
2023-03-16 15:57:27 +00:00
|
|
|
|
|
|
|
msg.clear();
|
|
|
|
m_curModelType = SIM_MODEL::ReadTypeFromFields( m_fields, &reporter );
|
|
|
|
|
|
|
|
if( reporter.HasMessage() )
|
|
|
|
DisplayErrorMessage( this, msg );
|
2022-11-12 22:12:29 +00:00
|
|
|
}
|
2022-04-01 04:30:50 +00:00
|
|
|
|
2023-03-16 15:57:27 +00:00
|
|
|
m_builtinModelsMgr.SetReporter( &reporter );
|
|
|
|
|
2022-11-12 22:12:29 +00:00
|
|
|
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
|
|
|
|
{
|
2023-01-03 15:29:45 +00:00
|
|
|
if( m_useInstanceModelRadioButton->GetValue() && type == m_curModelType )
|
2023-03-16 15:57:27 +00:00
|
|
|
{
|
|
|
|
msg.clear();
|
2023-01-03 15:29:45 +00:00
|
|
|
m_builtinModelsMgr.CreateModel( m_fields, sourcePins, false );
|
|
|
|
|
2023-03-16 15:57:27 +00:00
|
|
|
if( reporter.HasMessage() )
|
|
|
|
{
|
|
|
|
DisplayErrorMessage( this, _( "Failed to read simulation model from fields." )
|
|
|
|
+ wxT( "\n\n" ) + msg );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
2023-03-16 15:57:27 +00:00
|
|
|
m_builtinModelsMgr.CreateModel( type, sourcePins );
|
2022-04-01 04:30:50 +00:00
|
|
|
}
|
|
|
|
|
2022-12-18 22:53:53 +00:00
|
|
|
SIM_MODEL::DEVICE_T deviceTypeT = SIM_MODEL::TypeInfo( type ).deviceType;
|
2022-11-12 22:12:29 +00:00
|
|
|
|
2022-12-18 22:53:53 +00:00
|
|
|
if( !m_curModelTypeOfDeviceType.count( deviceTypeT ) )
|
|
|
|
m_curModelTypeOfDeviceType[deviceTypeT] = type;
|
2016-08-11 12:41:40 +00:00
|
|
|
}
|
2016-08-11 12:41:56 +00:00
|
|
|
|
2023-01-03 16:58:36 +00:00
|
|
|
if( storeInValue )
|
|
|
|
curModel().SetIsStoredInValue( true );
|
2022-12-23 17:26:16 +00:00
|
|
|
|
2022-11-22 00:46:02 +00:00
|
|
|
m_saveInValueCheckbox->SetValue( curModel().IsStoredInValue() );
|
2022-10-29 17:44:30 +00:00
|
|
|
|
2022-10-31 06:28:58 +00:00
|
|
|
onRadioButton( dummyEvent );
|
2022-04-12 14:37:06 +00:00
|
|
|
return DIALOG_SIM_MODEL_BASE::TransferDataToWindow();
|
2016-08-11 12:41:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataFromWindow()
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
2022-06-21 02:22:52 +00:00
|
|
|
m_pinAssignmentsGrid->CommitPendingChanges();
|
2022-12-05 02:07:45 +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;
|
|
|
|
|
2022-09-22 05:38:45 +00:00
|
|
|
std::string path;
|
2023-02-25 15:21:08 +00:00
|
|
|
std::string name;
|
2022-04-12 14:37:06 +00:00
|
|
|
|
2023-02-25 15:21:08 +00:00
|
|
|
if( m_useLibraryModelRadioButton->GetValue() )
|
2022-05-31 02:55:48 +00:00
|
|
|
{
|
2022-12-07 15:02:35 +00:00
|
|
|
path = m_libraryPathText->GetValue();
|
2022-04-12 14:37:06 +00:00
|
|
|
wxFileName fn( path );
|
|
|
|
|
|
|
|
if( fn.MakeRelativeTo( Prj().GetProjectPath() ) && !fn.GetFullPath().StartsWith( ".." ) )
|
|
|
|
path = fn.GetFullPath();
|
2023-02-25 15:21:08 +00:00
|
|
|
|
2023-03-06 11:16:19 +00:00
|
|
|
if( !m_modelNameChoice->IsEmpty() )
|
2023-02-25 15:21:08 +00:00
|
|
|
name = m_modelNameChoice->GetStringSelection().ToStdString();
|
2023-03-06 11:16:19 +00:00
|
|
|
else if( dynamic_cast<SIM_MODEL_SPICE_FALLBACK*>( &curModel() ) )
|
|
|
|
name = SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY::NAME_FIELD, false );
|
2022-04-01 04:30:50 +00:00
|
|
|
}
|
|
|
|
|
2022-09-27 20:47:00 +00:00
|
|
|
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY::LIBRARY_FIELD, path );
|
2023-02-25 15:21:08 +00:00
|
|
|
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY::NAME_FIELD, name );
|
2022-09-27 20:47:00 +00:00
|
|
|
|
2022-10-04 21:47:52 +00:00
|
|
|
if( isIbisLoaded() )
|
2022-09-27 20:47:00 +00:00
|
|
|
{
|
2023-01-12 12:46:52 +00:00
|
|
|
SIM_MODEL_KIBIS* ibismodel = static_cast<SIM_MODEL_KIBIS*>(
|
2022-12-15 12:12:36 +00:00
|
|
|
&m_libraryModelsMgr.GetModels().at( m_modelNameChoice->GetSelection() ).get() );
|
2022-09-27 20:47:00 +00:00
|
|
|
|
2023-01-12 12:46:52 +00:00
|
|
|
if( ibismodel )
|
2022-09-27 20:47:00 +00:00
|
|
|
{
|
2023-02-13 11:52:30 +00:00
|
|
|
std::string pins;
|
|
|
|
std::string modelName = std::string( m_ibisModelCombobox->GetValue().c_str() );
|
|
|
|
std::string differential;
|
2022-12-05 02:07:45 +00:00
|
|
|
|
2023-02-13 11:52:30 +00:00
|
|
|
if( m_ibisPinCombobox->GetSelection() >= 0 )
|
|
|
|
pins = ibismodel->GetIbisPins().at( m_ibisPinCombobox->GetSelection() ).first;
|
2022-12-05 02:07:45 +00:00
|
|
|
|
2023-02-13 11:52:30 +00:00
|
|
|
if( ibismodel->CanDifferential() && m_differentialCheckbox->GetValue() )
|
|
|
|
differential = "1";
|
|
|
|
|
|
|
|
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY_KIBIS::PIN_FIELD, pins );
|
|
|
|
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY_KIBIS::MODEL_FIELD, modelName );
|
|
|
|
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY_KIBIS::DIFF_FIELD, differential );
|
2022-09-27 20:47:00 +00:00
|
|
|
}
|
|
|
|
}
|
2022-05-31 02:55:48 +00:00
|
|
|
|
2023-01-14 02:43:34 +00:00
|
|
|
if( curModel().GetType() == SIM_MODEL::TYPE::RAWSPICE )
|
|
|
|
{
|
2023-03-25 20:22:04 +00:00
|
|
|
if( m_modelNotebook->GetSelection() == 0 )
|
|
|
|
updateModelCodeTab( &curModel() );
|
|
|
|
|
2023-01-14 02:43:34 +00:00
|
|
|
wxString code = m_codePreview->GetText().Trim( true ).Trim( false );
|
|
|
|
curModel().SetParamValue( "model", std::string( code.ToUTF8() ) );
|
|
|
|
}
|
|
|
|
|
2023-01-03 16:58:36 +00:00
|
|
|
curModel().SetIsStoredInValue( m_saveInValueCheckbox->GetValue() );
|
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
curModel().WriteFields( m_fields );
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::updateWidgets()
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
2023-02-15 00:26:01 +00:00
|
|
|
SIM_MODEL* model = &curModel();
|
|
|
|
|
|
|
|
updateIbisWidgets( model );
|
|
|
|
updateInstanceWidgets( model );
|
|
|
|
updateModelParamsTab( model );
|
|
|
|
updateModelCodeTab( model );
|
|
|
|
updatePinAssignments( model );
|
2022-11-07 19:26:36 +00:00
|
|
|
|
2023-01-05 14:16:06 +00:00
|
|
|
std::string ref = SIM_MODEL::GetFieldValue( &m_fields, SIM_REFERENCE_FIELD );
|
2022-10-31 06:28:58 +00:00
|
|
|
|
2022-10-04 21:47:52 +00:00
|
|
|
m_modelPanel->Layout();
|
|
|
|
m_pinAssignmentsPanel->Layout();
|
|
|
|
m_parametersPanel->Layout();
|
|
|
|
m_codePanel->Layout();
|
|
|
|
|
|
|
|
SendSizeEvent( wxSEND_EVENT_POST );
|
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
m_prevModel = &curModel();
|
2022-03-09 01:40:59 +00:00
|
|
|
}
|
|
|
|
|
2022-10-26 13:03:20 +00:00
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
2023-02-15 00:26:01 +00:00
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::updateIbisWidgets( SIM_MODEL* aModel )
|
2022-10-04 21:47:52 +00:00
|
|
|
{
|
2023-02-15 00:26:01 +00:00
|
|
|
SIM_MODEL_KIBIS* modelkibis = isIbisLoaded() ? dynamic_cast<SIM_MODEL_KIBIS*>( aModel )
|
2022-11-02 12:32:22 +00:00
|
|
|
: nullptr;
|
2022-10-25 09:45:40 +00:00
|
|
|
|
2022-10-04 21:47:52 +00:00
|
|
|
m_ibisModelCombobox->Show( isIbisLoaded() );
|
|
|
|
m_ibisPinCombobox->Show( isIbisLoaded() );
|
|
|
|
m_ibisModelLabel->Show( isIbisLoaded() );
|
|
|
|
m_ibisPinLabel->Show( isIbisLoaded() );
|
|
|
|
|
2022-10-25 09:45:40 +00:00
|
|
|
m_differentialCheckbox->Show( isIbisLoaded() && modelkibis && modelkibis->CanDifferential() );
|
2022-12-12 21:07:53 +00:00
|
|
|
m_modelNameLabel->SetLabel( isIbisLoaded() ? _( "Component:" ) : _( "Model:" ) );
|
2022-10-04 21:47:52 +00:00
|
|
|
}
|
|
|
|
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
2023-02-15 00:26:01 +00:00
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::updateInstanceWidgets( SIM_MODEL* aModel )
|
2016-08-11 12:41:40 +00:00
|
|
|
{
|
2022-10-31 10:33:45 +00:00
|
|
|
// Change the Type choice to match the current device type.
|
2023-02-15 00:26:01 +00:00
|
|
|
if( aModel != m_prevModel )
|
2022-10-31 10:33:45 +00:00
|
|
|
{
|
2022-11-20 21:06:21 +00:00
|
|
|
m_deviceTypeChoice->Clear();
|
|
|
|
|
|
|
|
if( m_useLibraryModelRadioButton->GetValue() )
|
|
|
|
{
|
2023-02-15 00:26:01 +00:00
|
|
|
m_deviceTypeChoice->Append( aModel->GetDeviceInfo().description );
|
2022-11-20 21:06:21 +00:00
|
|
|
m_deviceTypeChoice->SetSelection( 0 );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-12-06 14:59:49 +00:00
|
|
|
for( SIM_MODEL::DEVICE_T deviceType : SIM_MODEL::DEVICE_T_ITERATOR() )
|
2022-11-20 21:06:21 +00:00
|
|
|
{
|
|
|
|
if( !SIM_MODEL::DeviceInfo( deviceType ).isBuiltin )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
m_deviceTypeChoice->Append( SIM_MODEL::DeviceInfo( deviceType ).description );
|
|
|
|
|
2023-02-15 00:26:01 +00:00
|
|
|
if( deviceType == aModel->GetDeviceType() )
|
2022-11-20 21:06:21 +00:00
|
|
|
m_deviceTypeChoice->SetSelection( m_deviceTypeChoice->GetCount() - 1 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-31 10:33:45 +00:00
|
|
|
m_typeChoice->Clear();
|
2017-10-26 17:54:53 +00:00
|
|
|
|
2022-10-31 10:33:45 +00:00
|
|
|
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
|
|
|
|
{
|
2023-02-15 00:26:01 +00:00
|
|
|
if( SIM_MODEL::TypeInfo( type ).deviceType == aModel->GetDeviceType() )
|
2022-10-31 06:28:58 +00:00
|
|
|
{
|
2022-11-18 08:02:25 +00:00
|
|
|
m_typeChoice->Append( SIM_MODEL::TypeInfo( type ).description );
|
2022-10-31 06:28:58 +00:00
|
|
|
|
2023-02-15 00:26:01 +00:00
|
|
|
if( type == aModel->GetType() )
|
2022-10-31 10:33:45 +00:00
|
|
|
m_typeChoice->SetSelection( m_typeChoice->GetCount() - 1 );
|
2022-04-01 04:30:50 +00:00
|
|
|
}
|
2016-08-11 12:41:40 +00:00
|
|
|
}
|
2022-10-31 10:33:45 +00:00
|
|
|
}
|
2022-11-20 21:56:01 +00:00
|
|
|
|
|
|
|
m_typeChoice->Enable( !m_useLibraryModelRadioButton->GetValue() || isIbisLoaded() );
|
2022-11-22 00:46:02 +00:00
|
|
|
|
2023-02-28 12:20:45 +00:00
|
|
|
if( dynamic_cast<SIM_MODEL_RAW_SPICE*>( aModel ) )
|
2022-12-04 19:43:57 +00:00
|
|
|
m_modelNotebook->SetSelection( 1 );
|
|
|
|
else
|
|
|
|
m_modelNotebook->SetSelection( 0 );
|
|
|
|
|
2023-02-15 00:26:01 +00:00
|
|
|
if( aModel->HasPrimaryValue() )
|
2022-11-22 00:46:02 +00:00
|
|
|
{
|
2023-02-15 00:26:01 +00:00
|
|
|
const SIM_MODEL::PARAM& primary = aModel->GetParam( 0 );
|
2022-11-22 00:46:02 +00:00
|
|
|
|
2022-12-04 15:19:38 +00:00
|
|
|
m_saveInValueCheckbox->SetLabel( wxString::Format( _( "Save parameter '%s (%s)' in Value "
|
|
|
|
"field" ),
|
|
|
|
primary.info.description,
|
|
|
|
primary.info.name ) );
|
|
|
|
m_saveInValueCheckbox->Enable( true );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_saveInValueCheckbox->SetLabel( _( "Save primary parameter in Value field" ) );
|
|
|
|
m_saveInValueCheckbox->SetValue( false );
|
|
|
|
m_saveInValueCheckbox->Enable( false );
|
|
|
|
}
|
2022-10-31 10:33:45 +00:00
|
|
|
}
|
2022-10-29 17:44:30 +00:00
|
|
|
|
2022-10-31 10:33:45 +00:00
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
2023-02-15 00:26:01 +00:00
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::updateModelParamsTab( SIM_MODEL* aModel )
|
2022-10-31 10:33:45 +00:00
|
|
|
{
|
2023-02-15 00:26:01 +00:00
|
|
|
if( aModel != m_prevModel )
|
2022-10-31 10:33:45 +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.
|
|
|
|
|
2022-10-28 11:43:00 +00:00
|
|
|
m_paramGridMgr->SetColumnCount( PARAM_COLUMN::END_ );
|
2018-05-03 09:58:13 +00:00
|
|
|
|
2022-12-04 15:19:38 +00:00
|
|
|
m_paramGridMgr->SetColumnTitle( PARAM_COLUMN::DESCRIPTION, _( "Parameter" ) );
|
2022-10-28 11:43:00 +00:00
|
|
|
m_paramGridMgr->SetColumnTitle( PARAM_COLUMN::UNIT, _( "Unit" ) );
|
|
|
|
m_paramGridMgr->SetColumnTitle( PARAM_COLUMN::DEFAULT, _( "Default" ) );
|
|
|
|
m_paramGridMgr->SetColumnTitle( 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-06-21 02:22:52 +00:00
|
|
|
m_firstCategory = m_paramGrid->Append( new wxPropertyCategory( "Geometry" ) );
|
|
|
|
m_paramGrid->HideProperty( "Geometry" );
|
|
|
|
|
|
|
|
m_paramGrid->Append( new wxPropertyCategory( "AC" ) );
|
2022-06-12 03:39:13 +00:00
|
|
|
m_paramGrid->HideProperty( "AC" );
|
|
|
|
|
|
|
|
m_paramGrid->Append( new wxPropertyCategory( "DC" ) );
|
2022-04-01 04:30:50 +00:00
|
|
|
m_paramGrid->HideProperty( "DC" );
|
2022-02-21 03:58:31 +00:00
|
|
|
|
2022-05-08 09:54:35 +00:00
|
|
|
m_paramGrid->Append( new wxPropertyCategory( "Capacitance" ) );
|
|
|
|
m_paramGrid->HideProperty( "Capacitance" );
|
|
|
|
|
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-09-27 20:47:00 +00:00
|
|
|
m_paramGrid->Append( new wxPropertyCategory( "Waveform" ) );
|
|
|
|
m_paramGrid->HideProperty( "Waveform" );
|
|
|
|
|
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" );
|
|
|
|
|
2022-06-12 03:39:13 +00:00
|
|
|
m_paramGrid->CollapseAll();
|
|
|
|
|
2023-02-15 00:26:01 +00:00
|
|
|
for( int i = 0; i < aModel->GetParamCount(); ++i )
|
|
|
|
addParamPropertyIfRelevant( aModel, i );
|
2022-06-21 02:22:52 +00:00
|
|
|
|
|
|
|
m_paramGrid->CollapseAll();
|
|
|
|
m_paramGrid->Expand( "AC" );
|
2022-09-27 20:47:00 +00:00
|
|
|
m_paramGrid->Expand( "Waveform" );
|
2022-04-01 04:30:50 +00:00
|
|
|
}
|
2022-02-21 03:58:31 +00:00
|
|
|
|
2022-12-08 14:40:01 +00:00
|
|
|
adjustParamGridColumns( m_paramGrid->GetGrid()->GetSize().GetX(), true );
|
|
|
|
|
2022-06-21 02:22:52 +00:00
|
|
|
// Set all properties to default colors.
|
2022-11-13 01:13:44 +00:00
|
|
|
// Update properties in models that have autofill.
|
2022-04-01 04:30:50 +00:00
|
|
|
for( wxPropertyGridIterator it = m_paramGrid->GetIterator(); !it.AtEnd(); ++it )
|
|
|
|
{
|
2022-06-21 02:22:52 +00:00
|
|
|
wxColour bgCol = m_paramGrid->GetGrid()->GetPropertyDefaultCell().GetBgCol();
|
|
|
|
wxColour fgCol = m_paramGrid->GetGrid()->GetPropertyDefaultCell().GetFgCol();
|
|
|
|
|
2022-08-22 05:40:23 +00:00
|
|
|
for( int col = 0; col < m_paramGridMgr->GetColumnCount(); ++col )
|
2022-06-21 02:22:52 +00:00
|
|
|
{
|
2022-09-11 13:22:45 +00:00
|
|
|
( *it )->GetCell( col ).SetBgCol( bgCol );
|
|
|
|
( *it )->GetCell( col ).SetFgCol( fgCol );
|
2022-06-21 02:22:52 +00:00
|
|
|
}
|
|
|
|
|
2022-11-13 01:13:44 +00:00
|
|
|
SIM_PROPERTY* prop = dynamic_cast<SIM_PROPERTY*>( *it );
|
|
|
|
|
|
|
|
if( !prop )
|
|
|
|
continue;
|
|
|
|
|
2022-10-26 13:03:20 +00:00
|
|
|
const SIM_MODEL::PARAM& param = prop->GetParam();
|
|
|
|
|
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.
|
2023-02-15 00:26:01 +00:00
|
|
|
if( aModel->HasAutofill() )
|
2023-02-22 09:10:06 +00:00
|
|
|
( *it )->SetValueFromString( param.value );
|
2022-04-01 04:30:50 +00:00
|
|
|
}
|
2016-08-11 12:41:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
2023-02-15 00:26:01 +00:00
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::updateModelCodeTab( SIM_MODEL* aModel )
|
2016-08-11 12:41:40 +00:00
|
|
|
{
|
2023-02-28 12:20:45 +00:00
|
|
|
if( dynamic_cast<SIM_MODEL_SPICE_FALLBACK*>( aModel ) )
|
|
|
|
return;
|
|
|
|
|
2022-12-04 19:43:57 +00:00
|
|
|
wxString text;
|
2022-10-10 23:23:00 +00:00
|
|
|
SPICE_ITEM item;
|
2022-04-01 04:30:50 +00:00
|
|
|
|
2023-01-14 02:43:34 +00:00
|
|
|
item.modelName = m_modelNameChoice->GetStringSelection();
|
2022-12-22 20:21:10 +00:00
|
|
|
|
2022-10-10 23:23:00 +00:00
|
|
|
if( m_useInstanceModelRadioButton->GetValue() || item.modelName == "" )
|
|
|
|
item.modelName = m_fields.at( REFERENCE_FIELD ).GetText();
|
2022-04-01 04:30:50 +00:00
|
|
|
|
2023-02-15 00:26:01 +00:00
|
|
|
text << aModel->SpiceGenerator().Preview( item );
|
2022-09-03 12:55:47 +00:00
|
|
|
|
2022-12-04 19:43:57 +00:00
|
|
|
m_codePreview->SetText( text );
|
2022-12-09 20:02:47 +00:00
|
|
|
m_codePreview->SelectNone();
|
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-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
2023-02-15 00:26:01 +00:00
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::updatePinAssignments( SIM_MODEL* aModel )
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
2023-02-15 00:26:01 +00:00
|
|
|
removeOrphanedPinAssignments( aModel );
|
2022-08-28 12:51:03 +00:00
|
|
|
|
|
|
|
// Reset the grid.
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
m_pinAssignmentsGrid->ClearRows();
|
2022-11-26 00:31:41 +00:00
|
|
|
m_pinAssignmentsGrid->AppendRows( static_cast<int>( m_sortedPartPins.size() ) );
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2022-08-22 05:40:23 +00:00
|
|
|
for( int row = 0; row < m_pinAssignmentsGrid->GetNumberRows(); ++row )
|
2022-10-28 11:43:00 +00:00
|
|
|
m_pinAssignmentsGrid->SetCellValue( row, PIN_COLUMN::MODEL, _( "Not Connected" ) );
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2022-08-22 05:40:23 +00:00
|
|
|
// Now set up the grid values in the Model column.
|
2023-02-15 00:26:01 +00:00
|
|
|
for( int modelPinIndex = 0; modelPinIndex < aModel->GetPinCount(); ++modelPinIndex )
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
2023-02-15 00:26:01 +00:00
|
|
|
wxString symbolPinNumber = aModel->GetPin( modelPinIndex ).symbolPinNumber;
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2022-08-22 05:40:23 +00:00
|
|
|
if( symbolPinNumber == "" )
|
2022-03-09 01:40:59 +00:00
|
|
|
continue;
|
|
|
|
|
2022-11-26 00:31:41 +00:00
|
|
|
int symbolPinRow = findSymbolPinRow( symbolPinNumber );
|
|
|
|
|
|
|
|
if( symbolPinRow == -1 )
|
|
|
|
continue;
|
|
|
|
|
2023-02-15 00:26:01 +00:00
|
|
|
wxString modelPinString = getModelPinString( aModel, modelPinIndex );
|
2022-11-26 00:31:41 +00:00
|
|
|
m_pinAssignmentsGrid->SetCellValue( symbolPinRow, PIN_COLUMN::MODEL, modelPinString );
|
2022-03-09 01:40:59 +00:00
|
|
|
}
|
|
|
|
|
2022-08-22 05:40:23 +00:00
|
|
|
// Set up the Symbol column grid values and Model column cell editors with dropdown options.
|
2022-10-28 11:43:00 +00:00
|
|
|
for( int ii = 0; ii < m_pinAssignmentsGrid->GetNumberRows(); ++ii )
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
2022-10-28 11:43:00 +00:00
|
|
|
wxString symbolPinString = getSymbolPinString( ii );
|
|
|
|
|
|
|
|
m_pinAssignmentsGrid->SetReadOnly( ii, PIN_COLUMN::SYMBOL );
|
|
|
|
m_pinAssignmentsGrid->SetCellValue( ii, PIN_COLUMN::SYMBOL, symbolPinString );
|
|
|
|
|
|
|
|
wxString curModelPinString = m_pinAssignmentsGrid->GetCellValue( ii, PIN_COLUMN::MODEL );
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2022-10-28 11:43:00 +00:00
|
|
|
std::vector<BITMAPS> modelPinIcons;
|
|
|
|
wxArrayString modelPinChoices;
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2023-02-15 00:26:01 +00:00
|
|
|
for( int jj = 0; jj < aModel->GetPinCount(); ++jj )
|
2022-10-28 11:43:00 +00:00
|
|
|
{
|
2023-02-15 00:26:01 +00:00
|
|
|
if( aModel->GetPin( jj ).symbolPinNumber != "" )
|
2022-10-28 11:43:00 +00:00
|
|
|
modelPinIcons.push_back( PinShapeGetBitmap( GRAPHIC_PINSHAPE::LINE ) );
|
|
|
|
else
|
|
|
|
modelPinIcons.push_back( BITMAPS::INVALID_BITMAP );
|
|
|
|
|
2023-02-15 00:26:01 +00:00
|
|
|
modelPinChoices.Add( getModelPinString( aModel, jj ) );
|
2022-10-28 11:43:00 +00:00
|
|
|
}
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2022-10-28 11:43:00 +00:00
|
|
|
modelPinIcons.push_back( BITMAPS::INVALID_BITMAP );
|
|
|
|
modelPinChoices.Add( _( "Not Connected" ) );
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2022-06-21 02:22:52 +00:00
|
|
|
// Using `new` here shouldn't cause a memory leak because `SetCellEditor()` calls
|
|
|
|
// `DecRef()` on its last editor.
|
2022-10-28 11:43:00 +00:00
|
|
|
m_pinAssignmentsGrid->SetCellEditor( ii, PIN_COLUMN::MODEL,
|
|
|
|
new GRID_CELL_ICON_TEXT_POPUP( modelPinIcons,
|
|
|
|
modelPinChoices ) );
|
2022-03-09 01:40:59 +00:00
|
|
|
}
|
2022-06-21 02:22:52 +00:00
|
|
|
|
|
|
|
// TODO: Show a preview of the symbol with the pin numbers shown.
|
2022-12-31 16:53:37 +00:00
|
|
|
|
2023-02-15 00:26:01 +00:00
|
|
|
if( aModel->GetType() == SIM_MODEL::TYPE::SUBCKT )
|
2022-12-31 16:53:37 +00:00
|
|
|
{
|
2023-02-15 00:26:01 +00:00
|
|
|
SIM_MODEL_SUBCKT* subckt = static_cast<SIM_MODEL_SUBCKT*>( aModel );
|
2022-12-31 16:53:37 +00:00
|
|
|
m_subckt->SetText( subckt->GetSpiceCode() );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_subcktLabel->Show( false );
|
|
|
|
m_subckt->Show( false );
|
|
|
|
}
|
2020-03-23 16:49:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
2023-02-15 00:26:01 +00:00
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::removeOrphanedPinAssignments( SIM_MODEL* aModel )
|
2022-08-28 12:51:03 +00:00
|
|
|
{
|
2023-02-15 00:26:01 +00:00
|
|
|
for( int i = 0; i < aModel->GetPinCount(); ++i )
|
2022-08-28 12:51:03 +00:00
|
|
|
{
|
2023-02-15 00:26:01 +00:00
|
|
|
if( !m_symbol.GetPin( aModel->GetPin( i ).symbolPinNumber ) )
|
|
|
|
aModel->SetPinSymbolPinNumber( i, "" );
|
2022-08-28 12:51:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
2023-01-18 13:49:50 +00:00
|
|
|
bool DIALOG_SIM_MODEL<T_symbol, T_field>::loadLibrary( const wxString& aLibraryPath,
|
2022-12-31 16:53:37 +00:00
|
|
|
bool aForceReload )
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
2023-02-15 00:26:01 +00:00
|
|
|
if( m_prevLibrary == aLibraryPath && !aForceReload )
|
|
|
|
return true;
|
|
|
|
|
2023-01-03 15:29:45 +00:00
|
|
|
wxString msg;
|
|
|
|
WX_STRING_REPORTER reporter( &msg );
|
2022-11-18 21:07:38 +00:00
|
|
|
|
2023-01-03 15:29:45 +00:00
|
|
|
m_libraryModelsMgr.SetReporter( &reporter );
|
2023-04-22 20:17:08 +00:00
|
|
|
m_libraryModelsMgr.SetForceFullParse();
|
2023-01-03 15:29:45 +00:00
|
|
|
m_libraryModelsMgr.SetLibrary( aLibraryPath );
|
2022-11-18 21:07:38 +00:00
|
|
|
|
2023-01-03 15:29:45 +00:00
|
|
|
if( reporter.HasMessage() )
|
|
|
|
{
|
|
|
|
DisplayErrorMessage( this, msg );
|
2023-01-18 13:49:50 +00:00
|
|
|
return false;
|
2022-11-18 21:07:38 +00:00
|
|
|
}
|
2022-09-27 20:47:00 +00:00
|
|
|
|
2022-12-17 15:21:35 +00:00
|
|
|
std::vector<LIB_PIN*> sourcePins = m_symbol.GetAllLibPins();
|
|
|
|
|
|
|
|
std::sort( sourcePins.begin(), sourcePins.end(),
|
|
|
|
[]( const LIB_PIN* lhs, const LIB_PIN* rhs )
|
|
|
|
{
|
|
|
|
return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0;
|
|
|
|
} );
|
|
|
|
|
2023-01-03 15:29:45 +00:00
|
|
|
std::string modelName = SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY::NAME_FIELD );
|
2022-04-01 04:30:50 +00:00
|
|
|
|
2023-01-29 17:35:19 +00:00
|
|
|
for( const auto& [baseModelName, baseModel] : library()->GetModels() )
|
2022-06-21 02:22:52 +00:00
|
|
|
{
|
2023-01-03 15:29:45 +00:00
|
|
|
if( baseModelName == modelName )
|
|
|
|
m_libraryModelsMgr.CreateModel( &baseModel, sourcePins, m_fields );
|
|
|
|
else
|
|
|
|
m_libraryModelsMgr.CreateModel( &baseModel, sourcePins );
|
2022-06-21 02:22:52 +00:00
|
|
|
}
|
|
|
|
|
2023-01-03 15:29:45 +00:00
|
|
|
if( reporter.HasMessage() )
|
|
|
|
DisplayErrorMessage( this, msg );
|
|
|
|
|
2022-12-15 12:12:36 +00:00
|
|
|
m_useLibraryModelRadioButton->SetValue( true );
|
|
|
|
m_libraryPathText->ChangeValue( aLibraryPath );
|
|
|
|
|
2022-06-21 02:22:52 +00:00
|
|
|
wxArrayString modelNames;
|
2022-10-26 13:03:20 +00:00
|
|
|
|
2023-01-29 17:35:19 +00:00
|
|
|
for( const auto& [name, model] : library()->GetModels() )
|
2023-01-03 15:29:45 +00:00
|
|
|
modelNames.Add( name );
|
2022-06-21 02:22:52 +00:00
|
|
|
|
2022-12-15 12:12:36 +00:00
|
|
|
m_modelNameChoice->Clear();
|
|
|
|
m_modelNameChoice->Append( modelNames );
|
2022-11-18 20:07:59 +00:00
|
|
|
|
|
|
|
if( isIbisLoaded() )
|
|
|
|
{
|
|
|
|
wxArrayString emptyArray;
|
|
|
|
m_ibisModelCombobox->Set( emptyArray );
|
|
|
|
m_ibisPinCombobox->Set( emptyArray );
|
|
|
|
m_ibisModelCombobox->SetSelection( -1 );
|
|
|
|
m_ibisPinCombobox->SetSelection( -1 );
|
|
|
|
}
|
2023-01-18 13:49:50 +00:00
|
|
|
|
2023-02-15 00:26:01 +00:00
|
|
|
m_prevLibrary = aLibraryPath;
|
2023-01-18 13:49:50 +00:00
|
|
|
return true;
|
2022-04-01 04:30:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
2023-02-15 00:26:01 +00:00
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::addParamPropertyIfRelevant( SIM_MODEL* aModel,
|
|
|
|
int aParamIndex )
|
2022-02-21 03:58:31 +00:00
|
|
|
{
|
2023-02-15 00:26:01 +00:00
|
|
|
if( aModel->GetParam( aParamIndex ).info.dir == SIM_MODEL::PARAM::DIR_OUT )
|
2022-02-21 03:58:31 +00:00
|
|
|
return;
|
|
|
|
|
2023-02-15 00:26:01 +00:00
|
|
|
switch( aModel->GetParam( aParamIndex ).info.category )
|
2022-02-21 03:58:31 +00:00
|
|
|
{
|
2022-06-12 03:39:13 +00:00
|
|
|
case CATEGORY::AC:
|
|
|
|
m_paramGrid->HideProperty( "AC", false );
|
2023-02-15 00:26:01 +00:00
|
|
|
m_paramGrid->AppendIn( "AC", newParamProperty( aModel, aParamIndex ) );
|
2022-06-12 03:39:13 +00:00
|
|
|
break;
|
|
|
|
|
2022-02-21 03:58:31 +00:00
|
|
|
case CATEGORY::DC:
|
|
|
|
m_paramGrid->HideProperty( "DC", false );
|
2023-02-15 00:26:01 +00:00
|
|
|
m_paramGrid->AppendIn( "DC", newParamProperty( aModel, aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CATEGORY::CAPACITANCE:
|
|
|
|
m_paramGrid->HideProperty( "Capacitance", false );
|
2023-02-15 00:26:01 +00:00
|
|
|
m_paramGrid->AppendIn( "Capacitance", newParamProperty( aModel, aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CATEGORY::TEMPERATURE:
|
|
|
|
m_paramGrid->HideProperty( "Temperature", false );
|
2023-02-15 00:26:01 +00:00
|
|
|
m_paramGrid->AppendIn( "Temperature", newParamProperty( aModel, aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CATEGORY::NOISE:
|
|
|
|
m_paramGrid->HideProperty( "Noise", false );
|
2023-02-15 00:26:01 +00:00
|
|
|
m_paramGrid->AppendIn( "Noise", newParamProperty( aModel, aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CATEGORY::DISTRIBUTED_QUANTITIES:
|
|
|
|
m_paramGrid->HideProperty( "Distributed Quantities", false );
|
2023-02-15 00:26:01 +00:00
|
|
|
m_paramGrid->AppendIn( "Distributed Quantities", newParamProperty( aModel, aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
2022-09-27 20:47:00 +00:00
|
|
|
case CATEGORY::WAVEFORM:
|
|
|
|
m_paramGrid->HideProperty( "Waveform", false );
|
2023-02-15 00:26:01 +00:00
|
|
|
m_paramGrid->AppendIn( "Waveform", newParamProperty( aModel, aParamIndex ) );
|
2022-09-27 20:47:00 +00:00
|
|
|
break;
|
|
|
|
|
2022-02-21 03:58:31 +00:00
|
|
|
case CATEGORY::GEOMETRY:
|
|
|
|
m_paramGrid->HideProperty( "Geometry", false );
|
2023-02-15 00:26:01 +00:00
|
|
|
m_paramGrid->AppendIn( "Geometry", newParamProperty( aModel, aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CATEGORY::LIMITING_VALUES:
|
|
|
|
m_paramGrid->HideProperty( "Limiting Values", false );
|
2023-02-15 00:26:01 +00:00
|
|
|
m_paramGrid->AppendIn( "Limiting Values", newParamProperty( aModel, aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CATEGORY::ADVANCED:
|
|
|
|
m_paramGrid->HideProperty( "Advanced", false );
|
2023-02-15 00:26:01 +00:00
|
|
|
m_paramGrid->AppendIn( "Advanced", newParamProperty( aModel, aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CATEGORY::FLAGS:
|
|
|
|
m_paramGrid->HideProperty( "Flags", false );
|
2023-02-15 00:26:01 +00:00
|
|
|
m_paramGrid->AppendIn( "Flags", newParamProperty( aModel, aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2023-02-15 00:26:01 +00:00
|
|
|
m_paramGrid->Insert( m_firstCategory, newParamProperty( aModel, aParamIndex ) );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CATEGORY::INITIAL_CONDITIONS:
|
|
|
|
case CATEGORY::SUPERFLUOUS:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-26 13:03:20 +00:00
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
2023-02-15 00:26:01 +00:00
|
|
|
wxPGProperty* DIALOG_SIM_MODEL<T_symbol, T_field>::newParamProperty( SIM_MODEL* aModel ,
|
|
|
|
int aParamIndex ) const
|
2017-10-26 17:54:53 +00:00
|
|
|
{
|
2023-02-15 00:26:01 +00:00
|
|
|
const SIM_MODEL::PARAM& param = aModel->GetParam( aParamIndex );
|
2022-04-12 14:37:06 +00:00
|
|
|
wxString paramDescription;
|
|
|
|
|
2022-08-02 12:43:03 +00:00
|
|
|
if( param.info.description == "" )
|
2022-04-12 14:37:06 +00:00
|
|
|
paramDescription = wxString::Format( "%s", param.info.name );
|
2022-08-30 07:00:52 +00:00
|
|
|
else
|
|
|
|
paramDescription = wxString::Format( "%s (%s)", param.info.description, param.info.name );
|
2022-04-12 14:37:06 +00:00
|
|
|
|
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
|
|
|
{
|
2022-06-21 02:22:52 +00:00
|
|
|
case SIM_VALUE::TYPE_BOOL:
|
2022-05-08 09:54:35 +00:00
|
|
|
// TODO.
|
2023-02-15 00:26:01 +00:00
|
|
|
prop = new SIM_BOOL_PROPERTY( paramDescription, param.info.name, *aModel, aParamIndex );
|
2022-05-08 09:54:35 +00:00
|
|
|
prop->SetAttribute( wxPG_BOOL_USE_CHECKBOX, true );
|
|
|
|
break;
|
|
|
|
|
2022-06-21 02:22:52 +00:00
|
|
|
case SIM_VALUE::TYPE_INT:
|
2023-02-15 00:26:01 +00:00
|
|
|
prop = new SIM_STRING_PROPERTY( paramDescription, param.info.name, *aModel, aParamIndex,
|
|
|
|
SIM_VALUE::TYPE_INT );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
2022-06-21 02:22:52 +00:00
|
|
|
case SIM_VALUE::TYPE_FLOAT:
|
2023-02-15 00:26:01 +00:00
|
|
|
prop = new SIM_STRING_PROPERTY( paramDescription, param.info.name, *aModel, aParamIndex,
|
|
|
|
SIM_VALUE::TYPE_FLOAT );
|
2022-02-21 03:58:31 +00:00
|
|
|
break;
|
|
|
|
|
2022-06-21 02:22:52 +00:00
|
|
|
//case TYPE_COMPLEX:
|
2022-05-08 09:54:35 +00:00
|
|
|
// break;
|
|
|
|
|
2022-06-21 02:22:52 +00:00
|
|
|
case SIM_VALUE::TYPE_STRING:
|
2022-08-30 07:00:52 +00:00
|
|
|
if( param.info.enumValues.empty() )
|
|
|
|
{
|
2023-02-15 00:26:01 +00:00
|
|
|
prop = new SIM_STRING_PROPERTY( paramDescription, param.info.name, *aModel,
|
2022-11-12 02:09:26 +00:00
|
|
|
aParamIndex, SIM_VALUE::TYPE_STRING );
|
2022-08-30 07:00:52 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-02-15 00:26:01 +00:00
|
|
|
prop = new SIM_ENUM_PROPERTY( paramDescription, param.info.name, *aModel, aParamIndex );
|
2022-08-30 07:00:52 +00:00
|
|
|
}
|
2022-02-21 03:58:31 +00:00
|
|
|
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-11-07 14:45:51 +00:00
|
|
|
prop->SetAttribute( wxPG_ATTR_UNITS, wxString::FromUTF8( param.info.unit.c_str() ) );
|
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-11-07 19:26:36 +00:00
|
|
|
#if wxCHECK_VERSION( 3, 1, 0 )
|
2023-02-21 19:55:47 +00:00
|
|
|
prop->SetCell( 3, wxString::FromUTF8( param.info.defaultValue ) );
|
2022-11-07 19:26:36 +00:00
|
|
|
#else
|
2023-02-21 19:55:47 +00:00
|
|
|
prop->SetCell( 3, wxString::FromUTF8( param.info.defaultValue.c_str() ) );
|
2022-11-07 19:26:36 +00:00
|
|
|
#endif
|
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
|
|
|
{
|
2022-10-28 11:43:00 +00:00
|
|
|
case SIM_VALUE::TYPE_BOOL: typeStr = wxT( "Bool" ); break;
|
|
|
|
case SIM_VALUE::TYPE_INT: typeStr = wxT( "Int" ); break;
|
|
|
|
case SIM_VALUE::TYPE_FLOAT: typeStr = wxT( "Float" ); break;
|
|
|
|
case SIM_VALUE::TYPE_COMPLEX: typeStr = wxT( "Complex" ); break;
|
|
|
|
case SIM_VALUE::TYPE_STRING: typeStr = wxT( "String" ); break;
|
|
|
|
case SIM_VALUE::TYPE_BOOL_VECTOR: typeStr = wxT( "Bool Vector" ); break;
|
|
|
|
case SIM_VALUE::TYPE_INT_VECTOR: typeStr = wxT( "Int Vector" ); break;
|
|
|
|
case SIM_VALUE::TYPE_FLOAT_VECTOR: typeStr = wxT( "Float Vector" ); break;
|
|
|
|
case SIM_VALUE::TYPE_COMPLEX_VECTOR: typeStr = wxT( "Complex Vector" ); break;
|
2022-02-21 03:58:31 +00:00
|
|
|
}
|
|
|
|
|
2022-10-28 11:43:00 +00:00
|
|
|
prop->SetCell( PARAM_COLUMN::TYPE, typeStr );
|
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
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
int DIALOG_SIM_MODEL<T_symbol, T_field>::findSymbolPinRow( const wxString& aSymbolPinNumber ) const
|
2022-08-22 05:40:23 +00:00
|
|
|
{
|
2022-11-26 00:31:41 +00:00
|
|
|
for( int row = 0; row < static_cast<int>( m_sortedPartPins.size() ); ++row )
|
2022-08-22 05:40:23 +00:00
|
|
|
{
|
2022-11-26 00:31:41 +00:00
|
|
|
LIB_PIN* pin = m_sortedPartPins[row];
|
2022-08-22 05:40:23 +00:00
|
|
|
|
|
|
|
if( pin->GetNumber() == aSymbolPinNumber )
|
|
|
|
return row;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
SIM_MODEL& DIALOG_SIM_MODEL<T_symbol, T_field>::curModel() const
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
2023-02-04 19:13:09 +00:00
|
|
|
if( m_useLibraryModelRadioButton->GetValue() )
|
2022-10-26 13:03:20 +00:00
|
|
|
{
|
2023-02-04 19:13:09 +00:00
|
|
|
int sel = m_modelNameChoice->GetSelection();
|
|
|
|
|
2023-02-04 20:16:28 +00:00
|
|
|
if( sel >= 0 && sel < (int) m_libraryModelsMgr.GetModels().size() )
|
|
|
|
return m_libraryModelsMgr.GetModels().at( sel ).get();
|
2022-10-26 13:03:20 +00:00
|
|
|
}
|
2022-04-01 04:30:50 +00:00
|
|
|
else
|
2022-12-04 19:43:57 +00:00
|
|
|
{
|
2023-02-04 19:13:09 +00:00
|
|
|
if( (int) m_curModelType < (int) m_builtinModelsMgr.GetModels().size() )
|
|
|
|
return m_builtinModelsMgr.GetModels().at( (int) m_curModelType );
|
2022-12-04 19:43:57 +00:00
|
|
|
}
|
2023-02-04 19:13:09 +00:00
|
|
|
|
|
|
|
return m_builtinModelsMgr.GetModels().at( (int) SIM_MODEL::TYPE::NONE );
|
2022-11-19 00:45:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-01-12 16:29:51 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
const SIM_LIBRARY* DIALOG_SIM_MODEL<T_symbol, T_field>::library() const
|
|
|
|
{
|
|
|
|
if( m_libraryModelsMgr.GetLibraries().size() == 1 )
|
|
|
|
return &m_libraryModelsMgr.GetLibraries().begin()->second.get();
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
wxString DIALOG_SIM_MODEL<T_symbol, T_field>::getSymbolPinString( int symbolPinIndex ) const
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
2022-11-26 00:31:41 +00:00
|
|
|
LIB_PIN* pin = m_sortedPartPins.at( symbolPinIndex );
|
2022-10-28 11:21:40 +00:00
|
|
|
wxString pinNumber;
|
|
|
|
wxString pinName;
|
2022-08-22 05:40:23 +00:00
|
|
|
|
|
|
|
if( pin )
|
|
|
|
{
|
2022-10-28 11:21:40 +00:00
|
|
|
pinNumber = pin->GetShownNumber();
|
|
|
|
pinName = pin->GetShownName();
|
2022-08-22 05:40:23 +00:00
|
|
|
}
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2022-10-28 11:21:40 +00:00
|
|
|
if( !pinName.IsEmpty() && pinName != pinNumber )
|
|
|
|
pinNumber += wxString::Format( wxT( " (%s)" ), pinName );
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2022-10-28 11:21:40 +00:00
|
|
|
return pinNumber;
|
2022-03-09 01:40:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
2023-02-15 00:26:01 +00:00
|
|
|
wxString DIALOG_SIM_MODEL<T_symbol, T_field>::getModelPinString( SIM_MODEL* aModel,
|
|
|
|
int aModelPinIndex ) const
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
2023-02-15 00:26:01 +00:00
|
|
|
const wxString& pinName = aModel->GetPin( aModelPinIndex ).name;
|
2022-08-22 05:40:23 +00:00
|
|
|
|
|
|
|
LOCALE_IO toggle;
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2022-10-28 11:21:40 +00:00
|
|
|
wxString pinNumber = wxString::Format( "%d", aModelPinIndex + 1 );
|
|
|
|
|
|
|
|
if( !pinName.IsEmpty() && pinName != pinNumber )
|
|
|
|
pinNumber += wxString::Format( wxT( " (%s)" ), pinName );
|
|
|
|
|
|
|
|
return pinNumber;
|
2022-03-09 01:40:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
int DIALOG_SIM_MODEL<T_symbol, T_field>::getModelPinIndex( 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 );
|
|
|
|
|
2022-08-22 05:40:23 +00:00
|
|
|
return static_cast<int>( result - 1 );
|
2022-03-09 01:40:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::onRadioButton( wxCommandEvent& aEvent )
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
2022-10-26 13:03:20 +00:00
|
|
|
bool fromLibrary = m_useLibraryModelRadioButton->GetValue();
|
|
|
|
|
|
|
|
m_pathLabel->Enable( fromLibrary );
|
2022-11-26 02:47:41 +00:00
|
|
|
m_libraryPathText->Enable( fromLibrary );
|
2022-11-12 22:12:29 +00:00
|
|
|
m_browseButton->Enable( fromLibrary );
|
|
|
|
m_modelNameLabel->Enable( fromLibrary );
|
2022-12-15 12:12:36 +00:00
|
|
|
m_modelNameChoice->Enable( fromLibrary );
|
2022-11-12 22:12:29 +00:00
|
|
|
m_ibisPinLabel->Enable( fromLibrary );
|
|
|
|
m_ibisPinCombobox->Enable( fromLibrary );
|
|
|
|
m_differentialCheckbox->Enable( fromLibrary );
|
|
|
|
m_ibisModelLabel->Enable( fromLibrary );
|
|
|
|
m_ibisModelCombobox->Enable( fromLibrary );
|
|
|
|
|
|
|
|
m_staticTextDevType->Enable( !fromLibrary );
|
|
|
|
m_deviceTypeChoice->Enable( !fromLibrary );
|
|
|
|
m_staticTextSpiceType->Enable( !fromLibrary );
|
2022-10-26 13:03:20 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
updateWidgets();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::onLibraryPathTextEnter( wxCommandEvent& aEvent )
|
2022-11-26 02:47:41 +00:00
|
|
|
{
|
|
|
|
if( m_useLibraryModelRadioButton->GetValue() )
|
|
|
|
{
|
|
|
|
wxString path = m_libraryPathText->GetValue();
|
|
|
|
|
2022-12-07 15:02:35 +00:00
|
|
|
if( !path.IsEmpty() )
|
2022-11-26 02:47:41 +00:00
|
|
|
{
|
2022-12-07 15:02:35 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
loadLibrary( path );
|
|
|
|
updateWidgets();
|
|
|
|
}
|
|
|
|
catch( const IO_ERROR& )
|
|
|
|
{
|
|
|
|
// TODO: Add an infobar to report the error?
|
|
|
|
}
|
2022-11-26 02:47:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::onLibraryPathTextKillFocus( wxFocusEvent& aEvent )
|
2022-11-26 02:47:41 +00:00
|
|
|
{
|
2022-12-07 15:02:35 +00:00
|
|
|
if( !m_inKillFocus )
|
|
|
|
{
|
|
|
|
m_inKillFocus = true;
|
|
|
|
|
|
|
|
wxCommandEvent dummy;
|
|
|
|
onLibraryPathTextEnter( dummy );
|
|
|
|
|
|
|
|
m_inKillFocus = false;
|
|
|
|
}
|
2022-11-26 02:47:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::onBrowseButtonClick( wxCommandEvent& aEvent )
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
2023-01-20 00:18:08 +00:00
|
|
|
static wxString s_mruPath;
|
|
|
|
|
|
|
|
wxString path = s_mruPath.IsEmpty() ? Prj().GetProjectPath() : s_mruPath;
|
|
|
|
wxFileDialog dlg( this, _( "Browse Models" ), path );
|
2022-04-01 04:30:50 +00:00
|
|
|
|
|
|
|
if( dlg.ShowModal() == wxID_CANCEL )
|
|
|
|
return;
|
|
|
|
|
2023-01-20 00:18:08 +00:00
|
|
|
path = dlg.GetPath();
|
2022-04-12 14:37:06 +00:00
|
|
|
wxFileName fn( path );
|
|
|
|
|
2023-01-20 00:18:08 +00:00
|
|
|
s_mruPath = fn.GetPath();
|
|
|
|
|
2023-01-17 04:14:38 +00:00
|
|
|
if( fn.MakeRelativeTo( Prj().GetProjectPath() ) && !fn.GetFullPath().StartsWith( wxS( ".." ) ) )
|
2022-04-12 14:37:06 +00:00
|
|
|
path = fn.GetFullPath();
|
|
|
|
|
2022-11-26 02:47:41 +00:00
|
|
|
loadLibrary( path, true );
|
2022-10-04 21:47:52 +00:00
|
|
|
updateWidgets();
|
2022-04-01 04:30:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
2022-12-15 12:12:36 +00:00
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::onModelNameChoice( wxCommandEvent& aEvent )
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
2022-10-04 21:47:52 +00:00
|
|
|
if( isIbisLoaded() )
|
2022-09-27 20:47:00 +00:00
|
|
|
{
|
|
|
|
wxArrayString pinLabels;
|
|
|
|
SIM_MODEL_KIBIS* modelkibis = dynamic_cast<SIM_MODEL_KIBIS*>( &curModel() );
|
|
|
|
|
2022-12-04 19:43:57 +00:00
|
|
|
wxCHECK2( modelkibis, return );
|
2022-09-27 20:47:00 +00:00
|
|
|
|
|
|
|
for( std::pair<wxString, wxString> strs : modelkibis->GetIbisPins() )
|
2022-10-26 13:03:20 +00:00
|
|
|
pinLabels.Add( strs.first + wxT( " - " ) + strs.second );
|
2022-09-27 20:47:00 +00:00
|
|
|
|
|
|
|
m_ibisPinCombobox->Set( pinLabels );
|
|
|
|
|
|
|
|
wxArrayString emptyArray;
|
|
|
|
m_ibisModelCombobox->Set( emptyArray );
|
|
|
|
}
|
2022-10-26 13:03:20 +00:00
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
updateWidgets();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::onIbisPinCombobox( wxCommandEvent& aEvent )
|
2022-09-27 20:47:00 +00:00
|
|
|
{
|
2022-10-04 21:47:52 +00:00
|
|
|
if( isIbisLoaded() )
|
2022-09-27 20:47:00 +00:00
|
|
|
{
|
|
|
|
wxArrayString modelLabels;
|
|
|
|
|
2023-01-12 12:46:52 +00:00
|
|
|
SIM_MODEL_KIBIS& ibisModel = static_cast<SIM_MODEL_KIBIS&>( curModel() );
|
2022-09-27 20:47:00 +00:00
|
|
|
|
2023-01-12 12:46:52 +00:00
|
|
|
std::vector<std::pair<std::string, std::string>> strs = ibisModel.GetIbisPins();
|
2022-10-25 09:45:40 +00:00
|
|
|
std::string pinNumber = strs.at( m_ibisPinCombobox->GetSelection() ).first;
|
|
|
|
|
2023-01-12 16:29:51 +00:00
|
|
|
const SIM_LIBRARY_KIBIS* ibisLibrary = dynamic_cast<const SIM_LIBRARY_KIBIS*>( library() );
|
2022-11-19 00:45:28 +00:00
|
|
|
|
2023-01-12 12:46:52 +00:00
|
|
|
ibisModel.ChangePin( *ibisLibrary, pinNumber );
|
2022-10-25 09:45:40 +00:00
|
|
|
|
2023-01-12 12:46:52 +00:00
|
|
|
ibisModel.m_enableDiff = ibisLibrary->isPinDiff( ibisModel.GetComponentName(), pinNumber );
|
2022-09-27 20:47:00 +00:00
|
|
|
|
2023-01-12 12:46:52 +00:00
|
|
|
for( wxString modelName : ibisModel.GetIbisModels() )
|
2022-09-27 20:47:00 +00:00
|
|
|
modelLabels.Add( modelName );
|
|
|
|
|
|
|
|
m_ibisModelCombobox->Set( modelLabels );
|
|
|
|
}
|
2022-10-26 13:03:20 +00:00
|
|
|
|
2022-09-27 20:47:00 +00:00
|
|
|
updateWidgets();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::onIbisPinComboboxTextEnter( wxCommandEvent& aEvent )
|
2022-09-27 20:47:00 +00:00
|
|
|
{
|
|
|
|
m_ibisPinCombobox->SetSelection(
|
|
|
|
m_ibisPinCombobox->FindString( m_ibisPinCombobox->GetValue() ) );
|
|
|
|
|
|
|
|
onIbisPinCombobox( aEvent );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::onIbisModelCombobox( wxCommandEvent& aEvent )
|
2022-09-27 20:47:00 +00:00
|
|
|
{
|
2022-06-21 02:22:52 +00:00
|
|
|
updateWidgets();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::onIbisModelComboboxTextEnter( wxCommandEvent& aEvent )
|
2022-09-27 20:47:00 +00:00
|
|
|
{
|
|
|
|
m_ibisModelCombobox->SetSelection(
|
|
|
|
m_ibisModelCombobox->FindString( m_ibisModelCombobox->GetValue() ) );
|
|
|
|
|
|
|
|
onIbisPinCombobox( aEvent );
|
|
|
|
}
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::onDifferentialCheckbox( wxCommandEvent& aEvent )
|
2022-10-25 09:45:40 +00:00
|
|
|
{
|
|
|
|
if( isIbisLoaded() )
|
|
|
|
{
|
|
|
|
SIM_MODEL_KIBIS* modelkibis = dynamic_cast<SIM_MODEL_KIBIS*>( &curModel() );
|
2023-03-04 18:02:05 +00:00
|
|
|
|
|
|
|
wxCHECK( modelkibis, /* void */ );
|
|
|
|
|
2022-10-25 09:45:40 +00:00
|
|
|
bool diff = m_differentialCheckbox->GetValue() && modelkibis->CanDifferential();
|
|
|
|
modelkibis->SwitchSingleEndedDiff( diff );
|
|
|
|
}
|
2022-11-20 21:06:21 +00:00
|
|
|
|
2022-10-25 09:45:40 +00:00
|
|
|
updateWidgets();
|
|
|
|
}
|
|
|
|
|
2022-04-01 04:30:50 +00:00
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::onDeviceTypeChoice( wxCommandEvent& aEvent )
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
2022-12-06 14:59:49 +00:00
|
|
|
for( SIM_MODEL::DEVICE_T deviceType : SIM_MODEL::DEVICE_T_ITERATOR() )
|
2022-11-20 21:06:21 +00:00
|
|
|
{
|
|
|
|
if( SIM_MODEL::DeviceInfo( deviceType ).description == m_deviceTypeChoice->GetStringSelection() )
|
|
|
|
{
|
|
|
|
m_curModelType = m_curModelTypeOfDeviceType.at( deviceType );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-03-09 01:40:59 +00:00
|
|
|
|
|
|
|
updateWidgets();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::onTypeChoice( wxCommandEvent& aEvent )
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
2022-12-17 20:25:29 +00:00
|
|
|
SIM_MODEL::DEVICE_T deviceType = curModel().GetDeviceType();
|
|
|
|
wxString typeDescription = m_typeChoice->GetString( m_typeChoice->GetSelection() );
|
|
|
|
std::vector<LIB_PIN*> sourcePins = m_symbol.GetAllLibPins();
|
|
|
|
|
|
|
|
std::sort( sourcePins.begin(), sourcePins.end(),
|
|
|
|
[]( const LIB_PIN* lhs, const LIB_PIN* rhs )
|
|
|
|
{
|
|
|
|
return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0;
|
|
|
|
} );
|
2022-03-09 01:40:59 +00:00
|
|
|
|
|
|
|
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
|
|
|
|
{
|
|
|
|
if( deviceType == SIM_MODEL::TypeInfo( type ).deviceType
|
|
|
|
&& typeDescription == SIM_MODEL::TypeInfo( type ).description )
|
|
|
|
{
|
2022-10-04 21:47:52 +00:00
|
|
|
if( isIbisLoaded()
|
2022-09-30 12:29:44 +00:00
|
|
|
&& ( type == SIM_MODEL::TYPE::KIBIS_DEVICE
|
|
|
|
|| type == SIM_MODEL::TYPE::KIBIS_DRIVER_DC
|
|
|
|
|| type == SIM_MODEL::TYPE::KIBIS_DRIVER_RECT
|
2022-10-25 09:45:40 +00:00
|
|
|
|| type == SIM_MODEL::TYPE::KIBIS_DRIVER_PRBS ) )
|
2022-09-27 20:47:00 +00:00
|
|
|
{
|
2022-12-15 12:12:36 +00:00
|
|
|
int idx = m_modelNameChoice->GetSelection();
|
|
|
|
|
2023-02-13 11:52:30 +00:00
|
|
|
auto& baseModel = static_cast<SIM_MODEL_KIBIS&>( m_libraryModelsMgr.GetModels().at( idx ).get() );
|
|
|
|
|
|
|
|
m_libraryModelsMgr.SetModel( idx, std::make_unique<SIM_MODEL_KIBIS>( type, baseModel ) );
|
2022-09-27 20:47:00 +00:00
|
|
|
|
2023-02-13 11:52:30 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
m_libraryModelsMgr.GetModels().at( idx ).get().ReadDataFields( &m_fields, sourcePins );
|
|
|
|
}
|
|
|
|
catch( IO_ERROR& err )
|
|
|
|
{
|
|
|
|
DisplayErrorMessage( this, err.What() );
|
|
|
|
}
|
2022-09-27 20:47:00 +00:00
|
|
|
}
|
|
|
|
|
2022-03-09 01:40:59 +00:00
|
|
|
m_curModelType = type;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_curModelTypeOfDeviceType.at( deviceType ) = m_curModelType;
|
|
|
|
updateWidgets();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
2022-12-17 22:33:00 +00:00
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::onPageChanging( wxBookCtrlEvent& event )
|
2022-04-01 04:30:50 +00:00
|
|
|
{
|
2023-02-15 00:26:01 +00:00
|
|
|
updateModelCodeTab( &curModel() );
|
2022-04-01 04:30:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::onPinAssignmentsGridCellChange( wxGridEvent& aEvent )
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
2022-10-27 23:33:31 +00:00
|
|
|
int symbolPinIndex = aEvent.GetRow();
|
|
|
|
wxString oldModelPinName = aEvent.GetString();
|
|
|
|
wxString modelPinName = m_pinAssignmentsGrid->GetCellValue( aEvent.GetRow(), aEvent.GetCol() );
|
|
|
|
|
|
|
|
int oldModelPinIndex = getModelPinIndex( oldModelPinName );
|
|
|
|
int modelPinIndex = getModelPinIndex( modelPinName );
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2022-08-22 05:40:23 +00:00
|
|
|
if( oldModelPinIndex != SIM_MODEL::PIN::NOT_CONNECTED )
|
|
|
|
curModel().SetPinSymbolPinNumber( oldModelPinIndex, "" );
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2022-08-22 05:40:23 +00:00
|
|
|
if( modelPinIndex != SIM_MODEL::PIN::NOT_CONNECTED )
|
|
|
|
{
|
|
|
|
curModel().SetPinSymbolPinNumber( modelPinIndex,
|
2022-11-26 00:31:41 +00:00
|
|
|
std::string( m_sortedPartPins.at( symbolPinIndex )->GetShownNumber().ToUTF8() ) );
|
2022-08-22 05:40:23 +00:00
|
|
|
}
|
2022-03-09 01:40:59 +00:00
|
|
|
|
2023-02-15 00:26:01 +00:00
|
|
|
updatePinAssignments( &curModel() );
|
2022-03-09 01:40:59 +00:00
|
|
|
|
|
|
|
aEvent.Skip();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::onPinAssignmentsGridSize( wxSizeEvent& aEvent )
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
|
|
|
wxGridUpdateLocker deferRepaintsTillLeavingScope( m_pinAssignmentsGrid );
|
|
|
|
|
|
|
|
int gridWidth = KIPLATFORM::UI::GetUnobscuredSize( m_pinAssignmentsGrid ).x;
|
2022-10-28 11:43:00 +00:00
|
|
|
m_pinAssignmentsGrid->SetColSize( PIN_COLUMN::MODEL, gridWidth / 2 );
|
|
|
|
m_pinAssignmentsGrid->SetColSize( PIN_COLUMN::SYMBOL, gridWidth / 2 );
|
2022-03-09 01:40:59 +00:00
|
|
|
|
|
|
|
aEvent.Skip();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::onParamGridSetFocus( wxFocusEvent& aEvent )
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
2022-06-21 02:22:52 +00:00
|
|
|
// By default, when a property grid is focused, the textbox is not immediately focused until
|
2022-06-12 03:39:13 +00:00
|
|
|
// Tab key is pressed. This is inconvenient, so we fix that here.
|
2022-03-09 01:40:59 +00:00
|
|
|
|
|
|
|
wxPropertyGrid* grid = m_paramGrid->GetGrid();
|
2023-02-24 14:19:01 +00:00
|
|
|
wxPGProperty* selected = grid->GetSelection();
|
2022-06-12 03:39:13 +00:00
|
|
|
|
|
|
|
if( !selected )
|
|
|
|
selected = grid->wxPropertyGridInterface::GetFirst();
|
|
|
|
|
2023-04-12 17:52:50 +00:00
|
|
|
#if wxCHECK_VERSION( 3, 3, 0 )
|
|
|
|
if( selected )
|
|
|
|
grid->DoSelectProperty( selected, wxPGSelectPropertyFlags::Focus );
|
|
|
|
#else
|
2022-06-12 03:39:13 +00:00
|
|
|
if( selected )
|
|
|
|
grid->DoSelectProperty( selected, wxPG_SEL_FOCUS );
|
2023-04-12 17:52:50 +00:00
|
|
|
#endif
|
2022-06-12 03:39:13 +00:00
|
|
|
|
|
|
|
aEvent.Skip();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::onParamGridSelectionChange( wxPropertyGridEvent& aEvent )
|
2022-06-12 03:39:13 +00:00
|
|
|
{
|
|
|
|
wxPropertyGrid* grid = m_paramGrid->GetGrid();
|
2022-10-26 13:03:20 +00:00
|
|
|
|
2022-06-12 03:39:13 +00:00
|
|
|
// Jump over categories.
|
|
|
|
if( grid->GetSelection() && grid->GetSelection()->IsCategory() )
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
2022-06-12 03:39:13 +00:00
|
|
|
wxPGProperty* selection = grid->GetSelection();
|
|
|
|
|
|
|
|
// If the new selection is immediately above the previous selection, we jump up. Otherwise
|
|
|
|
// we jump down. We do this by simulating up or down arrow keys.
|
|
|
|
|
|
|
|
wxPropertyGridIterator it = grid->GetIterator( wxPG_ITERATE_VISIBLE, selection );
|
|
|
|
it.Next();
|
|
|
|
|
|
|
|
wxKeyEvent* keyEvent = new wxKeyEvent( wxEVT_KEY_DOWN );
|
|
|
|
|
|
|
|
if( *it == m_prevParamGridSelection )
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
2022-06-12 03:39:13 +00:00
|
|
|
if( !selection->IsExpanded() )
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
2022-06-12 03:39:13 +00:00
|
|
|
grid->Expand( selection );
|
|
|
|
keyEvent->m_keyCode = WXK_DOWN;
|
|
|
|
wxQueueEvent( grid, keyEvent );
|
|
|
|
|
|
|
|
// Does not work for some reason.
|
|
|
|
/*m_paramGrid->DoSelectProperty( selection->Item( selection->GetChildCount() - 1 ),
|
|
|
|
wxPG_SEL_FOCUS );*/
|
2022-03-09 01:40:59 +00:00
|
|
|
}
|
2022-06-12 03:39:13 +00:00
|
|
|
else
|
2022-03-09 01:40:59 +00:00
|
|
|
{
|
2022-06-12 03:39:13 +00:00
|
|
|
keyEvent->m_keyCode = WXK_UP;
|
|
|
|
wxQueueEvent( grid, keyEvent );
|
2022-03-09 01:40:59 +00:00
|
|
|
}
|
|
|
|
}
|
2022-06-12 03:39:13 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if( !selection->IsExpanded() )
|
|
|
|
grid->Expand( selection );
|
|
|
|
|
|
|
|
keyEvent->m_keyCode = WXK_DOWN;
|
|
|
|
wxQueueEvent( grid, keyEvent );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_prevParamGridSelection = grid->GetSelection();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
wxWindow* editorControl = grid->GetEditorControl();
|
2023-02-24 12:43:41 +00:00
|
|
|
|
2022-06-12 03:39:13 +00:00
|
|
|
if( !editorControl )
|
|
|
|
{
|
|
|
|
m_prevParamGridSelection = grid->GetSelection();
|
|
|
|
return;
|
2022-03-09 01:40:59 +00:00
|
|
|
}
|
2022-07-30 12:06:51 +00:00
|
|
|
|
2022-06-12 03:39:13 +00:00
|
|
|
// Without this the user had to press tab before they could edit the field.
|
|
|
|
editorControl->SetFocus();
|
|
|
|
m_prevParamGridSelection = grid->GetSelection();
|
|
|
|
}
|
2022-08-01 02:49:28 +00:00
|
|
|
|
2022-12-08 14:40:01 +00:00
|
|
|
|
2023-02-24 12:43:41 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::onUpdateUI( wxUpdateUIEvent& aEvent )
|
|
|
|
{
|
|
|
|
// This is currently patched in wxPropertyGrid::ScrollWindow() in the Mac wxWidgets fork.
|
|
|
|
// However, we may need this version if it turns out to be an issue on other platforms and
|
|
|
|
// we can't get it upstreamed.
|
|
|
|
#if 0
|
|
|
|
// It's a shame to do this on the UpdateUI event, but neither the wxPropertyGridManager,
|
|
|
|
// wxPropertyGridPage, wxPropertyGrid, nor the wxPropertyGrid's GetCanvas() window appear
|
|
|
|
// to get scroll events.
|
|
|
|
|
|
|
|
wxPropertyGrid* grid = m_paramGrid->GetGrid();
|
|
|
|
wxTextCtrl* ctrl = grid->GetEditorTextCtrl();
|
|
|
|
|
|
|
|
if( ctrl )
|
|
|
|
{
|
|
|
|
wxRect ctrlRect = ctrl->GetScreenRect();
|
|
|
|
wxRect gridRect = grid->GetScreenRect();
|
|
|
|
|
|
|
|
if( ctrlRect.GetTop() < gridRect.GetTop() || ctrlRect.GetBottom() > gridRect.GetBottom() )
|
|
|
|
grid->ClearSelection();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::adjustParamGridColumns( int aWidth, bool aForce )
|
2022-12-08 14:40:01 +00:00
|
|
|
{
|
|
|
|
wxPropertyGrid* grid = m_paramGridMgr->GetGrid();
|
|
|
|
int margin = 15;
|
|
|
|
int indent = 20;
|
|
|
|
|
|
|
|
if( aWidth != m_lastParamGridWidth || aForce )
|
|
|
|
{
|
|
|
|
m_lastParamGridWidth = aWidth;
|
|
|
|
|
|
|
|
grid->FitColumns();
|
|
|
|
|
|
|
|
std::vector<int> colWidths;
|
|
|
|
|
|
|
|
for( size_t ii = 0; ii < grid->GetColumnCount(); ii++ )
|
|
|
|
{
|
2023-03-04 00:08:21 +00:00
|
|
|
if( ii == PARAM_COLUMN::DESCRIPTION )
|
2022-12-08 14:40:01 +00:00
|
|
|
colWidths.push_back( grid->GetState()->GetColumnWidth( ii ) + margin + indent );
|
2023-03-04 00:08:21 +00:00
|
|
|
else if( ii == PARAM_COLUMN::VALUE )
|
|
|
|
colWidths.push_back( std::max( 72, grid->GetState()->GetColumnWidth( ii ) ) + margin );
|
2022-12-08 14:40:01 +00:00
|
|
|
else
|
2023-03-04 00:08:21 +00:00
|
|
|
colWidths.push_back( 60 + margin );
|
2022-12-08 14:40:01 +00:00
|
|
|
|
|
|
|
aWidth -= colWidths[ ii ];
|
|
|
|
}
|
|
|
|
|
|
|
|
for( size_t ii = 0; ii < grid->GetColumnCount(); ii++ )
|
|
|
|
grid->SetColumnProportion( ii, colWidths[ ii ] );
|
|
|
|
|
|
|
|
grid->ResetColumnSizes();
|
|
|
|
grid->RefreshEditor();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template <typename T_symbol, typename T_field>
|
|
|
|
void DIALOG_SIM_MODEL<T_symbol, T_field>::onSizeParamGrid( wxSizeEvent& event )
|
2022-12-08 14:40:01 +00:00
|
|
|
{
|
|
|
|
adjustParamGridColumns( event.GetSize().GetX(), false );
|
|
|
|
|
|
|
|
event.Skip();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-12-09 20:02:47 +00:00
|
|
|
template class DIALOG_SIM_MODEL<SCH_SYMBOL, SCH_FIELD>;
|
|
|
|
template class DIALOG_SIM_MODEL<LIB_SYMBOL, LIB_FIELD>;
|