From 6fcb95b24e550523d35ae8210619fbf3c0aa5adc Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Tue, 21 Feb 2023 09:06:02 +0000 Subject: [PATCH] ADDED user-defined signals. --- common/widgets/grid_text_helpers.cpp | 5 +- eeschema/CMakeLists.txt | 2 + .../dialogs/dialog_user_defined_signals.cpp | 226 +++++++++ .../dialogs/dialog_user_defined_signals.h | 61 +++ .../dialog_user_defined_signals_base.cpp | 114 +++++ .../dialog_user_defined_signals_base.fbp | 477 ++++++++++++++++++ .../dialog_user_defined_signals_base.h | 68 +++ eeschema/sim/ngspice.cpp | 6 +- eeschema/sim/sim_plot_frame.cpp | 229 +++++---- eeschema/sim/sim_plot_frame.h | 26 +- eeschema/sim/sim_plot_panel.cpp | 2 +- eeschema/sim/sim_types.h | 29 +- eeschema/sim/spice_settings.cpp | 4 +- eeschema/sim/toolbars_sim_plot_frame.cpp | 1 + eeschema/tools/ee_actions.cpp | 6 + eeschema/tools/ee_actions.h | 1 + eeschema/tools/simulator_control.cpp | 15 + eeschema/tools/simulator_control.h | 1 + include/widgets/grid_text_helpers.h | 6 +- 19 files changed, 1163 insertions(+), 116 deletions(-) create mode 100644 eeschema/dialogs/dialog_user_defined_signals.cpp create mode 100644 eeschema/dialogs/dialog_user_defined_signals.h create mode 100644 eeschema/dialogs/dialog_user_defined_signals_base.cpp create mode 100644 eeschema/dialogs/dialog_user_defined_signals_base.fbp create mode 100644 eeschema/dialogs/dialog_user_defined_signals_base.h diff --git a/common/widgets/grid_text_helpers.cpp b/common/widgets/grid_text_helpers.cpp index 2f482b6c9b..fec5cdcace 100644 --- a/common/widgets/grid_text_helpers.cpp +++ b/common/widgets/grid_text_helpers.cpp @@ -60,8 +60,10 @@ wxSize GRID_CELL_ESCAPED_TEXT_RENDERER::GetBestSize( wxGrid & aGrid, wxGridCellA //-------- GRID_CELL_STC_EDITOR ----------------------------------------------------------------- // -GRID_CELL_STC_EDITOR::GRID_CELL_STC_EDITOR( std::function aOnChar ) : + m_ignoreCase( aIgnoreCase ), m_onChar( aOnChar ) { } @@ -79,6 +81,7 @@ void GRID_CELL_STC_EDITOR::Create( wxWindow* aParent, wxWindowID aId, wxEvtHandl stc_ctrl()->SetMarginWidth( 1, 0 ); // Line-number margin stc_ctrl()->SetEOLMode( wxSTC_EOL_LF ); stc_ctrl()->AutoCompSetMaxWidth( 25 ); + stc_ctrl()->AutoCompSetIgnoreCase( m_ignoreCase ); stc_ctrl()->UsePopUp( 0 ); // A hack which causes Scintilla to auto-size the text editor canvas diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index 8d839e53ff..fc4e7e64c0 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -351,6 +351,8 @@ if( KICAD_SPICE ) dialogs/dialog_sim_format_value_base.cpp dialogs/dialog_sim_model.cpp dialogs/dialog_sim_model_base.cpp + dialogs/dialog_user_defined_signals.cpp + dialogs/dialog_user_defined_signals_base.cpp tools/simulator_control.cpp sim/ngspice_circuit_model.cpp sim/ngspice.cpp diff --git a/eeschema/dialogs/dialog_user_defined_signals.cpp b/eeschema/dialogs/dialog_user_defined_signals.cpp new file mode 100644 index 0000000000..903f9992b3 --- /dev/null +++ b/eeschema/dialogs/dialog_user_defined_signals.cpp @@ -0,0 +1,226 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * 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: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include <../sim/sim_plot_frame.h> +#include + + +DIALOG_USER_DEFINED_SIGNALS::DIALOG_USER_DEFINED_SIGNALS( SIM_PLOT_FRAME* aParent, + std::vector* aSignals ) : + DIALOG_USER_DEFINED_SIGNALS_BASE( aParent ), + m_frame( aParent ), + m_signals( aSignals ), + m_helpWindow( nullptr ) +{ + m_grid->PushEventHandler( new GRID_TRICKS( m_grid ) ); + + for( const wxString& signal : *m_signals ) + addGridRow( signal ); + + m_addButton->SetBitmap( KiBitmap( BITMAPS::small_plus ) ); + m_deleteButton->SetBitmap( KiBitmap( BITMAPS::small_trash ) ); + + SetupStandardButtons(); + Layout(); + + // Now all widgets have the size fixed, call FinishDialogSettings + finishDialogSettings(); +} + + +DIALOG_USER_DEFINED_SIGNALS::~DIALOG_USER_DEFINED_SIGNALS() +{ + // Delete the GRID_TRICKS. + m_grid->PopEventHandler( true ); + + if( m_helpWindow ) + m_helpWindow->Destroy(); +} + + +bool DIALOG_USER_DEFINED_SIGNALS::TransferDataToWindow() +{ + if( !wxDialog::TransferDataToWindow() ) + return false; + + return true; +} + + +void DIALOG_USER_DEFINED_SIGNALS::addGridRow( const wxString& aText ) +{ + int row = m_grid->GetNumberRows(); + + m_grid->AppendRows(); + m_grid->SetCellValue( row, 0, aText ); + + wxGridCellAttr* attr = new wxGridCellAttr; + attr->SetEditor( new GRID_CELL_STC_EDITOR( true, + [this]( wxStyledTextEvent& aEvent, SCINTILLA_TRICKS* aScintillaTricks ) + { + onScintillaCharAdded( aEvent, aScintillaTricks ); + } ) ); + + m_grid->SetAttr( row, 0, attr ); +} + + +void DIALOG_USER_DEFINED_SIGNALS::onAddSignal( wxCommandEvent& event ) +{ + if( !m_grid->CommitPendingChanges() ) + return; + + addGridRow( wxEmptyString ); + + m_grid->MakeCellVisible( m_grid->GetNumberRows() - 1, 0 ); + m_grid->SetGridCursor( m_grid->GetNumberRows() - 1, 0 ); + + m_grid->EnableCellEditControl( true ); + m_grid->ShowCellEditControl(); +} + + +void DIALOG_USER_DEFINED_SIGNALS::onDeleteSignal( wxCommandEvent& event ) +{ + int curRow = m_grid->GetGridCursorRow(); + + if( curRow < 0 || m_grid->GetNumberRows() <= curRow ) + return; + + m_grid->CommitPendingChanges( true /* silent mode; we don't care if it's valid */ ); + m_grid->DeleteRows( curRow, 1 ); + + m_grid->MakeCellVisible( std::max( 0, curRow-1 ), m_grid->GetGridCursorCol() ); + m_grid->SetGridCursor( std::max( 0, curRow-1 ), m_grid->GetGridCursorCol() ); +} + + +void DIALOG_USER_DEFINED_SIGNALS::onScintillaCharAdded( wxStyledTextEvent &aEvent, + SCINTILLA_TRICKS* aTricks ) +{ + wxStyledTextCtrl* textCtrl = aTricks->Scintilla(); + wxArrayString tokens; + + for( const wxString& signal : m_frame->Signals() ) + tokens.push_back( signal ); + + tokens.push_back( wxS( "sqrt(x)" ) ); + tokens.push_back( wxS( "sin(x)" ) ); + tokens.push_back( wxS( "cos(x)" ) ); + tokens.push_back( wxS( "tan(x)" ) ); + tokens.push_back( wxS( "sinh(x)" ) ); + tokens.push_back( wxS( "cosh(x)" ) ); + tokens.push_back( wxS( "tanh(x)" ) ); + tokens.push_back( wxS( "asin(x)" ) ); + tokens.push_back( wxS( "acos(x)" ) ); + tokens.push_back( wxS( "atan(x)" ) ); + tokens.push_back( wxS( "asinh(x)" ) ); + tokens.push_back( wxS( "acosh(x)" ) ); + tokens.push_back( wxS( "atanh(x)" ) ); + tokens.push_back( wxS( "arctan(x)" ) ); + tokens.push_back( wxS( "exp(x)" ) ); + tokens.push_back( wxS( "ln(x)" ) ); + tokens.push_back( wxS( "log(x)" ) ); + tokens.push_back( wxS( "abs(x)" ) ); + tokens.push_back( wxS( "nint(x)" ) ); + tokens.push_back( wxS( "int(x)" ) ); + tokens.push_back( wxS( "floor(x)" ) ); + tokens.push_back( wxS( "ceil(x)" ) ); + tokens.push_back( wxS( "pow(x,y)" ) ); + tokens.push_back( wxS( "pwr(x,y)" ) ); + tokens.push_back( wxS( "min(x,y)" ) ); + tokens.push_back( wxS( "max(x,y)" ) ); + tokens.push_back( wxS( "sgn(x)" ) ); + tokens.push_back( wxS( "ternary_fcn(x,y,z)" ) ); + tokens.push_back( wxS( "gauss(nom,rvar,sigma)" ) ); + tokens.push_back( wxS( "agauss(nom,avar,sigma)" ) ); + tokens.push_back( wxS( "unif(nom,rvar)" ) ); + tokens.push_back( wxS( "aunif(nom,avar)" ) ); + tokens.push_back( wxS( "limit(nom,avar)" ) ); + + int text_pos = textCtrl->GetCurrentPos(); + int start = textCtrl->WordStartPosition( text_pos, true ); + int parenCount = 0; + + for( start = text_pos - 1; start > 0; start-- ) + { + wxUniChar c = textCtrl->GetCharAt( start ); + + if( c == '(' ) + { + if( parenCount ) + { + start += 1; + break; + } + else + { + parenCount++; + } + } + else if( wxIsalpha( c ) && parenCount ) + { + break; + } + else if( !wxIsalnum( c ) && c != '/' ) + { + start += 1; + break; + } + } + + wxString partial = textCtrl->GetRange( start, text_pos ); + + aTricks->DoAutocomplete( partial, tokens ); + textCtrl->SetFocus(); +} + + +bool DIALOG_USER_DEFINED_SIGNALS::TransferDataFromWindow() +{ + if( !wxDialog::TransferDataFromWindow() ) + return false; + + if( !m_grid->CommitPendingChanges() ) + return false; + + m_signals->clear(); + + for( int ii = 0; ii < m_grid->GetNumberRows(); ++ii ) + m_signals->push_back( m_grid->GetCellValue( ii, 0 ) ); + + return true; +} + + +void DIALOG_USER_DEFINED_SIGNALS::OnFormattingHelp( wxHyperlinkEvent& aEvent ) +{ + m_helpWindow = SCH_TEXT::ShowSyntaxHelp( this ); +} + + diff --git a/eeschema/dialogs/dialog_user_defined_signals.h b/eeschema/dialogs/dialog_user_defined_signals.h new file mode 100644 index 0000000000..3e6075e423 --- /dev/null +++ b/eeschema/dialogs/dialog_user_defined_signals.h @@ -0,0 +1,61 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * 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: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef DIALOG_USER_DEFINED_SIGNALS_H +#define DIALOG_USER_DEFINED_SIGNALS_H + +#include + + +class SIM_PLOT_FRAME; +class SCINTILLA_TRICKS; +class HTML_MESSAGE_BOX; + + +class DIALOG_USER_DEFINED_SIGNALS : public DIALOG_USER_DEFINED_SIGNALS_BASE +{ +public: + DIALOG_USER_DEFINED_SIGNALS( SIM_PLOT_FRAME* parent, std::vector* aSignals ); + ~DIALOG_USER_DEFINED_SIGNALS(); + +private: + void addGridRow( const wxString& aValue ); + + void onAddSignal( wxCommandEvent& event ) override; + void onDeleteSignal( wxCommandEvent& event ) override; + void onScintillaCharAdded( wxStyledTextEvent &aEvent, SCINTILLA_TRICKS* aTricks ); + void OnFormattingHelp( wxHyperlinkEvent& aEvent ) override; + + bool TransferDataToWindow() override; + bool TransferDataFromWindow() override; + +private: + SIM_PLOT_FRAME* m_frame; + std::vector* m_signals; + + HTML_MESSAGE_BOX* m_helpWindow; +}; + + + +#endif // DIALOG_USER_DEFINED_SIGNALS_H diff --git a/eeschema/dialogs/dialog_user_defined_signals_base.cpp b/eeschema/dialogs/dialog_user_defined_signals_base.cpp new file mode 100644 index 0000000000..aad15c505b --- /dev/null +++ b/eeschema/dialogs/dialog_user_defined_signals_base.cpp @@ -0,0 +1,114 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "widgets/std_bitmap_button.h" +#include "widgets/wx_grid.h" +#include "widgets/wx_infobar.h" + +#include "dialog_user_defined_signals_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_USER_DEFINED_SIGNALS_BASE::DIALOG_USER_DEFINED_SIGNALS_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bMainSizer; + bMainSizer = new wxBoxSizer( wxVERTICAL ); + + m_infoBar = new WX_INFOBAR( this ); + m_infoBar->SetShowHideEffects( wxSHOW_EFFECT_NONE, wxSHOW_EFFECT_NONE ); + m_infoBar->SetEffectDuration( 500 ); + m_infoBar->Hide(); + + bMainSizer->Add( m_infoBar, 0, wxEXPAND|wxBOTTOM, 5 ); + + m_grid = new WX_GRID( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + + // Grid + m_grid->CreateGrid( 0, 1 ); + m_grid->EnableEditing( true ); + m_grid->EnableGridLines( true ); + m_grid->EnableDragGridSize( false ); + m_grid->SetMargins( 0, 0 ); + + // Columns + m_grid->SetColSize( 0, 400 ); + m_grid->EnableDragColMove( false ); + m_grid->EnableDragColSize( true ); + m_grid->SetColLabelSize( 0 ); + m_grid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + + // Rows + m_grid->EnableDragRowSize( false ); + m_grid->SetRowLabelSize( 0 ); + m_grid->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + + // Label Appearance + + // Cell Defaults + m_grid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); + m_grid->SetMinSize( wxSize( -1,120 ) ); + + bMainSizer->Add( m_grid, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 10 ); + + bButtonSize = new wxBoxSizer( wxHORIZONTAL ); + + m_addButton = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + m_addButton->SetToolTip( _("Add field") ); + + bButtonSize->Add( m_addButton, 0, wxTOP|wxRIGHT, 5 ); + + + bButtonSize->Add( 20, 0, 0, wxEXPAND, 5 ); + + m_deleteButton = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + m_deleteButton->SetToolTip( _("Delete field") ); + + bButtonSize->Add( m_deleteButton, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + + bButtonSize->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_syntaxHelp = new wxHyperlinkCtrl( this, wxID_ANY, _("Syntax help"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_syntaxHelp->SetToolTip( _("Show syntax help window") ); + + bButtonSize->Add( m_syntaxHelp, 0, wxTOP|wxRIGHT, 4 ); + + + bMainSizer->Add( bButtonSize, 0, wxEXPAND|wxRIGHT|wxLEFT, 10 ); + + m_sdbSizer1 = new wxStdDialogButtonSizer(); + m_sdbSizer1OK = new wxButton( this, wxID_OK ); + m_sdbSizer1->AddButton( m_sdbSizer1OK ); + m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL ); + m_sdbSizer1->AddButton( m_sdbSizer1Cancel ); + m_sdbSizer1->Realize(); + + bMainSizer->Add( m_sdbSizer1, 0, wxALL|wxEXPAND, 5 ); + + + this->SetSizer( bMainSizer ); + this->Layout(); + bMainSizer->Fit( this ); + + // Connect Events + m_grid->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_USER_DEFINED_SIGNALS_BASE::onGridCellClick ), NULL, this ); + m_addButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_USER_DEFINED_SIGNALS_BASE::onAddSignal ), NULL, this ); + m_deleteButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_USER_DEFINED_SIGNALS_BASE::onDeleteSignal ), NULL, this ); + m_syntaxHelp->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( DIALOG_USER_DEFINED_SIGNALS_BASE::OnFormattingHelp ), NULL, this ); +} + +DIALOG_USER_DEFINED_SIGNALS_BASE::~DIALOG_USER_DEFINED_SIGNALS_BASE() +{ + // Disconnect Events + m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_USER_DEFINED_SIGNALS_BASE::onGridCellClick ), NULL, this ); + m_addButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_USER_DEFINED_SIGNALS_BASE::onAddSignal ), NULL, this ); + m_deleteButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_USER_DEFINED_SIGNALS_BASE::onDeleteSignal ), NULL, this ); + m_syntaxHelp->Disconnect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( DIALOG_USER_DEFINED_SIGNALS_BASE::OnFormattingHelp ), NULL, this ); + +} diff --git a/eeschema/dialogs/dialog_user_defined_signals_base.fbp b/eeschema/dialogs/dialog_user_defined_signals_base.fbp new file mode 100644 index 0000000000..f5227b478a --- /dev/null +++ b/eeschema/dialogs/dialog_user_defined_signals_base.fbp @@ -0,0 +1,477 @@ + + + + + + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + dialog_user_defined_signals_base + 1000 + none + + + 1 + dialog_user_defined_signals_base + + . + + 1 + 1 + 1 + 1 + UI + 0 + 1 + 0 + + 0 + wxAUI_MGR_DEFAULT + + + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + + DIALOG_USER_DEFINED_SIGNALS_BASE + + -1,-1 + wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER + DIALOG_SHIM; dialog_shim.h + User-defined Signals + + 0 + + + + + + bMainSizer + wxVERTICAL + none + + 5 + wxEXPAND|wxBOTTOM + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 500 + 1 + + 1 + + 0 + 1 + wxSHOW_EFFECT_NONE + wxID_ANY + + 0 + + + 0 + + 1 + m_infoBar + 1 + + + protected + 1 + + Resizable + 1 + wxSHOW_EFFECT_NONE + + WX_INFOBAR; widgets/wx_infobar.h; forward_declare + 0 + + + + + + + + 10 + wxEXPAND|wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + 0 + + + + 1 + + + wxALIGN_LEFT + + wxALIGN_TOP + 0 + 1 + wxALIGN_CENTER + 0 + + wxALIGN_CENTER + 1 + 400 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + 0 + 0 + 1 + 1 + + 1 + + + 1 + 0 + 0 + wxID_ANY + + + + 0 + 0 + + 0 + + + 0 + -1,120 + 1 + m_grid + 1 + + + protected + 1 + + Resizable + wxALIGN_CENTER + 0 + + wxALIGN_CENTER + + 0 + 1 + + WX_GRID; widgets/wx_grid.h; forward_declare + 0 + + + + + onGridCellClick + + + + 10 + wxEXPAND|wxRIGHT|wxLEFT + 0 + + + bButtonSize + wxHORIZONTAL + protected + + 5 + wxTOP|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 1 + + 1 + + + 0 + 0 + wxID_ANY + Add Field + + 0 + + 0 + + + 0 + -1,-1 + 1 + m_addButton + 1 + + + protected + 1 + + + + Resizable + 1 + + + STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare + 0 + Add field + + wxFILTER_NONE + wxDefaultValidator + + + + + onAddSignal + + + + 5 + wxEXPAND + 0 + + 0 + protected + 20 + + + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 1 + + 1 + + + 0 + 0 + wxID_ANY + Delete Field + + 0 + + 0 + + + 0 + -1,-1 + 1 + m_deleteButton + 1 + + + protected + 1 + + + + Resizable + 1 + + + STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare + 0 + Delete field + + wxFILTER_NONE + wxDefaultValidator + + + + + onDeleteSignal + + + + 5 + wxEXPAND + 1 + + 0 + protected + 0 + + + + 4 + wxTOP|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + + wxID_ANY + Syntax help + + 0 + + + 0 + + 1 + m_syntaxHelp + + 1 + + + protected + 1 + + Resizable + 1 + + wxHL_DEFAULT_STYLE + ; ; forward_declare + 0 + Show syntax help window + + + + + + OnFormattingHelp + + + + + + 5 + wxALL|wxEXPAND + 0 + + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + + m_sdbSizer1 + protected + + + + + + diff --git a/eeschema/dialogs/dialog_user_defined_signals_base.h b/eeschema/dialogs/dialog_user_defined_signals_base.h new file mode 100644 index 0000000000..e2048c652d --- /dev/null +++ b/eeschema/dialogs/dialog_user_defined_signals_base.h @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include +class STD_BITMAP_BUTTON; +class WX_GRID; +class WX_INFOBAR; + +#include "dialog_shim.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_USER_DEFINED_SIGNALS_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_USER_DEFINED_SIGNALS_BASE : public DIALOG_SHIM +{ + private: + + protected: + WX_INFOBAR* m_infoBar; + WX_GRID* m_grid; + wxBoxSizer* bButtonSize; + STD_BITMAP_BUTTON* m_addButton; + STD_BITMAP_BUTTON* m_deleteButton; + wxHyperlinkCtrl* m_syntaxHelp; + wxStdDialogButtonSizer* m_sdbSizer1; + wxButton* m_sdbSizer1OK; + wxButton* m_sdbSizer1Cancel; + + // Virtual event handlers, override them in your derived class + virtual void onGridCellClick( wxGridEvent& event ) { event.Skip(); } + virtual void onAddSignal( wxCommandEvent& event ) { event.Skip(); } + virtual void onDeleteSignal( wxCommandEvent& event ) { event.Skip(); } + virtual void OnFormattingHelp( wxHyperlinkEvent& event ) { event.Skip(); } + + + public: + + DIALOG_USER_DEFINED_SIGNALS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("User-defined Signals"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + + ~DIALOG_USER_DEFINED_SIGNALS_BASE(); + +}; + diff --git a/eeschema/sim/ngspice.cpp b/eeschema/sim/ngspice.cpp index f51fa375c7..ce480185b3 100644 --- a/eeschema/sim/ngspice.cpp +++ b/eeschema/sim/ngspice.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2016-2022 CERN - * Copyright (C) 2018-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2018-2023 KiCad Developers, see AUTHORS.txt for contributors. * * @author Tomasz Wlostowski * @author Maciej Suminski @@ -567,7 +567,9 @@ void NGSPICE::init_dll() // Workarounds to avoid hang ups on certain errors // These commands have to be called, no matter what is in the spinit file - Command( "unset interactive" ); + // We have to allow interactive for user-defined signals. Hopefully whatever bug this was + // meant to address has gone away in the last 5 years... + //Command( "unset interactive" ); Command( "set noaskquit" ); Command( "set nomoremode" ); diff --git a/eeschema/sim/sim_plot_frame.cpp b/eeschema/sim/sim_plot_frame.cpp index 8e6238a6a1..d24574b76a 100644 --- a/eeschema/sim/sim_plot_frame.cpp +++ b/eeschema/sim/sim_plot_frame.cpp @@ -56,6 +56,8 @@ #include "sim_plot_panel.h" #include "spice_simulator.h" #include "spice_reporter.h" +#include "core/kicad_algo.h" +#include "fmt/format.h" #include #include @@ -772,16 +774,28 @@ void SIM_PLOT_FRAME::rebuildSignalsList() unconnected.Replace( '(', '_' ); // Convert to SPICE markup auto addSignal = - [&]( const wxString& aSignal ) + [&]( const wxString& aSignal, const wxString& aSpiceVecName = wxEmptyString ) { if( simType == ST_AC ) { - m_signals.push_back( wxString::Format( _( "%s (gain)" ), aSignal ) ); - m_signals.push_back( wxString::Format( _( "%s (phase)" ), aSignal ) ); + wxString gain = _( " (gain)" ); + wxString phase = _( " (phase)" ); + + m_signals.push_back( aSignal + gain ); + m_signals.push_back( aSignal + phase ); + + if( !aSpiceVecName.IsEmpty() ) + { + m_userDefinedSignalToSpiceVecName[ aSignal + gain ] = aSpiceVecName + gain; + m_userDefinedSignalToSpiceVecName[ aSignal + phase ] = aSpiceVecName + phase; + } } else { m_signals.push_back( aSignal ); + + if( !aSpiceVecName.IsEmpty() ) + m_userDefinedSignalToSpiceVecName[ aSignal ] = aSpiceVecName; } }; @@ -795,6 +809,7 @@ void SIM_PLOT_FRAME::rebuildSignalsList() if( netname == "GND" || netname == "0" || netname.StartsWith( unconnected ) ) continue; + m_quotedNetnames[ netname ] = wxString::Format( wxS( "\"%s\"" ), netname ); addSignal( wxString::Format( wxS( "V(%s)" ), netname ) ); } } @@ -838,6 +853,23 @@ void SIM_PLOT_FRAME::rebuildSignalsList() } } + // JEY TODO: find and add LET commands + + // Add user-defined signals + for( int ii = 0; ii < (int) m_userDefinedSignals.size(); ++ii ) + { + static wxRegEx regEx( wxS( "(^|[^a-z0-9_])([VIP])\\(" ), wxRE_ICASE ); + const wxString& signal = m_userDefinedSignals[ii]; + + if( regEx.Matches( signal ) ) + { + wxString vecType = regEx.GetMatch( signal, 2 ); + wxString spiceVecName = wxString::Format( wxS( "%s(user%d)" ), vecType, ii ); + + addSignal( signal, spiceVecName ); + } + } + std::sort( m_signals.begin(), m_signals.end(), []( const wxString& lhs, const wxString& rhs ) { @@ -912,9 +944,6 @@ void SIM_PLOT_FRAME::StartSimulation() if( !LoadSimulator() ) return; - rebuildSignalsList(); - rebuildSignalsGrid( m_filter->GetValue() ); - std::unique_lock simulatorLock( m_simulator->GetMutex(), std::try_to_lock ); if( simulatorLock.owns_lock() ) @@ -996,6 +1025,17 @@ void updateRangeUnits( wxString* aRange, const wxString& aUnits ) } +wxString SIM_PLOT_FRAME::getTraceName( int aRow ) +{ + wxString signalName = m_signalsGrid->GetCellValue( aRow, COL_SIGNAL_NAME ); + + if( alg::contains( m_userDefinedSignals, signalName ) ) + signalName = m_userDefinedSignalToSpiceVecName[ signalName ]; + + return signalName; +} + + void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent ) { if( m_SuppressGridEvents > 0 ) @@ -1009,55 +1049,18 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent ) if( col == COL_SIGNAL_SHOW ) { if( text == wxS( "1" ) ) - { - wxString signalName = m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME ); - wxString baseSignal = signalName; - - if( !signalName.IsEmpty() ) - { - wxString gainSuffix = _( " (gain)" ); - wxString phaseSuffix = _( " (phase)" ); - wxUniChar firstChar = signalName.Upper()[0]; - int traceType = SPT_UNKNOWN; - - if( firstChar == 'V' ) - traceType = SPT_VOLTAGE; - else if( firstChar == 'I' ) - traceType = SPT_CURRENT; - else if( firstChar == 'P' ) - traceType = SPT_POWER; - - if( signalName.EndsWith( gainSuffix ) ) - { - traceType |= SPT_AC_MAG; - baseSignal = signalName.Left( signalName.Length() - gainSuffix.Length() ); - } - else if( signalName.EndsWith( phaseSuffix ) ) - { - traceType |= SPT_AC_PHASE; - baseSignal = signalName.Left( signalName.Length() - phaseSuffix.Length() ); - } - - if( traceType != SPT_UNKNOWN ) - { - addTrace( baseSignal, (SIM_TRACE_TYPE) traceType ); - m_workbookModified = true; - } - } - } + addTrace( getTraceName( row ) ); else - { - removeTrace( m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME ) ); - } + removeTrace( getTraceName( row ) ); // Update enabled/visible states of other controls updateSignalsGrid(); + m_workbookModified = true; } else if( col == COL_SIGNAL_COLOR ) { KIGFX::COLOR4D color( m_signalsGrid->GetCellValue( row, COL_SIGNAL_COLOR ) ); - wxString signalName = m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME ); - TRACE* trace = plot->GetTrace( signalName ); + TRACE* trace = plot->GetTrace( getTraceName( row ) ); if( trace ) { @@ -1071,10 +1074,9 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent ) { for( int ii = 0; ii < m_signalsGrid->GetNumberRows(); ++ii ) { - wxString signalName = m_signalsGrid->GetCellValue( ii, COL_SIGNAL_NAME ); - bool enable = ii == row && text == wxS( "1" ); + bool enable = ii == row && text == wxS( "1" ); - plot->EnableCursor( signalName, col == COL_CURSOR_1 ? 1 : 2, enable ); + plot->EnableCursor( getTraceName( ii ), col == COL_CURSOR_1 ? 1 : 2, enable ); m_workbookModified = true; } @@ -1229,15 +1231,13 @@ void SIM_PLOT_FRAME::updateMeasurement( int aRow ) void SIM_PLOT_FRAME::AddVoltagePlot( const wxString& aNetName ) { - addTrace( aNetName, SPT_VOLTAGE ); - m_workbookModified = true; + doAddPlot( aNetName, SPT_VOLTAGE ); } void SIM_PLOT_FRAME::AddCurrentPlot( const wxString& aDeviceName ) { - addTrace( aDeviceName, SPT_CURRENT ); - m_workbookModified = true; + doAddPlot( aDeviceName, SPT_CURRENT ); } @@ -1357,7 +1357,7 @@ const NGSPICE_CIRCUIT_MODEL* SIM_PLOT_FRAME::GetExporter() const } -void SIM_PLOT_FRAME::addTrace( const wxString& aName, SIM_TRACE_TYPE aType ) +void SIM_PLOT_FRAME::doAddPlot( const wxString& aName, SIM_TRACE_TYPE aType ) { SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); @@ -1398,6 +1398,64 @@ void SIM_PLOT_FRAME::addTrace( const wxString& aName, SIM_TRACE_TYPE aType ) } updateSignalsGrid(); + m_workbookModified = true; +} + + +void SIM_PLOT_FRAME::SetUserDefinedSignals( const std::vector& aNewSignals ) +{ + for( const wxString& signal : m_userDefinedSignals ) + { + if( !alg::contains( aNewSignals, signal ) ) + removeTrace( m_userDefinedSignalToSpiceVecName[ signal ] ); + } + + m_userDefinedSignals = aNewSignals; + + if( m_simFinished ) + applyUserDefinedSignals(); + + rebuildSignalsList(); + rebuildSignalsGrid( m_filter->GetValue() ); + updateSignalsGrid(); + m_workbookModified = true; +} + + +void SIM_PLOT_FRAME::addTrace( const wxString& aSignalName ) +{ + if( aSignalName.IsEmpty() ) + return; + + wxString baseSignal = aSignalName; + wxString gainSuffix = _( " (gain)" ); + wxString phaseSuffix = _( " (phase)" ); + wxUniChar firstChar = aSignalName.Upper()[0]; + int traceType = SPT_UNKNOWN; + + if( firstChar == 'V' ) + traceType = SPT_VOLTAGE; + else if( firstChar == 'I' ) + traceType = SPT_CURRENT; + else if( firstChar == 'P' ) + traceType = SPT_POWER; + + if( aSignalName.EndsWith( gainSuffix ) ) + { + traceType |= SPT_AC_MAG; + baseSignal = aSignalName.Left( aSignalName.Length() - gainSuffix.Length() ); + } + else if( aSignalName.EndsWith( phaseSuffix ) ) + { + traceType |= SPT_AC_PHASE; + baseSignal = aSignalName.Left( aSignalName.Length() - phaseSuffix.Length() ); + } + + if( traceType != SPT_UNKNOWN ) + { + if( SIM_PLOT_PANEL* plotPanel = GetCurrentPlot() ) + updateTrace( baseSignal, (SIM_TRACE_TYPE) traceType, plotPanel ); + } } @@ -1425,6 +1483,9 @@ void SIM_PLOT_FRAME::updateTrace( const wxString& aName, SIM_TRACE_TYPE aTraceTy { SIM_TYPE simType = NGSPICE_CIRCUIT_MODEL::CommandToSimType( aPlotPanel->GetSimCommand() ); + aTraceType = (SIM_TRACE_TYPE) ( aTraceType & SPT_Y_AXIS_MASK ); + aTraceType = (SIM_TRACE_TYPE) ( aTraceType | getXAxisType( simType ) ); + wxString traceTitle = aName; wxString vectorName = aName; @@ -1538,9 +1599,7 @@ void SIM_PLOT_FRAME::updateSignalsGrid() for( int row = 0; row < m_signalsGrid->GetNumberRows(); ++row ) { - wxString signal = m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME ); - - if( TRACE* trace = plot->GetTrace( signal ) ) + if( TRACE* trace = plot->GetTrace( getTraceName( row ) ) ) { m_signalsGrid->SetCellValue( row, COL_SIGNAL_SHOW, wxS( "1" ) ); @@ -1598,6 +1657,27 @@ void SIM_PLOT_FRAME::updateSignalsGrid() } +void SIM_PLOT_FRAME::applyUserDefinedSignals() +{ + auto quoteNetNames = + [&]( wxString aExpression ) -> wxString + { + for( const auto& [netname, quotedNetname] : m_quotedNetnames ) + aExpression.Replace( netname, quotedNetname ); + + return aExpression; + }; + + for( int ii = 0; ii < (int) m_userDefinedSignals.size(); ++ii ) + { + wxString signal = m_userDefinedSignals[ii].Lower(); + std::string cmd = "let user{} = {}"; + + m_simulator->Command( "echo " + fmt::format(cmd, ii, signal.ToStdString() ) ); + m_simulator->Command( fmt::format( cmd, ii, quoteNetNames( signal ).ToStdString() ) ); + } +} + void SIM_PLOT_FRAME::applyTuners() { wxString errors; @@ -1745,33 +1825,6 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath ) return false; } - if( version <= 2 ) - { - long legacyTraceType = traceType; - traceType = 0; - - if( legacyTraceType & LEGACY_SPT_VOLTAGE ) - traceType |= SPT_VOLTAGE; - - if( legacyTraceType & LEGACY_SPT_CURRENT ) - traceType |= SPT_CURRENT; - - if( legacyTraceType & LEGACY_SPT_AC_PHASE ) - traceType |= SPT_AC_PHASE; - - if( legacyTraceType & LEGACY_SPT_AC_MAG ) - traceType |= SPT_AC_MAG; - - if( legacyTraceType & LEGACY_SPT_TIME ) - traceType |= SPT_TIME; - - if( legacyTraceType & LEGACY_SPT_LIN_FREQUENCY ) - traceType |= SPT_LIN_FREQUENCY; - - if( legacyTraceType & LEGACY_SPT_SWEEP ) - traceType |= SPT_SWEEP; - } - name = file.GetNextLine(); if( name.IsEmpty() ) @@ -1784,7 +1837,7 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath ) param = file.GetNextLine(); - addTrace( name, (SIM_TRACE_TYPE) traceType ); + addTrace( name ); SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); TRACE* trace = plotPanel ? plotPanel->GetTrace( name ) : nullptr; @@ -2459,6 +2512,8 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent ) m_simFinished = true; + applyUserDefinedSignals(); + // If there are any signals plotted, update them if( SIM_PANEL_BASE::IsPlottable( simType ) ) { @@ -2487,6 +2542,8 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent ) updateTrace( trace.m_name, trace.m_type, plotPanel ); rebuildSignalsGrid( m_filter->GetValue() ); + updateSignalsGrid(); + plotPanel->GetPlotWin()->UpdateAll(); plotPanel->ResetScales(); } diff --git a/eeschema/sim/sim_plot_frame.h b/eeschema/sim/sim_plot_frame.h index 895751cf6b..518f4de737 100644 --- a/eeschema/sim/sim_plot_frame.h +++ b/eeschema/sim/sim_plot_frame.h @@ -85,6 +85,11 @@ public: */ bool EditSimCommand(); + const std::vector& Signals() { return m_signals; } + + const std::vector& UserDefinedSignals() { return m_userDefinedSignals; } + void SetUserDefinedSignals( const std::vector& aSignals ); + /** * Add a voltage plot for a given net name. * @@ -255,7 +260,14 @@ private: * @param aType describes the type of plot. * @param aParam is the parameter for the device/net (e.g. I, Id, V). */ - void addTrace( const wxString& aName, SIM_TRACE_TYPE aType ); + void doAddPlot( const wxString& aName, SIM_TRACE_TYPE aType ); + + void addTrace( const wxString& aSignalName ); + + /** + * For user-defined traces we have a separate SPICE vector name. + */ + wxString getTraceName( int aRow ); /** * Remove a plot with a specific title. @@ -302,6 +314,11 @@ private: */ void updateMeasurement( int aRow ); + /** + * Apply user-defined signals to the SPICE session. + */ + void applyUserDefinedSignals(); + /** * Apply component values specified using tuner sliders to the current netlist. */ @@ -365,8 +382,15 @@ private: SIM_THREAD_REPORTER* m_reporter; std::vector m_signals; + std::vector m_userDefinedSignals; + std::map m_userDefinedSignalToSpiceVecName; std::list m_tuners; + ///< SPICE expressions need quoted versions of the netnames since KiCad allows '-' and '/' + ///< in netnames. + std::map m_quotedNetnames; + + ///< Panel that was used as the most recent one for simulations SIM_PANEL_BASE* m_lastSimPlot; diff --git a/eeschema/sim/sim_plot_panel.cpp b/eeschema/sim/sim_plot_panel.cpp index 2313a4b6ab..166b22fc2e 100644 --- a/eeschema/sim/sim_plot_panel.cpp +++ b/eeschema/sim/sim_plot_panel.cpp @@ -355,7 +355,7 @@ void CURSOR::Plot( wxDC& aDC, mpWindow& aWindow ) bool CURSOR::Inside( const wxPoint& aPoint ) const { - if( !m_window ) + if( !m_window || !m_trace ) return false; return ( std::abs( (double) aPoint.x - diff --git a/eeschema/sim/sim_types.h b/eeschema/sim/sim_types.h index 703292b102..e125ab160e 100644 --- a/eeschema/sim/sim_types.h +++ b/eeschema/sim/sim_types.h @@ -43,37 +43,24 @@ enum SIM_TYPE }; ///< Possible plot types -enum LEGACY_SIM_TRACE_TYPE -{ - // Y axis - LEGACY_SPT_VOLTAGE = 0x01, - LEGACY_SPT_CURRENT = 0x02, - LEGACY_SPT_AC_PHASE = 0x04, - LEGACY_SPT_AC_MAG = 0x08, - - // X axis - LEGACY_SPT_TIME = 0x10, - LEGACY_SPT_LIN_FREQUENCY = 0x20, - LEGACY_SPT_SWEEP = 0x40 -}; - - enum SIM_TRACE_TYPE { // Y axis - SPT_VOLTAGE = 0x01, - SPT_CURRENT = 0x02, - SPT_AC_PHASE = 0x04, - SPT_AC_MAG = 0x08, - SPT_POWER = 0x10, + SPT_VOLTAGE = 0x0001, + SPT_CURRENT = 0x0002, + SPT_AC_PHASE = 0x0004, + SPT_AC_MAG = 0x0008, + SPT_POWER = 0x0010, + SPT_Y_AXIS_MASK = 0x00FF, // X axis SPT_TIME = 0x0100, SPT_LIN_FREQUENCY = 0x0200, SPT_LOG_FREQUENCY = 0x0400, SPT_SWEEP = 0x0800, + SPT_X_AXIS_MASK = 0xFF00, - SPT_UNKNOWN = 0x00 + SPT_UNKNOWN = 0x0000 }; #endif /* SIM_TYPES_H */ diff --git a/eeschema/sim/spice_settings.cpp b/eeschema/sim/spice_settings.cpp index ee206b9463..2382d169b4 100644 --- a/eeschema/sim/spice_settings.cpp +++ b/eeschema/sim/spice_settings.cpp @@ -50,10 +50,10 @@ bool SPICE_SIMULATOR_SETTINGS::operator==( const SPICE_SIMULATOR_SETTINGS &aRhs NGSPICE_SIMULATOR_SETTINGS::NGSPICE_SIMULATOR_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : SPICE_SIMULATOR_SETTINGS( aParent, aPath ), - m_modelMode( NGSPICE_MODEL_MODE::USER_CONFIG ) + m_modelMode( NGSPICE_MODEL_MODE::LT_PSPICE ) { m_params.emplace_back( new PARAM_ENUM( "model_mode", &m_modelMode, - NGSPICE_MODEL_MODE::USER_CONFIG, + NGSPICE_MODEL_MODE::LT_PSPICE, NGSPICE_MODEL_MODE::USER_CONFIG, NGSPICE_MODEL_MODE::HSPICE ) ); } diff --git a/eeschema/sim/toolbars_sim_plot_frame.cpp b/eeschema/sim/toolbars_sim_plot_frame.cpp index 51258733c2..7178664e58 100644 --- a/eeschema/sim/toolbars_sim_plot_frame.cpp +++ b/eeschema/sim/toolbars_sim_plot_frame.cpp @@ -62,6 +62,7 @@ void SIM_PLOT_FRAME::ReCreateHToolbar() m_toolBar->Add( EE_ACTIONS::simTune ); m_toolBar->AddScaledSeparator( this ); + m_toolBar->Add( EE_ACTIONS::editUserDefinedSignals ); m_toolBar->Add( EE_ACTIONS::showNetlist ); // after adding the buttons to the toolbar, must call Realize() to reflect the changes diff --git a/eeschema/tools/ee_actions.cpp b/eeschema/tools/ee_actions.cpp index 236b696a9d..618d585553 100644 --- a/eeschema/tools/ee_actions.cpp +++ b/eeschema/tools/ee_actions.cpp @@ -989,3 +989,9 @@ TOOL_ACTION EE_ACTIONS::showNetlist( "eeschema.Simulation.showNetlist", _( "Show SPICE Netlist" ), "", BITMAPS::netlist ); +TOOL_ACTION EE_ACTIONS::editUserDefinedSignals( "eeschema.Simulation.editUserDefinedSignals", + AS_GLOBAL, 0, "", + _( "User-defined Signals" ), + _( "Add, edit or delete user-defined simulation signals" ), + BITMAPS::sim_add_signal ); + diff --git a/eeschema/tools/ee_actions.h b/eeschema/tools/ee_actions.h index c79cd9f88f..78e71af0d7 100644 --- a/eeschema/tools/ee_actions.h +++ b/eeschema/tools/ee_actions.h @@ -258,6 +258,7 @@ public: static TOOL_ACTION simCommand; static TOOL_ACTION runSimulation; static TOOL_ACTION stopSimulation; + static TOOL_ACTION editUserDefinedSignals; static TOOL_ACTION showNetlist; // Net highlighting diff --git a/eeschema/tools/simulator_control.cpp b/eeschema/tools/simulator_control.cpp index f292b72c2d..62a0e276bb 100644 --- a/eeschema/tools/simulator_control.cpp +++ b/eeschema/tools/simulator_control.cpp @@ -36,6 +36,7 @@ #include #include #include +#include bool SIMULATOR_CONTROL::Init() @@ -377,6 +378,19 @@ public: }; +int SIMULATOR_CONTROL::EditUserDefinedSignals( const TOOL_EVENT& aEvent ) +{ + std::vector userSignals = m_plotFrame->UserDefinedSignals(); + + DIALOG_USER_DEFINED_SIGNALS dlg( m_plotFrame, &userSignals ); + + if( dlg.ShowQuasiModal() == wxID_OK ) + m_plotFrame->SetUserDefinedSignals( userSignals ); + + return 0; +} + + int SIMULATOR_CONTROL::ShowNetlist( const TOOL_EVENT& aEvent ) { if( m_schematicFrame == nullptr || m_simulator == nullptr ) @@ -420,5 +434,6 @@ void SIMULATOR_CONTROL::setTransitions() Go( &SIMULATOR_CONTROL::Probe, EE_ACTIONS::simProbe.MakeEvent() ); Go( &SIMULATOR_CONTROL::Tune, EE_ACTIONS::simTune.MakeEvent() ); + Go( &SIMULATOR_CONTROL::EditUserDefinedSignals, EE_ACTIONS::editUserDefinedSignals.MakeEvent() ); Go( &SIMULATOR_CONTROL::ShowNetlist, EE_ACTIONS::showNetlist.MakeEvent() ); } diff --git a/eeschema/tools/simulator_control.h b/eeschema/tools/simulator_control.h index 070a36f675..6545ce980f 100644 --- a/eeschema/tools/simulator_control.h +++ b/eeschema/tools/simulator_control.h @@ -70,6 +70,7 @@ public: int Probe( const TOOL_EVENT& aEvent ); int Tune( const TOOL_EVENT& aEvent ); + int EditUserDefinedSignals( const TOOL_EVENT& aEvent ); int ShowNetlist( const TOOL_EVENT& aEvent ); private: diff --git a/include/widgets/grid_text_helpers.h b/include/widgets/grid_text_helpers.h index d6f7cd56a7..279df14ff4 100644 --- a/include/widgets/grid_text_helpers.h +++ b/include/widgets/grid_text_helpers.h @@ -47,13 +47,14 @@ public: class GRID_CELL_STC_EDITOR : public wxGridCellEditor { public: - GRID_CELL_STC_EDITOR( std::function aOnChar ); + GRID_CELL_STC_EDITOR( bool aIgnoreCase, + std::function aOnChar ); void Create( wxWindow* aParent, wxWindowID aId, wxEvtHandler* aEventHandler ) override; wxGridCellEditor* Clone() const override { - return new GRID_CELL_STC_EDITOR( m_onChar ); + return new GRID_CELL_STC_EDITOR( m_ignoreCase, m_onChar ); } wxString GetValue() const override; @@ -71,6 +72,7 @@ protected: protected: SCINTILLA_TRICKS* m_scintillaTricks; + bool m_ignoreCase; wxString m_value; std::function m_onChar;