diff --git a/common/eda_pattern_match.cpp b/common/eda_pattern_match.cpp index e1c4f3d222..43070d3d45 100644 --- a/common/eda_pattern_match.cpp +++ b/common/eda_pattern_match.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2017 Chris Pavlina - * Copyright (C) 2015-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2015-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 @@ -386,6 +386,12 @@ EDA_COMBINED_MATCHER::EDA_COMBINED_MATCHER( const wxString& aPattern, AddMatcher( aPattern, std::make_unique() ); AddMatcher( aPattern, std::make_unique() ); break; + + case CTX_SIGNAL: + AddMatcher( aPattern, std::make_unique() ); + AddMatcher( aPattern, std::make_unique() ); + AddMatcher( aPattern, std::make_unique() ); + break; } } diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index e872e547b0..5ea5820f07 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -345,8 +345,6 @@ set( EESCHEMA_COMMON_SRCS if( KICAD_SPICE ) set( EESCHEMA_SRCS ${EESCHEMA_SRCS} - dialogs/dialog_signal_list.cpp - dialogs/dialog_signal_list_base.cpp dialogs/dialog_sim_command.cpp dialogs/dialog_sim_command_base.cpp dialogs/dialog_sim_model.cpp diff --git a/eeschema/dialogs/dialog_signal_list.cpp b/eeschema/dialogs/dialog_signal_list.cpp deleted file mode 100644 index fee4d6405f..0000000000 --- a/eeschema/dialogs/dialog_signal_list.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2016 CERN - * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. - * - * @author Maciej Suminski - * - * 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 3 - * 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: - * https://www.gnu.org/licenses/gpl-3.0.html - * or you may search the http://www.gnu.org website for the version 3 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "dialog_signal_list.h" -#include -#include - -#include -#include - - -DIALOG_SIGNAL_LIST::DIALOG_SIGNAL_LIST( SIM_PLOT_FRAME* aParent, - NGSPICE_CIRCUIT_MODEL* aCircuitModel ) : - DIALOG_SIGNAL_LIST_BASE( aParent ), - m_plotFrame( aParent ), - m_circuitModel( aCircuitModel ) -{ - -} - - -bool DIALOG_SIGNAL_LIST::TransferDataFromWindow() -{ - if( !DIALOG_SIGNAL_LIST_BASE::TransferDataFromWindow() ) - return false; - - addSelectionToPlotFrame(); - - return true; -} - - -bool DIALOG_SIGNAL_LIST::TransferDataToWindow() -{ - // Create a list of possible signals - /// TODO: it could include separated mag & phase for AC analysis - if( m_circuitModel ) - { - // Voltage list - for( const auto& net : m_circuitModel->GetNets() ) - { - // netnames are escaped (can contain "{slash}" for '/') Unscape them: - wxString netname = UnescapeString( net ); - - if( netname != "GND" && netname != "0" ) - m_signals->Append( wxString::Format( "V(%s)", netname ) ); - } - - auto simType = m_circuitModel->GetSimType(); - - if( simType == ST_TRANSIENT || simType == ST_DC ) - { - for( const SPICE_ITEM& item : m_circuitModel->GetItems() ) - { - // Add all possible currents for the primitive. - for( const std::string& name : item.model->SpiceGenerator().CurrentNames( item ) ) - m_signals->Append( name ); - } - } - } - - bool success = DIALOG_SIGNAL_LIST_BASE::TransferDataToWindow(); - - // Now all widgets have the size fixed, call FinishDialogSettings - finishDialogSettings(); - - return success; -} - - -bool DIALOG_SIGNAL_LIST::addSignalToPlotFrame( const wxString& aPlotName ) -{ - - // Get the part in the parentheses - wxString name = aPlotName.AfterFirst( '(' ).BeforeLast( ')' ); - - if( !name.IsEmpty() ) - { - wxUniChar firstChar = aPlotName[0]; - - if( firstChar == 'V' || firstChar == 'v' ) - m_plotFrame->AddVoltagePlot( aPlotName ); - else if( firstChar == 'I' || firstChar == 'i' ) - m_plotFrame->AddCurrentPlot( aPlotName ); - else - return false; - } - else - { - return false; - } - - return true; -} - - -void DIALOG_SIGNAL_LIST::addSelectionToPlotFrame() -{ - for( int i = 0; i < (int) m_signals->GetCount(); ++i ) - { - if( m_signals->IsSelected( i ) ) - { - const wxString& plotName = m_signals->GetString( i ); - - if( !addSignalToPlotFrame( plotName ) ) - wxASSERT_MSG( false, "Unhandled plot type" ); - } - } - - // Add manually entered signal, if any - const wxString& plotName = m_signalEntry->GetValue(); - - if( !plotName.IsEmpty() ) - { - if( !addSignalToPlotFrame( plotName ) ) - m_plotFrame->AddVoltagePlot( plotName ); // Assume it's a V plot by default - - m_signalEntry->SetSelection( -1, -1 ); - } -} diff --git a/eeschema/dialogs/dialog_signal_list.h b/eeschema/dialogs/dialog_signal_list.h deleted file mode 100644 index a6ad3397c6..0000000000 --- a/eeschema/dialogs/dialog_signal_list.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2016 CERN - * @author Maciej Suminski - * - * 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 3 - * 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: - * https://www.gnu.org/licenses/gpl-3.0.html - * or you may search the http://www.gnu.org website for the version 3 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifndef DIALOG_SIGNAL_LIST_H -#define DIALOG_SIGNAL_LIST_H - -#include "dialog_signal_list_base.h" - -class SIM_PLOT_FRAME; -class NGSPICE_CIRCUIT_MODEL; - -class DIALOG_SIGNAL_LIST : public DIALOG_SIGNAL_LIST_BASE -{ -public: - DIALOG_SIGNAL_LIST( SIM_PLOT_FRAME* aParent, NGSPICE_CIRCUIT_MODEL* aCircuitModel ); - - bool TransferDataFromWindow() override; - bool TransferDataToWindow() override; - -private: - void onSignalAdd( wxCommandEvent& event ) override - { - addSelectionToPlotFrame(); - m_sdbSizerCancel->SetLabel( _( "Done" ) ); - } - - void addSelectionToPlotFrame(); - bool addSignalToPlotFrame( const wxString& aPlotName ); - - SIM_PLOT_FRAME* m_plotFrame; - NGSPICE_CIRCUIT_MODEL* m_circuitModel; -}; - -#endif /* DIALOG_SIGNAL_LIST_H */ diff --git a/eeschema/dialogs/dialog_signal_list_base.cpp b/eeschema/dialogs/dialog_signal_list_base.cpp deleted file mode 100644 index 10ab43a4d7..0000000000 --- a/eeschema/dialogs/dialog_signal_list_base.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b) -// http://www.wxformbuilder.org/ -// -// PLEASE DO *NOT* EDIT THIS FILE! -/////////////////////////////////////////////////////////////////////////// - -#include "dialog_signal_list_base.h" - -/////////////////////////////////////////////////////////////////////////// - -DIALOG_SIGNAL_LIST_BASE::DIALOG_SIGNAL_LIST_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( wxSize( -1,-1 ), wxDefaultSize ); - - wxBoxSizer* bSizer6; - bSizer6 = new wxBoxSizer( wxVERTICAL ); - - m_signals = new wxListBox( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_EXTENDED|wxLB_NEEDED_SB|wxLB_SORT ); - m_signals->SetMinSize( wxSize( 450,400 ) ); - - bSizer6->Add( m_signals, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 10 ); - - wxBoxSizer* bSizer2; - bSizer2 = new wxBoxSizer( wxVERTICAL ); - - m_staticText1 = new wxStaticText( this, wxID_ANY, _("Add signal by name:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText1->Wrap( -1 ); - bSizer2->Add( m_staticText1, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - - m_signalEntry = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); - bSizer2->Add( m_signalEntry, 0, wxALL|wxEXPAND, 5 ); - - - bSizer6->Add( bSizer2, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); - - m_sdbSizer = new wxStdDialogButtonSizer(); - m_sdbSizerOK = new wxButton( this, wxID_OK ); - m_sdbSizer->AddButton( m_sdbSizerOK ); - m_sdbSizerCancel = new wxButton( this, wxID_CANCEL ); - m_sdbSizer->AddButton( m_sdbSizerCancel ); - m_sdbSizer->Realize(); - - bSizer6->Add( m_sdbSizer, 0, wxEXPAND|wxALL, 5 ); - - - this->SetSizer( bSizer6 ); - this->Layout(); - bSizer6->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - m_signals->Connect( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, wxCommandEventHandler( DIALOG_SIGNAL_LIST_BASE::onSignalAdd ), NULL, this ); - m_signalEntry->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_SIGNAL_LIST_BASE::onSignalAdd ), NULL, this ); -} - -DIALOG_SIGNAL_LIST_BASE::~DIALOG_SIGNAL_LIST_BASE() -{ - // Disconnect Events - m_signals->Disconnect( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, wxCommandEventHandler( DIALOG_SIGNAL_LIST_BASE::onSignalAdd ), NULL, this ); - m_signalEntry->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_SIGNAL_LIST_BASE::onSignalAdd ), NULL, this ); - -} diff --git a/eeschema/dialogs/dialog_signal_list_base.fbp b/eeschema/dialogs/dialog_signal_list_base.fbp deleted file mode 100644 index 43ebbfcf2d..0000000000 --- a/eeschema/dialogs/dialog_signal_list_base.fbp +++ /dev/null @@ -1,286 +0,0 @@ - - - - - - C++ - 1 - source_name - 0 - 0 - res - UTF-8 - connect - dialog_signal_list_base - 1000 - none - - - 1 - DIALOG_SIGNAL_LIST_BASE - - . - - 1 - 1 - 1 - 1 - UI - 0 - 0 - 0 - - 0 - wxAUI_MGR_DEFAULT - - wxBOTH - - 1 - 1 - impl_virtual - - - - 0 - wxID_ANY - - -1,-1 - DIALOG_SIGNAL_LIST_BASE - - -1,-1 - wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER - DIALOG_SHIM; dialog_shim.h - Add Signals - - 0 - - - - - - bSizer6 - wxVERTICAL - none - - 10 - wxEXPAND|wxTOP|wxRIGHT|wxLEFT - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - 450,400 - 1 - m_signals - 1 - - - protected - 1 - - Resizable - 1 - - wxLB_EXTENDED|wxLB_NEEDED_SB|wxLB_SORT - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - onSignalAdd - - - - 5 - wxEXPAND|wxTOP|wxRIGHT|wxLEFT - 0 - - - bSizer2 - wxVERTICAL - none - - 5 - wxTOP|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Add signal by name: - 0 - - 0 - - - 0 - - 1 - m_staticText1 - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - - - -1 - - - - 5 - wxALL|wxEXPAND - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - - 0 - - 1 - m_signalEntry - 1 - - - protected - 1 - - Resizable - 1 - - wxTE_PROCESS_ENTER - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - onSignalAdd - - - - - - 5 - wxEXPAND|wxALL - 0 - - 0 - 1 - 0 - 0 - 0 - 1 - 0 - 0 - - m_sdbSizer - protected - - - - - - diff --git a/eeschema/dialogs/dialog_signal_list_base.h b/eeschema/dialogs/dialog_signal_list_base.h deleted file mode 100644 index 0a5bbdc36c..0000000000 --- a/eeschema/dialogs/dialog_signal_list_base.h +++ /dev/null @@ -1,55 +0,0 @@ -/////////////////////////////////////////////////////////////////////////// -// 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 -#include "dialog_shim.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/////////////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////////////////// -/// Class DIALOG_SIGNAL_LIST_BASE -/////////////////////////////////////////////////////////////////////////////// -class DIALOG_SIGNAL_LIST_BASE : public DIALOG_SHIM -{ - private: - - protected: - wxListBox* m_signals; - wxStaticText* m_staticText1; - wxTextCtrl* m_signalEntry; - wxStdDialogButtonSizer* m_sdbSizer; - wxButton* m_sdbSizerOK; - wxButton* m_sdbSizerCancel; - - // Virtual event handlers, override them in your derived class - virtual void onSignalAdd( wxCommandEvent& event ) { event.Skip(); } - - - public: - - DIALOG_SIGNAL_LIST_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Add Signals"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - - ~DIALOG_SIGNAL_LIST_BASE(); - -}; - diff --git a/eeschema/dialogs/dialog_symbol_fields_table.cpp b/eeschema/dialogs/dialog_symbol_fields_table.cpp index 12c79741a5..57974b6c25 100644 --- a/eeschema/dialogs/dialog_symbol_fields_table.cpp +++ b/eeschema/dialogs/dialog_symbol_fields_table.cpp @@ -1175,6 +1175,7 @@ void DIALOG_SYMBOL_FIELDS_TABLE::OnFilterMouseMoved( wxMouseEvent& aEvent ) SetCursor( wxCURSOR_IBEAM ); } + void DIALOG_SYMBOL_FIELDS_TABLE::OnFieldsCtrlSelectionChanged( wxDataViewEvent& event ) { int row = m_fieldsCtrl->GetSelectedRow(); diff --git a/eeschema/sim/ngspice_circuit_model.cpp b/eeschema/sim/ngspice_circuit_model.cpp index 398f16859b..630606d60d 100644 --- a/eeschema/sim/ngspice_circuit_model.cpp +++ b/eeschema/sim/ngspice_circuit_model.cpp @@ -30,8 +30,8 @@ #include -SIM_PLOT_TYPE NGSPICE_CIRCUIT_MODEL::VectorToSignal( const std::string& aVector, - wxString& aSignal ) const +SIM_TRACE_TYPE NGSPICE_CIRCUIT_MODEL::VectorToSignal( const std::string& aVector, + wxString& aSignal ) const { using namespace std; diff --git a/eeschema/sim/ngspice_circuit_model.h b/eeschema/sim/ngspice_circuit_model.h index faecc687a7..6ed25a7bb6 100644 --- a/eeschema/sim/ngspice_circuit_model.h +++ b/eeschema/sim/ngspice_circuit_model.h @@ -55,14 +55,14 @@ public: virtual ~NGSPICE_CIRCUIT_MODEL() {} /** - * Return name of Spice dataset for a specific plot. + * Return name of Spice dataset for a specific trace. * * @param aVector is name of the vector produced by ngspice * @param [out] aSignal is output in form: V(R1), Ib(Q2), I(L8) - * @return [SPT_VOLTAGE, SPT_CURRENT]. Otherwise SPT_UNKNOWN if vector is - * of different, unsupported type. + * @return [SPT_VOLTAGE, SPT_CURRENT]. Otherwise SPT_UNKNOWN if vector is of different, + * unsupported type. */ - SIM_PLOT_TYPE VectorToSignal( const std::string& aVector, wxString& aSignal ) const; + SIM_TRACE_TYPE VectorToSignal( const std::string& aVector, wxString& aSignal ) const; void SetSimOptions( int aOptions ) { m_options = aOptions; } int GetSimOptions() const { return m_options; } diff --git a/eeschema/sim/sim_plot_frame.cpp b/eeschema/sim/sim_plot_frame.cpp index 849a647ca6..1b67a65741 100644 --- a/eeschema/sim/sim_plot_frame.cpp +++ b/eeschema/sim/sim_plot_frame.cpp @@ -38,6 +38,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -58,11 +62,11 @@ #include -SIM_PLOT_TYPE operator|( SIM_PLOT_TYPE aFirst, SIM_PLOT_TYPE aSecond ) +SIM_TRACE_TYPE operator|( SIM_TRACE_TYPE aFirst, SIM_TRACE_TYPE aSecond ) { int res = (int) aFirst | (int) aSecond; - return (SIM_PLOT_TYPE) res; + return (SIM_TRACE_TYPE) res; } @@ -106,6 +110,25 @@ private: }; +enum SIGNALS_GRID_COLUMNS +{ + COL_SIGNAL_NAME = 0, + COL_SIGNAL_SHOW, + COL_SIGNAL_COLOR, + COL_CURSOR_1, + COL_CURSOR_2 +}; + + +enum CURSORS_GRID_COLUMNS +{ + COL_CURSOR_NAME = 0, + COL_CURSOR_SIGNAL, + COL_CURSOR_X, + COL_CURSOR_Y +}; + + SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : SIM_PLOT_FRAME_BASE( aParent ), m_lastSimPlot( nullptr ), @@ -114,7 +137,6 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : m_simFinished( false ) { SetKiway( this, aKiway ); - m_signalsIconColorList = nullptr; m_schematicFrame = (SCH_EDIT_FRAME*) Kiway().Player( FRAME_SCH, false ); wxASSERT( m_schematicFrame ); @@ -130,6 +152,36 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : // Get the previous size and position of windows: LoadSettings( config() ); + m_signalsGrid->wxGrid::SetLabelFont( KIUI::GetStatusFont( this ) ); + + wxGridCellAttr* attr = new wxGridCellAttr; + attr->SetReadOnly(); + m_signalsGrid->SetColAttr( COL_SIGNAL_NAME, attr ); + + attr = new wxGridCellAttr; + attr->SetRenderer( new wxGridCellBoolRenderer() ); + attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS + attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + m_signalsGrid->SetColAttr( COL_SIGNAL_SHOW, attr ); + + m_signalsGrid->PushEventHandler( new GRID_TRICKS( m_signalsGrid ) ); + + m_cursorsGrid->wxGrid::SetLabelFont( KIUI::GetStatusFont( this ) ); + + attr = new wxGridCellAttr; + attr->SetReadOnly(); + m_cursorsGrid->SetColAttr( COL_CURSOR_NAME, attr ); + + attr = new wxGridCellAttr; + attr->SetReadOnly(); + m_cursorsGrid->SetColAttr( COL_CURSOR_SIGNAL, attr ); + + attr = new wxGridCellAttr; + attr->SetReadOnly(); + m_cursorsGrid->SetColAttr( COL_CURSOR_Y, attr ); + + m_cursorsGrid->PushEventHandler( new GRID_TRICKS( m_cursorsGrid ) ); + // Prepare the color list to plot traces SIM_PLOT_COLORS::FillDefaultColorList( m_darkMode ); @@ -184,12 +236,15 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : SIM_PLOT_FRAME::~SIM_PLOT_FRAME() { + // Delete the GRID_TRICKS. + m_signalsGrid->PopEventHandler( true ); + m_cursorsGrid->PopEventHandler( true ); + NULL_REPORTER devnull; m_simulator->Attach( nullptr, devnull ); m_simulator->SetReporter( nullptr ); delete m_reporter; - delete m_signalsIconColorList; } @@ -230,10 +285,16 @@ void SIM_PLOT_FRAME::ShowChangedLanguage() m_workbook->SetPageText( ii, pageTitle ); } - m_staticTextSignals->SetLabel( _( "Signals" ) ); - updateSignalList(); + m_signalsGrid->SetColLabelValue( COL_SIGNAL_NAME, _( "Signal" ) ); + m_signalsGrid->SetColLabelValue( COL_SIGNAL_SHOW, _( "Plot" ) ); + m_signalsGrid->SetColLabelValue( COL_SIGNAL_COLOR, _( "Color" ) ); + m_signalsGrid->SetColLabelValue( COL_CURSOR_1, _( "Cursor 1" ) ); + m_signalsGrid->SetColLabelValue( COL_CURSOR_2, _( "Cursor 2" ) ); - m_staticTextCursors->SetLabel( _( "Cursors" ) ); + m_cursorsGrid->SetColLabelValue( COL_CURSOR_NAME, _( "Cursor" ) ); + m_cursorsGrid->SetColLabelValue( COL_CURSOR_SIGNAL, _( "Signal" ) ); + m_cursorsGrid->SetColLabelValue( COL_CURSOR_X, _( "Time" ) ); + m_cursorsGrid->SetColLabelValue( COL_CURSOR_Y, _( "Voltage / Current" ) ); wxCommandEvent dummy; onCursorUpdate( dummy ); @@ -373,6 +434,73 @@ void SIM_PLOT_FRAME::setSubWindowsSashSize() } +void SIM_PLOT_FRAME::rebuildSignalsGrid( wxString aFilter ) +{ + m_signalsGrid->ClearRows(); + + if( aFilter.IsEmpty() ) + aFilter = wxS( "*" ); + + EDA_COMBINED_MATCHER matcher( aFilter, CTX_SIGNAL ); + int row = 0; + + for( const wxString& signal : m_signals ) + { + int matches; + int offset; + + if( matcher.Find( signal, matches, offset ) && offset == 0 ) + { + m_signalsGrid->AppendRows( 1 ); + + m_signalsGrid->SetCellValue( row, COL_SIGNAL_NAME, signal ); + + if( TRACE* trace = GetCurrentPlot()->GetTrace( signal ) ) + { + m_signalsGrid->SetCellValue( row, COL_SIGNAL_SHOW, wxS( "1" ) ); + + wxGridCellAttr* attr = new wxGridCellAttr; + attr->SetRenderer( new GRID_CELL_COLOR_RENDERER( this ) ); + attr->SetEditor( new GRID_CELL_COLOR_SELECTOR( this, m_signalsGrid ) ); + attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + m_signalsGrid->SetAttr( row, COL_SIGNAL_COLOR, attr ); + KIGFX::COLOR4D color( trace->GetPen().GetColour() ); + m_signalsGrid->SetCellValue( row, COL_SIGNAL_COLOR, color.ToCSSString() ); + + attr = new wxGridCellAttr; + attr->SetRenderer( new wxGridCellBoolRenderer() ); + attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS + attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + m_signalsGrid->SetAttr( row, COL_CURSOR_1, attr ); + + attr = new wxGridCellAttr; + attr->SetRenderer( new wxGridCellBoolRenderer() ); + attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS + attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + m_signalsGrid->SetAttr( row, COL_CURSOR_2, attr ); + } + else + { + wxGridCellAttr* attr = new wxGridCellAttr; + attr->SetReadOnly(); + m_signalsGrid->SetAttr( row, COL_SIGNAL_COLOR, attr ); + m_signalsGrid->SetCellValue( row, COL_SIGNAL_COLOR, wxEmptyString ); + + attr = new wxGridCellAttr; + attr->SetReadOnly(); + m_signalsGrid->SetAttr( row, COL_CURSOR_1, attr ); + + attr = new wxGridCellAttr; + attr->SetReadOnly(); + m_signalsGrid->SetAttr( row, COL_CURSOR_2, attr ); + } + + row++; + } + } +} + + void SIM_PLOT_FRAME::StartSimulation( const wxString& aSimCommand ) { if( m_circuitModel->CommandToSimType( GetCurrentSimCommand() ) == ST_UNKNOWN ) @@ -423,12 +551,45 @@ void SIM_PLOT_FRAME::StartSimulation( const wxString& aSimCommand ) } } + if( !plotWindow || plotWindow->GetType() != m_circuitModel->GetSimType() ) + { + plotWindow = NewPlotPanel( m_circuitModel->GetSimCommand(), + m_circuitModel->GetSimOptions() ); + } + std::unique_lock simulatorLock( m_simulator->GetMutex(), std::try_to_lock ); if( simulatorLock.owns_lock() ) { wxBusyCursor toggle; + m_signals.clear(); + + // Add voltages + for( const std::string& net : m_circuitModel->GetNets() ) + { + // netnames are escaped (can contain "{slash}" for '/') Unscape them: + wxString netname = UnescapeString( net ); + + if( netname != "GND" && netname != "0" ) + m_signals.push_back( wxString::Format( "V(%s)", netname ) ); + } + + auto simType = m_circuitModel->GetSimType(); + + // Add currents + if( simType == ST_TRANSIENT || simType == ST_DC ) + { + for( const SPICE_ITEM& item : m_circuitModel->GetItems() ) + { + // Add all possible currents for the primitive. + for( const std::string& name : item.model->SpiceGenerator().CurrentNames( item ) ) + m_signals.push_back( name ); + } + } + + rebuildSignalsGrid( m_filter->GetValue() ); + applyTuners(); // Prevents memory leak on succeding simulations by deleting old vectors @@ -442,25 +603,22 @@ void SIM_PLOT_FRAME::StartSimulation( const wxString& aSimCommand ) } -SIM_PANEL_BASE* SIM_PLOT_FRAME::NewPlotPanel( wxString aSimCommand, int aOptions ) +SIM_PANEL_BASE* SIM_PLOT_FRAME::NewPlotPanel( const wxString& aSimCommand, int aOptions ) { SIM_PANEL_BASE* plotPanel = nullptr; SIM_TYPE simType = NGSPICE_CIRCUIT_MODEL::CommandToSimType( aSimCommand ); if( SIM_PANEL_BASE::IsPlottable( simType ) ) { - SIM_PLOT_PANEL* panel; - panel = new SIM_PLOT_PANEL( aSimCommand, aOptions, m_workbook, wxID_ANY ); - - panel->GetPlotWin()->EnableMouseWheelPan( - Pgm().GetCommonSettings()->m_Input.scroll_modifier_zoom != 0 ); - + SIM_PLOT_PANEL* panel = new SIM_PLOT_PANEL( aSimCommand, aOptions, m_workbook, wxID_ANY ); plotPanel = dynamic_cast( panel ); + + COMMON_SETTINGS::INPUT cfg = Pgm().GetCommonSettings()->m_Input; + panel->GetPlotWin()->EnableMouseWheelPan( cfg.scroll_modifier_zoom != 0 ); } else { - SIM_NOPLOT_PANEL* panel; - panel = new SIM_NOPLOT_PANEL( aSimCommand, aOptions, m_workbook, wxID_ANY ); + SIM_NOPLOT_PANEL* panel = new SIM_NOPLOT_PANEL( aSimCommand, aOptions, m_workbook, wxID_ANY ); plotPanel = dynamic_cast( panel ); } @@ -473,15 +631,131 @@ SIM_PANEL_BASE* SIM_PLOT_FRAME::NewPlotPanel( wxString aSimCommand, int aOptions } +void SIM_PLOT_FRAME::OnFilterText( wxCommandEvent& aEvent ) +{ + rebuildSignalsGrid( m_filter->GetValue() ); +} + + +void SIM_PLOT_FRAME::OnFilterMouseMoved( wxMouseEvent& aEvent ) +{ + wxPoint pos = aEvent.GetPosition(); + wxRect ctrlRect = m_filter->GetScreenRect(); + int buttonWidth = ctrlRect.GetHeight(); // Presume buttons are square + + if( m_filter->IsSearchButtonVisible() && pos.x < buttonWidth ) + SetCursor( wxCURSOR_ARROW ); + else if( m_filter->IsCancelButtonVisible() && pos.x > ctrlRect.GetWidth() - buttonWidth ) + SetCursor( wxCURSOR_ARROW ); + else + SetCursor( wxCURSOR_IBEAM ); +} + + +void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent ) +{ + int row = aEvent.GetRow(); + int col = aEvent.GetCol(); + wxString text = m_signalsGrid->GetCellValue( row, col ); + + if( col == COL_SIGNAL_SHOW ) + { + if( text == wxS( "1" ) ) + { + wxString signalName = m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME ); + + if( !signalName.IsEmpty() ) + { + wxUniChar firstChar = signalName[0]; + + if( firstChar == 'V' || firstChar == 'v' ) + addTrace( signalName, SPT_VOLTAGE ); + else if( firstChar == 'I' || firstChar == 'i' ) + addTrace( signalName, SPT_CURRENT ); + } + + if( !GetCurrentPlot()->GetTrace( signalName ) ) + { + aEvent.Veto(); + return; + } + } + else + { + removeTrace( m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME ) ); + } + } + else if( col == COL_CURSOR_1 || col == COL_CURSOR_2 ) + { + SIM_PLOT_PANEL* plot = GetCurrentPlot(); + + 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" ); + + plot->EnableCursor( signalName, col == COL_CURSOR_1 ? 1 : 2, enable ); + } + } + + updateSignalsGrid(); +} + + +void SIM_PLOT_FRAME::onCursorsGridCellChanged( wxGridEvent& aEvent ) +{ + SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); + + if( !plotPanel ) + return; + + int row = aEvent.GetRow(); + int col = aEvent.GetCol(); + wxString text = m_cursorsGrid->GetCellValue( row, col ); + wxString cursorName = m_cursorsGrid->GetCellValue( row, COL_CURSOR_NAME ); + + if( col == COL_CURSOR_X ) + { + CURSOR* cursor1 = nullptr; + CURSOR* cursor2 = nullptr; + + for( const auto& [name, trace] : plotPanel->GetTraces() ) + { + if( CURSOR* cursor = trace->GetCursor( 1 ) ) + cursor1 = cursor; + + if( CURSOR* cursor = trace->GetCursor( 2 ) ) + cursor2 = cursor; + } + + double value = SPICE_VALUE( text ).ToDouble(); + + if( cursorName == wxS( "1" ) && cursor1 ) + cursor1->SetCoordX( value ); + else if( cursorName == wxS( "2" ) && cursor2 ) + cursor2->SetCoordX( value ); + else if( cursorName == _( "Diff" ) && cursor1 && cursor2 ) + cursor2->SetCoordX( cursor1->GetCoords().x + value ); + + wxCommandEvent dummy; + onCursorUpdate( dummy ); + } + else + { + wxFAIL_MSG( wxT( "All other columns are supposed to be read-only!" ) ); + } +} + + void SIM_PLOT_FRAME::AddVoltagePlot( const wxString& aNetName ) { - addPlot( aNetName, SPT_VOLTAGE ); + addTrace( aNetName, SPT_VOLTAGE ); } void SIM_PLOT_FRAME::AddCurrentPlot( const wxString& aDeviceName ) { - addPlot( aDeviceName, SPT_CURRENT ); + addTrace( aDeviceName, SPT_CURRENT ); } @@ -579,7 +853,7 @@ const NGSPICE_CIRCUIT_MODEL* SIM_PLOT_FRAME::GetExporter() const } -void SIM_PLOT_FRAME::addPlot( const wxString& aName, SIM_PLOT_TYPE aType ) +void SIM_PLOT_FRAME::addTrace( const wxString& aName, SIM_TRACE_TYPE aType ) { SIM_TYPE simType = m_circuitModel->GetSimType(); @@ -611,7 +885,7 @@ void SIM_PLOT_FRAME::addPlot( const wxString& aName, SIM_PLOT_TYPE aType ) return; bool updated = false; - SIM_PLOT_TYPE xAxisType = getXAxisType( simType ); + SIM_TRACE_TYPE xAxisType = getXAxisType( simType ); if( xAxisType == SPT_LIN_FREQUENCY || xAxisType == SPT_LOG_FREQUENCY ) { @@ -620,52 +894,52 @@ void SIM_PLOT_FRAME::addPlot( const wxString& aName, SIM_PLOT_TYPE aType ) // If magnitude or phase wasn't specified, then add both if( baseType == aType ) { - updated |= updatePlot( aName, ( SIM_PLOT_TYPE )( baseType | SPT_AC_MAG ), plotPanel ); - updated |= updatePlot( aName, ( SIM_PLOT_TYPE )( baseType | SPT_AC_PHASE ), plotPanel ); + updated |= updateTrace( aName, (SIM_TRACE_TYPE) ( baseType | SPT_AC_MAG ), plotPanel ); + updated |= updateTrace( aName, (SIM_TRACE_TYPE) ( baseType | SPT_AC_PHASE ), plotPanel ); } else { - updated |= updatePlot( aName, ( SIM_PLOT_TYPE )( aType ), plotPanel ); + updated |= updateTrace( aName, (SIM_TRACE_TYPE) ( aType ), plotPanel ); } } else { - updated = updatePlot( aName, aType, plotPanel ); + updated = updateTrace( aName, aType, plotPanel ); } if( updated ) - updateSignalList(); + updateSignalsGrid(); } -void SIM_PLOT_FRAME::removePlot( const wxString& aPlotName ) +void SIM_PLOT_FRAME::removeTrace( const wxString& aSignalName ) { SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); if( !plotPanel ) return; - wxASSERT( plotPanel->TraceShown( aPlotName ) ); - m_workbook->DeleteTrace( plotPanel, aPlotName ); + wxASSERT( plotPanel->TraceShown( aSignalName ) ); + m_workbook->DeleteTrace( plotPanel, aSignalName ); plotPanel->GetPlotWin()->Fit(); - updateSignalList(); + updateSignalsGrid(); wxCommandEvent dummy; onCursorUpdate( dummy ); } -bool SIM_PLOT_FRAME::updatePlot( const wxString& aName, SIM_PLOT_TYPE aType, - SIM_PLOT_PANEL* aPlotPanel ) +bool SIM_PLOT_FRAME::updateTrace( const wxString& aName, SIM_TRACE_TYPE aType, + SIM_PLOT_PANEL* aPlotPanel ) { SIM_TYPE simType = m_circuitModel->GetSimType(); - wxString plotTitle = aName; + wxString traceTitle = aName; if( aType & SPT_AC_MAG ) - plotTitle += _( " (mag)" ); + traceTitle += _( " (mag)" ); else if( aType & SPT_AC_PHASE ) - plotTitle += _( " (phase)" ); + traceTitle += _( " (phase)" ); if( !SIM_PANEL_BASE::IsPlottable( simType ) ) { @@ -739,7 +1013,7 @@ bool SIM_PLOT_FRAME::updatePlot( const wxString& aName, SIM_PLOT_TYPE aType, for( size_t idx = 0; idx <= outer; idx++ ) { name = wxString::Format( wxT( "%s (%s = %s V)" ), - plotTitle, + traceTitle, source2.m_source, v.ToString() ); @@ -759,74 +1033,74 @@ bool SIM_PLOT_FRAME::updatePlot( const wxString& aName, SIM_PLOT_TYPE aType, } } - m_workbook->AddTrace( aPlotPanel, plotTitle, aName, size, data_x.data(), data_y.data(), aType ); + m_workbook->AddTrace( aPlotPanel, traceTitle, aName, size, data_x.data(), data_y.data(), aType ); return true; } -void SIM_PLOT_FRAME::updateSignalList() +void SIM_PLOT_FRAME::updateSignalsGrid() { - m_signals->ClearAll(); + SIM_PLOT_PANEL* plot = GetCurrentPlot(); - SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); - - if( !plotPanel ) - return; - - wxSize size = m_signals->GetClientSize(); - m_signals->AppendColumn( _( "Signal" ), wxLIST_FORMAT_LEFT, size.x ); - - // Build an image list, to show the color of the corresponding trace - // in the plot panel - // This image list is used for trace and cursor lists - wxMemoryDC bmDC; - const int isize = bmDC.GetCharHeight(); - - if( m_signalsIconColorList == nullptr ) - m_signalsIconColorList = new wxImageList( isize, isize, false ); - else - m_signalsIconColorList->RemoveAll(); - - for( const auto& [name, trace] : GetCurrentPlot()->GetTraces() ) + for( int row = 0; row < m_signalsGrid->GetNumberRows(); ++row ) { - wxBitmap bitmap( isize, isize ); - bmDC.SelectObject( bitmap ); - wxColour tcolor = trace->GetPen().GetColour(); + wxString signal = m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME ); - wxColour bgColor = m_signals->wxWindow::GetBackgroundColour(); - bmDC.SetPen( wxPen( bgColor ) ); - bmDC.SetBrush( wxBrush( bgColor ) ); - bmDC.DrawRectangle( 0, 0, isize, isize ); // because bmDC.Clear() does not work in wxGTK + if( TRACE* trace = plot->GetTrace( signal ) ) + { + m_signalsGrid->SetCellValue( row, COL_SIGNAL_SHOW, wxS( "1" ) ); - bmDC.SetPen( wxPen( tcolor ) ); - bmDC.SetBrush( wxBrush( tcolor ) ); - bmDC.DrawRectangle( 0, isize / 4 + 1, isize, isize / 2 ); + wxGridCellAttr* attr = new wxGridCellAttr; + attr->SetRenderer( new GRID_CELL_COLOR_RENDERER( this ) ); + attr->SetEditor( new GRID_CELL_COLOR_SELECTOR( this, m_signalsGrid ) ); + attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + m_signalsGrid->SetAttr( row, COL_SIGNAL_COLOR, attr ); - bmDC.SelectObject( wxNullBitmap ); // Needed to initialize bitmap + KIGFX::COLOR4D color( trace->GetPen().GetColour() ); + m_signalsGrid->SetCellValue( row, COL_SIGNAL_COLOR, color.ToCSSString() ); - bitmap.SetMask( new wxMask( bitmap, *wxBLACK ) ); - m_signalsIconColorList->Add( bitmap ); - } + attr = new wxGridCellAttr; + attr->SetRenderer( new wxGridCellBoolRenderer() ); + attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS + attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + m_signalsGrid->SetAttr( row, COL_CURSOR_1, attr ); - if( bmDC.IsOk() ) - { - bmDC.SetBrush( wxNullBrush ); - bmDC.SetPen( wxNullPen ); - } + attr = new wxGridCellAttr; + attr->SetRenderer( new wxGridCellBoolRenderer() ); + attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS + attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + m_signalsGrid->SetAttr( row, COL_CURSOR_2, attr ); - m_signals->SetImageList( m_signalsIconColorList, wxIMAGE_LIST_SMALL ); + if( trace->HasCursor( 1 ) ) + m_signalsGrid->SetCellValue( row, COL_CURSOR_1, wxS( "1" ) ); + else + m_signalsGrid->SetCellValue( row, COL_CURSOR_1, wxEmptyString ); - // Fill the signals listctrl. Keep the order of names and - // the order of icon color identical, because the icons - // are also used in cursor list, and the color index is - // calculated from the trace name index - int imgidx = 0; + if( trace->HasCursor( 2 ) ) + m_signalsGrid->SetCellValue( row, COL_CURSOR_2, wxS( "1" ) ); + else + m_signalsGrid->SetCellValue( row, COL_CURSOR_2, wxEmptyString ); + } + else + { + m_signalsGrid->SetCellValue( row, COL_SIGNAL_SHOW, wxEmptyString ); - for( const auto& [name, trace] : plotPanel->GetTraces() ) - { - m_signals->InsertItem( imgidx, name, imgidx ); - imgidx++; + wxGridCellAttr* attr = new wxGridCellAttr; + attr->SetReadOnly(); + m_signalsGrid->SetAttr( row, COL_SIGNAL_COLOR, attr ); + m_signalsGrid->SetCellValue( row, COL_SIGNAL_COLOR, wxEmptyString ); + + attr = new wxGridCellAttr; + attr->SetReadOnly(); + m_signalsGrid->SetAttr( row, COL_CURSOR_1, attr ); + m_signalsGrid->SetCellValue( row, COL_CURSOR_1, wxEmptyString ); + + attr = new wxGridCellAttr; + attr->SetReadOnly(); + m_signalsGrid->SetAttr( row, COL_CURSOR_2, attr ); + m_signalsGrid->SetCellValue( row, COL_CURSOR_2, wxEmptyString ); + } } } @@ -1002,7 +1276,7 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath ) } #endif - addPlot( name, (SIM_PLOT_TYPE) traceType ); + addTrace( name, (SIM_TRACE_TYPE) traceType ); } } @@ -1102,7 +1376,7 @@ bool SIM_PLOT_FRAME::SaveWorkbook( const wxString& aPath ) } -SIM_PLOT_TYPE SIM_PLOT_FRAME::getXAxisType( SIM_TYPE aType ) const +SIM_TRACE_TYPE SIM_PLOT_FRAME::getXAxisType( SIM_TYPE aType ) const { switch( aType ) { @@ -1112,7 +1386,7 @@ SIM_PLOT_TYPE SIM_PLOT_FRAME::getXAxisType( SIM_TYPE aType ) const case ST_TRANSIENT: return SPT_TIME; default: wxASSERT_MSG( false, wxT( "Unhandled simulation type" ) ); - return (SIM_PLOT_TYPE) 0; + return (SIM_TRACE_TYPE) 0; } } @@ -1146,23 +1420,17 @@ void SIM_PLOT_FRAME::onPlotClose( wxAuiNotebookEvent& event ) void SIM_PLOT_FRAME::onPlotClosed( wxAuiNotebookEvent& event ) { - if( m_workbook->GetPageCount() == 0 ) - { - m_signals->ClearAll(); - m_cursors->ClearAll(); - } - else - { - updateSignalList(); - wxCommandEvent dummy; - onCursorUpdate( dummy ); - } + m_signals.clear(); + rebuildSignalsGrid( m_filter->GetValue() ); + + wxCommandEvent dummy; + onCursorUpdate( dummy ); } void SIM_PLOT_FRAME::onPlotChanged( wxAuiNotebookEvent& event ) { - updateSignalList(); + rebuildSignalsGrid( m_filter->GetValue() ); wxCommandEvent dummy; onCursorUpdate( dummy ); } @@ -1173,52 +1441,6 @@ void SIM_PLOT_FRAME::onPlotDragged( wxAuiNotebookEvent& event ) } -void SIM_PLOT_FRAME::onSignalDblClick( wxMouseEvent& event ) -{ - // Remove signal from the plot panel when double clicked - long idx = m_signals->GetFocusedItem(); - - if( idx != wxNOT_FOUND ) - removePlot( m_signals->GetItemText( idx, 0 ) ); -} - - -void SIM_PLOT_FRAME::onSignalRClick( wxListEvent& aEvent ) -{ - long idx = aEvent.GetIndex(); - - if( idx != wxNOT_FOUND ) - m_signals->Select( idx ); - - idx = m_signals->GetFirstSelected(); - - if( idx != wxNOT_FOUND ) - { - const wxString& netName = m_signals->GetItemText( idx, 0 ); - SIGNAL_CONTEXT_MENU ctxMenu( netName, this ); - m_signals->PopupMenu( &ctxMenu ); - } -} - - -void SIM_PLOT_FRAME::onCursorRClick( wxListEvent& aEvent ) -{ - long idx = aEvent.GetIndex(); - - if( idx != wxNOT_FOUND ) - m_signals->Select( idx ); - - idx = m_signals->GetFirstSelected(); - - if( idx != wxNOT_FOUND ) - { - const wxString& netName = m_signals->GetItemText( idx, 0 ); - CURSOR_CONTEXT_MENU ctxMenu( netName, this ); - m_signals->PopupMenu( &ctxMenu ); - } -} - - void SIM_PLOT_FRAME::onWorkbookModified( wxCommandEvent& event ) { updateTitle(); @@ -1315,19 +1537,11 @@ bool SIM_PLOT_FRAME::canCloseWindow( wxCloseEvent& aEvent ) filename.SetFullName( Prj().GetProjectName() + wxT( ".wbk" ) ); } -#if 0 // TODO: Enable once 8.0 opens for dev - wxString msg = _( "Save changes to workbook?" ); -#else - wxString fullFilename = filename.GetFullName(); - wxString msg = _( "Save changes to '%s' before closing?" ); - msg.Printf( msg, fullFilename ); -#endif - - return HandleUnsavedChanges( this, msg, - [&]() -> bool - { - return SaveWorkbook( Prj().AbsolutePath( fullFilename ) ); - } ); + return HandleUnsavedChanges( this, _( "Save changes to workbook?" ), + [&]() -> bool + { + return SaveWorkbook( Prj().AbsolutePath( filename.GetFullName() ) ); + } ); } return true; @@ -1355,49 +1569,106 @@ void SIM_PLOT_FRAME::doCloseWindow() void SIM_PLOT_FRAME::onCursorUpdate( wxCommandEvent& event ) { - wxSize size = m_cursors->GetClientSize(); + m_cursorsGrid->ClearRows(); + SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); - m_cursors->ClearAll(); if( !plotPanel ) return; - if( m_signalsIconColorList ) - m_cursors->SetImageList(m_signalsIconColorList, wxIMAGE_LIST_SMALL); - - // Fill the signals listctrl - m_cursors->AppendColumn( _( "Signal" ), wxLIST_FORMAT_LEFT, size.x / 2 ); - const long X_COL = m_cursors->AppendColumn( plotPanel->GetLabelX(), wxLIST_FORMAT_LEFT, - size.x / 4 ); + // Set up the labels + m_cursorsGrid->SetColLabelValue( COL_CURSOR_X, plotPanel->GetLabelX() ); wxString labelY1 = plotPanel->GetLabelY1(); wxString labelY2 = plotPanel->GetLabelY2(); - wxString labelY; - if( !labelY2.IsEmpty() ) - labelY = labelY1 + wxT( " / " ) + labelY2; + if( labelY2.IsEmpty() ) + m_cursorsGrid->SetColLabelValue( COL_CURSOR_Y, labelY1 ); else - labelY = labelY1; + m_cursorsGrid->SetColLabelValue( COL_CURSOR_Y, labelY1 + wxT( " / " ) + labelY2 ); - const long Y_COL = m_cursors->AppendColumn( labelY, wxLIST_FORMAT_LEFT, size.x / 4 ); + auto getUnitsY = + [&]( TRACE* aTrace ) -> wxString + { + if( aTrace->GetType() == SPT_VOLTAGE ) + return wxS( "V" ); + else if( aTrace->GetType() == SPT_CURRENT ) + return wxS( "A" ); + else + return wxEmptyString; + }; // Update cursor values - int itemidx = 0; + wxString unitsX = plotPanel->GetUnitsX(); + CURSOR* cursor1 = nullptr; + wxString unitsY1; + CURSOR* cursor2 = nullptr; + wxString unitsY2; + +#define SET_CELL( r, c, v ) m_cursorsGrid->SetCellValue( r, c, v ) for( const auto& [name, trace] : plotPanel->GetTraces() ) { - if( CURSOR* cursor = trace->GetCursor() ) + if( CURSOR* cursor = trace->GetCursor( 1 ) ) { - // Find the right icon color in list. - // It is the icon used in m_signals list for the same trace - long iconColor = m_signals->FindItem( -1, name ); + cursor1 = cursor; + unitsY1 = getUnitsY( trace ); - const wxRealPoint coords = cursor->GetCoords(); - long idx = m_cursors->InsertItem( itemidx++, name, iconColor ); - m_cursors->SetItem( idx, X_COL, SPICE_VALUE( coords.x ).ToSpiceString() ); - m_cursors->SetItem( idx, Y_COL, SPICE_VALUE( coords.y ).ToSpiceString() ); + wxRealPoint coords = cursor->GetCoords(); + int row = m_cursorsGrid->GetNumberRows(); + + m_cursorsGrid->AppendRows( 1 ); + SET_CELL( row, COL_CURSOR_NAME, wxS( "1" ) ); + SET_CELL( row, COL_CURSOR_SIGNAL, cursor->GetName() ); + SET_CELL( row, COL_CURSOR_X, SPICE_VALUE( coords.x ).ToSpiceString() + unitsX ); + SET_CELL( row, COL_CURSOR_Y, SPICE_VALUE( coords.y ).ToSpiceString() + unitsY1 ); + + break; } } + + for( const auto& [name, trace] : plotPanel->GetTraces() ) + { + if( CURSOR* cursor = trace->GetCursor( 2 ) ) + { + cursor2 = cursor; + unitsY2 = getUnitsY( trace ); + + wxRealPoint coords = cursor->GetCoords(); + int row = m_cursorsGrid->GetNumberRows(); + + m_cursorsGrid->AppendRows( 1 ); + SET_CELL( row, COL_CURSOR_NAME, wxS( "2" ) ); + SET_CELL( row, COL_CURSOR_SIGNAL, cursor->GetName() ); + SET_CELL( row, COL_CURSOR_X, SPICE_VALUE( coords.x ).ToSpiceString() + unitsX ); + SET_CELL( row, COL_CURSOR_Y, SPICE_VALUE( coords.y ).ToSpiceString() + unitsY2 ); + + break; + } + } + + if( cursor1 && cursor2 && unitsY1 == unitsY2 ) + { + const wxRealPoint coords = cursor2->GetCoords() - cursor1->GetCoords(); + + m_cursorsGrid->AppendRows( 1 ); + SET_CELL( 2, COL_CURSOR_NAME, _( "Diff" ) ); + if( cursor1->GetName() == cursor2->GetName() ) + { + SET_CELL( 2, COL_CURSOR_SIGNAL, wxString::Format( wxS( "%s[2 - 1]" ), + cursor2->GetName() ) ); + } + else + { + SET_CELL( 2, COL_CURSOR_SIGNAL, wxString::Format( wxS( "%s - %s" ), + cursor2->GetName(), + cursor1->GetName() ) ); + } + SET_CELL( 2, COL_CURSOR_X, SPICE_VALUE( coords.x ).ToSpiceString() + unitsX ); + SET_CELL( 2, COL_CURSOR_Y, SPICE_VALUE( coords.y ).ToSpiceString() + unitsY1 ); + } + +#undef SET_CELL } @@ -1471,7 +1742,6 @@ void SIM_PLOT_FRAME::setupUIConditions() mgr->SetConditions( EE_ACTIONS::simCommand, ENABLE( SELECTION_CONDITIONS::ShowAlways ) ); mgr->SetConditions( EE_ACTIONS::runSimulation, ENABLE( !simRunning ) ); mgr->SetConditions( EE_ACTIONS::stopSimulation, ENABLE( simRunning ) ); - mgr->SetConditions( EE_ACTIONS::addSignals, ENABLE( simFinished ) ); mgr->SetConditions( EE_ACTIONS::simProbe, ENABLE( simFinished ) ); mgr->SetConditions( EE_ACTIONS::simTune, ENABLE( simFinished ) ); mgr->SetConditions( EE_ACTIONS::showNetlist, ENABLE( SELECTION_CONDITIONS::ShowAlways ) ); @@ -1532,7 +1802,7 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent ) struct TRACE_DESC { wxString m_name; ///< Name of the measured net/device - SIM_PLOT_TYPE m_type; ///< Type of the signal + SIM_TRACE_TYPE m_type; ///< Type of the signal }; std::vector traceInfo; @@ -1549,11 +1819,11 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent ) for( const struct TRACE_DESC& trace : traceInfo ) { - if( !updatePlot( trace.m_name, trace.m_type, plotPanel ) ) - removePlot( trace.m_name ); + if( !updateTrace( trace.m_name, trace.m_type, plotPanel ) ) + removeTrace( trace.m_name ); } - updateSignalList(); + rebuildSignalsGrid( m_filter->GetValue() ); plotPanel->GetPlotWin()->UpdateAll(); plotPanel->ResetScales(); } @@ -1569,12 +1839,12 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent ) if( val_list.size() == 0 ) // The list of values can be empty! continue; - double val = val_list.at( 0 ); - wxString outLine, signal; - SIM_PLOT_TYPE type = m_circuitModel->VectorToSignal( vec, signal ); + double val = val_list.at( 0 ); + wxString outLine, signal; + SIM_TRACE_TYPE type = m_circuitModel->VectorToSignal( vec, signal ); - const size_t tab = 25; //characters - size_t padding = ( signal.length() < tab ) ? ( tab - signal.length() ) : 1; + const size_t tab = 25; //characters + size_t padding = ( signal.length() < tab ) ? ( tab - signal.length() ) : 1; outLine.Printf( wxT( "%s%s" ), ( signal + wxT( ":" ) ).Pad( padding, wxUniChar( ' ' ) ), @@ -1643,64 +1913,6 @@ void SIM_PLOT_FRAME::onSimReport( wxCommandEvent& aEvent ) } -SIM_PLOT_FRAME::SIGNAL_CONTEXT_MENU::SIGNAL_CONTEXT_MENU( const wxString& aSignal, - SIM_PLOT_FRAME* aPlotFrame ) : - m_signal( aSignal ), - m_plotFrame( aPlotFrame ) -{ - SIM_PLOT_PANEL* plot = m_plotFrame->GetCurrentPlot(); - - AddMenuItem( this, REMOVE_SIGNAL, _( "Remove Signal" ), _( "Remove the signal from the plot" ), - KiBitmap( BITMAPS::trash ) ); - - TRACE* trace = plot->GetTrace( m_signal ); - - AppendSeparator(); - - if( trace->HasCursor() ) - AddMenuItem( this, HIDE_CURSOR, _( "Hide Cursor" ), KiBitmap( BITMAPS::pcb_target ) ); - else - AddMenuItem( this, SHOW_CURSOR, _( "Show Cursor" ), KiBitmap( BITMAPS::pcb_target ) ); - - Connect( wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler( SIGNAL_CONTEXT_MENU::onMenuEvent ), - nullptr, this ); -} - - -void SIM_PLOT_FRAME::SIGNAL_CONTEXT_MENU::onMenuEvent( wxMenuEvent& aEvent ) -{ - SIM_PLOT_PANEL* plot = m_plotFrame->GetCurrentPlot(); - - switch( aEvent.GetId() ) - { - case REMOVE_SIGNAL: m_plotFrame->removePlot( m_signal ); break; - case SHOW_CURSOR: plot->EnableCursor( m_signal, true ); break; - case HIDE_CURSOR: plot->EnableCursor( m_signal, false ); break; - } -} - - -SIM_PLOT_FRAME::CURSOR_CONTEXT_MENU::CURSOR_CONTEXT_MENU( const wxString& aSignal, - SIM_PLOT_FRAME* aPlotFrame ) : - m_signal( aSignal ), - m_plotFrame( aPlotFrame ) -{ - AddMenuItem( this, HIDE_CURSOR, _( "Hide Cursor" ), KiBitmap( BITMAPS::pcb_target ) ); - - Connect( wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler( CURSOR_CONTEXT_MENU::onMenuEvent ), - nullptr, this ); -} - - -void SIM_PLOT_FRAME::CURSOR_CONTEXT_MENU::onMenuEvent( wxMenuEvent& aEvent ) -{ - SIM_PLOT_PANEL* plot = m_plotFrame->GetCurrentPlot(); - - if( aEvent.GetId() == HIDE_CURSOR ) - plot->EnableCursor( m_signal, false ); -} - - void SIM_PLOT_FRAME::onExit( wxCommandEvent& event ) { Kiway().OnKiCadExit(); diff --git a/eeschema/sim/sim_plot_frame.h b/eeschema/sim/sim_plot_frame.h index e7ef9530da..f04ed4b78d 100644 --- a/eeschema/sim/sim_plot_frame.h +++ b/eeschema/sim/sim_plot_frame.h @@ -71,7 +71,7 @@ public: * @param aSimOptions netlisting options * @return The new plot panel. */ - SIM_PANEL_BASE* NewPlotPanel( wxString aSimCommand, int aSimOptions ); + SIM_PANEL_BASE* NewPlotPanel( const wxString& aSimCommand, int aSimOptions ); /** * Shows a dialog for editing the current tab's simulation command, or creating a new tab @@ -209,18 +209,18 @@ private: * @param aType describes the type of plot. * @param aParam is the parameter for the device/net (e.g. I, Id, V). */ - void addPlot( const wxString& aName, SIM_PLOT_TYPE aType ); + void addTrace( const wxString& aName, SIM_TRACE_TYPE aType ); /** * Remove a plot with a specific title. * - * @param aPlotName is the full plot title (e.g. I(Net-C1-Pad1)). + * @param aSignalName is the full plot title (e.g. I(Net-C1-Pad1)). */ - void removePlot( const wxString& aPlotName ); + void removeTrace( const wxString& aSignalName ); /** - * Update plot in a particular SIM_PLOT_PANEL. If the panel does not contain - * the plot, it will be added. + * Update a trace in a particular SIM_PLOT_PANEL. If the panel does not contain the given + * trace, then add it. * * @param aName is the device/net name. * @param aType describes the type of plot. @@ -228,12 +228,17 @@ private: * @param aPlotPanel is the panel that should receive the update. * @return True if a plot was successfully added/updated. */ - bool updatePlot( const wxString& aName, SIM_PLOT_TYPE aType, SIM_PLOT_PANEL* aPlotPanel ); + bool updateTrace( const wxString& aName, SIM_TRACE_TYPE aType, SIM_PLOT_PANEL* aPlotPanel ); /** - * Update the list of currently plotted signals. + * Rebuild the filtered list of signals in the signals grid. */ - void updateSignalList(); + void rebuildSignalsGrid( wxString aFilter ); + + /** + * Update the values in the signals grid. + */ + void updateSignalsGrid(); /** * Apply component values specified using tuner sliders to the current netlist. @@ -254,7 +259,7 @@ private: /** * Return X axis for a given simulation type. */ - SIM_PLOT_TYPE getXAxisType( SIM_TYPE aType ) const; + SIM_TRACE_TYPE getXAxisType( SIM_TYPE aType ) const; // Event handlers void onPlotClose( wxAuiNotebookEvent& event ) override; @@ -262,10 +267,11 @@ private: void onPlotChanged( wxAuiNotebookEvent& event ) override; void onPlotDragged( wxAuiNotebookEvent& event ) override; - void onSignalDblClick( wxMouseEvent& event ) override; - void onSignalRClick( wxListEvent& aEvent ) override; + void OnFilterText( wxCommandEvent& aEvent ) override; + void OnFilterMouseMoved( wxMouseEvent& aEvent ) override; - void onCursorRClick( wxListEvent& aEvent ) override; + void onSignalsGridCellChanged( wxGridEvent& aEvent ) override; + void onCursorsGridCellChanged( wxGridEvent& aEvent ) override; void onWorkbookModified( wxCommandEvent& event ); void onWorkbookClrModified( wxCommandEvent& event ); @@ -287,54 +293,18 @@ private: // frame is initialized (end of the Ctor) void setSubWindowsSashSize(); - enum CONTEXT_MENU_EVENTS - { - REMOVE_SIGNAL = 944, - SHOW_CURSOR, - HIDE_CURSOR - }; - - // Right click context menu for signals in the listbox - class SIGNAL_CONTEXT_MENU : public wxMenu - { - public: - SIGNAL_CONTEXT_MENU( const wxString& aSignal, SIM_PLOT_FRAME* aPlotFrame ); - - private: - void onMenuEvent( wxMenuEvent& aEvent ); - - const wxString& m_signal; - SIM_PLOT_FRAME* m_plotFrame; - }; - - // Right click context menu for cursors in the listbox - class CURSOR_CONTEXT_MENU : public wxMenu - { - public: - CURSOR_CONTEXT_MENU( const wxString& aSignal, SIM_PLOT_FRAME* aPlotFrame ); - - private: - void onMenuEvent( wxMenuEvent& aEvent ); - - const wxString& m_signal; - SIM_PLOT_FRAME* m_plotFrame; - }; - private: SCH_EDIT_FRAME* m_schematicFrame; std::shared_ptr m_circuitModel; std::shared_ptr m_simulator; SIM_THREAD_REPORTER* m_reporter; + std::vector m_signals; std::list m_tuners; ///< Panel that was used as the most recent one for simulations SIM_PANEL_BASE* m_lastSimPlot; - ///< imagelists used to add a small colored icon to signal names - ///< and cursors name, the same color as the corresponding signal traces - wxImageList* m_signalsIconColorList; - // Variables for temporary storage: int m_splitterLeftRightSashPosition; int m_splitterPlotAndConsoleSashPosition; diff --git a/eeschema/sim/sim_plot_frame_base.cpp b/eeschema/sim/sim_plot_frame_base.cpp index 7fd40bbd3d..e83107752c 100644 --- a/eeschema/sim/sim_plot_frame_base.cpp +++ b/eeschema/sim/sim_plot_frame_base.cpp @@ -6,6 +6,7 @@ /////////////////////////////////////////////////////////////////////////// #include "tool/action_toolbar.h" +#include "widgets/wx_grid.h" #include "sim_plot_frame_base.h" @@ -87,25 +88,67 @@ SIM_PLOT_FRAME_BASE::SIM_PLOT_FRAME_BASE( wxWindow* parent, wxWindowID id, const m_panelSignals = new wxPanel( m_splitterSignals, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); m_panelSignals->SetMinSize( wxSize( -1,100 ) ); - wxBoxSizer* bSizer10; - bSizer10 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSignalsSizer; + bSignalsSizer = new wxBoxSizer( wxVERTICAL ); - m_staticTextSignals = new wxStaticText( m_panelSignals, wxID_ANY, _("Signals"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextSignals->Wrap( -1 ); - bSizer10->Add( m_staticTextSignals, 0, wxTOP|wxRIGHT, 5 ); + wxBoxSizer* bFiltersSizer; + bFiltersSizer = new wxBoxSizer( wxHORIZONTAL ); - m_signals = new wxListView( m_panelSignals, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_HEADER|wxLC_REPORT|wxLC_SINGLE_SEL ); - bSizer10->Add( m_signals, 1, wxEXPAND, 5 ); + m_filter = new wxSearchCtrl( m_panelSignals, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + #ifndef __WXMAC__ + m_filter->ShowSearchButton( true ); + #endif + m_filter->ShowCancelButton( true ); + bFiltersSizer->Add( m_filter, 1, wxALIGN_CENTER_VERTICAL, 5 ); - m_panelSignals->SetSizer( bSizer10 ); + bSignalsSizer->Add( bFiltersSizer, 0, wxEXPAND, 5 ); + + m_signalsGrid = new WX_GRID( m_panelSignals, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + + // Grid + m_signalsGrid->CreateGrid( 0, 5 ); + m_signalsGrid->EnableEditing( true ); + m_signalsGrid->EnableGridLines( true ); + m_signalsGrid->EnableDragGridSize( false ); + m_signalsGrid->SetMargins( 0, 0 ); + + // Columns + m_signalsGrid->SetColSize( 0, 196 ); + m_signalsGrid->SetColSize( 1, 50 ); + m_signalsGrid->SetColSize( 2, 50 ); + m_signalsGrid->SetColSize( 3, 54 ); + m_signalsGrid->SetColSize( 4, 54 ); + m_signalsGrid->EnableDragColMove( false ); + m_signalsGrid->EnableDragColSize( true ); + m_signalsGrid->SetColLabelValue( 0, _("Signal") ); + m_signalsGrid->SetColLabelValue( 1, _("Plot") ); + m_signalsGrid->SetColLabelValue( 2, _("Color") ); + m_signalsGrid->SetColLabelValue( 3, _("Cursor 1") ); + m_signalsGrid->SetColLabelValue( 4, _("Cursor 2") ); + m_signalsGrid->SetColLabelSize( -1 ); + m_signalsGrid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + + // Rows + m_signalsGrid->EnableDragRowSize( true ); + m_signalsGrid->SetRowLabelSize( 0 ); + m_signalsGrid->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + + // Label Appearance + + // Cell Defaults + m_signalsGrid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); + bSignalsSizer->Add( m_signalsGrid, 1, wxEXPAND, 5 ); + + + m_panelSignals->SetSizer( bSignalsSizer ); m_panelSignals->Layout(); - bSizer10->Fit( m_panelSignals ); + bSignalsSizer->Fit( m_panelSignals ); m_panelCursorsAndTune = new wxPanel( m_splitterSignals, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); m_panelCursorsAndTune->SetMinSize( wxSize( -1,300 ) ); - wxBoxSizer* bSizer9; - bSizer9 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bCursorsSizer; + bCursorsSizer = new wxBoxSizer( wxVERTICAL ); m_splitterTuneValues = new wxSplitterWindow( m_panelCursorsAndTune, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_3DSASH|wxSP_LIVE_UPDATE|wxBORDER_NONE ); m_splitterTuneValues->SetSashGravity( 0.5 ); @@ -118,12 +161,39 @@ SIM_PLOT_FRAME_BASE::SIM_PLOT_FRAME_BASE( wxWindow* parent, wxWindowID id, const wxBoxSizer* bSizer12; bSizer12 = new wxBoxSizer( wxVERTICAL ); - m_staticTextCursors = new wxStaticText( m_panelCursors, wxID_ANY, _("Cursors"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextCursors->Wrap( -1 ); - bSizer12->Add( m_staticTextCursors, 0, wxTOP|wxRIGHT, 5 ); + m_cursorsGrid = new WX_GRID( m_panelCursors, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_cursors = new wxListCtrl( m_panelCursors, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_HRULES|wxLC_REPORT|wxLC_SINGLE_SEL ); - bSizer12->Add( m_cursors, 1, wxEXPAND, 5 ); + // Grid + m_cursorsGrid->CreateGrid( 0, 4 ); + m_cursorsGrid->EnableEditing( true ); + m_cursorsGrid->EnableGridLines( true ); + m_cursorsGrid->EnableDragGridSize( false ); + m_cursorsGrid->SetMargins( 0, 0 ); + + // Columns + m_cursorsGrid->SetColSize( 0, 44 ); + m_cursorsGrid->SetColSize( 1, 140 ); + m_cursorsGrid->SetColSize( 2, 110 ); + m_cursorsGrid->SetColSize( 3, 110 ); + m_cursorsGrid->EnableDragColMove( false ); + m_cursorsGrid->EnableDragColSize( true ); + m_cursorsGrid->SetColLabelValue( 0, _("Cursor") ); + m_cursorsGrid->SetColLabelValue( 1, _("Signal") ); + m_cursorsGrid->SetColLabelValue( 2, _("Time") ); + m_cursorsGrid->SetColLabelValue( 3, _("Voltage / Current") ); + m_cursorsGrid->SetColLabelSize( -1 ); + m_cursorsGrid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + + // Rows + m_cursorsGrid->EnableDragRowSize( true ); + m_cursorsGrid->SetRowLabelSize( 0 ); + m_cursorsGrid->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + + // Label Appearance + + // Cell Defaults + m_cursorsGrid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); + bSizer12->Add( m_cursorsGrid, 1, wxEXPAND, 5 ); m_panelCursors->SetSizer( bSizer12 ); @@ -149,12 +219,12 @@ SIM_PLOT_FRAME_BASE::SIM_PLOT_FRAME_BASE( wxWindow* parent, wxWindowID id, const m_tunePanel->Layout(); bSizer13->Fit( m_tunePanel ); m_splitterTuneValues->SplitHorizontally( m_panelCursors, m_tunePanel, 0 ); - bSizer9->Add( m_splitterTuneValues, 1, wxEXPAND, 5 ); + bCursorsSizer->Add( m_splitterTuneValues, 1, wxEXPAND, 5 ); - m_panelCursorsAndTune->SetSizer( bSizer9 ); + m_panelCursorsAndTune->SetSizer( bCursorsSizer ); m_panelCursorsAndTune->Layout(); - bSizer9->Fit( m_panelCursorsAndTune ); + bCursorsSizer->Fit( m_panelCursorsAndTune ); m_splitterSignals->SplitHorizontally( m_panelSignals, m_panelCursorsAndTune, 0 ); m_sideSizer->Add( m_splitterSignals, 1, wxEXPAND, 5 ); @@ -176,9 +246,10 @@ SIM_PLOT_FRAME_BASE::SIM_PLOT_FRAME_BASE( wxWindow* parent, wxWindowID id, const m_workbook->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotChanged ), NULL, this ); m_workbook->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotClose ), NULL, this ); m_workbook->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotClosed ), NULL, this ); - m_signals->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SIM_PLOT_FRAME_BASE::onSignalDblClick ), NULL, this ); - m_signals->Connect( wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, wxListEventHandler( SIM_PLOT_FRAME_BASE::onSignalRClick ), NULL, this ); - m_cursors->Connect( wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, wxListEventHandler( SIM_PLOT_FRAME_BASE::onCursorRClick ), NULL, this ); + m_filter->Connect( wxEVT_MOTION, wxMouseEventHandler( SIM_PLOT_FRAME_BASE::OnFilterMouseMoved ), NULL, this ); + m_filter->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::OnFilterText ), NULL, this ); + m_signalsGrid->Connect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( SIM_PLOT_FRAME_BASE::onSignalsGridCellChanged ), NULL, this ); + m_cursorsGrid->Connect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( SIM_PLOT_FRAME_BASE::onCursorsGridCellChanged ), NULL, this ); } SIM_PLOT_FRAME_BASE::~SIM_PLOT_FRAME_BASE() @@ -188,8 +259,9 @@ SIM_PLOT_FRAME_BASE::~SIM_PLOT_FRAME_BASE() m_workbook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotChanged ), NULL, this ); m_workbook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotClose ), NULL, this ); m_workbook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotClosed ), NULL, this ); - m_signals->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SIM_PLOT_FRAME_BASE::onSignalDblClick ), NULL, this ); - m_signals->Disconnect( wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, wxListEventHandler( SIM_PLOT_FRAME_BASE::onSignalRClick ), NULL, this ); - m_cursors->Disconnect( wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, wxListEventHandler( SIM_PLOT_FRAME_BASE::onCursorRClick ), NULL, this ); + m_filter->Disconnect( wxEVT_MOTION, wxMouseEventHandler( SIM_PLOT_FRAME_BASE::OnFilterMouseMoved ), NULL, this ); + m_filter->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::OnFilterText ), NULL, this ); + m_signalsGrid->Disconnect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( SIM_PLOT_FRAME_BASE::onSignalsGridCellChanged ), NULL, this ); + m_cursorsGrid->Disconnect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( SIM_PLOT_FRAME_BASE::onCursorsGridCellChanged ), NULL, this ); } diff --git a/eeschema/sim/sim_plot_frame_base.fbp b/eeschema/sim/sim_plot_frame_base.fbp index 6a72cbab7a..b55f27b1f1 100644 --- a/eeschema/sim/sim_plot_frame_base.fbp +++ b/eeschema/sim/sim_plot_frame_base.fbp @@ -731,14 +731,92 @@ wxTAB_TRAVERSAL - bSizer10 + bSignalsSizer wxVERTICAL none - + 5 - wxTOP|wxRIGHT + wxEXPAND 0 - + + + bFiltersSizer + wxHORIZONTAL + none + + 5 + wxALIGN_CENTER_VERTICAL + 1 + + 1 + 1 + 1 + 1 + + + + + + + 1 + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + -1,-1 + 1 + m_filter + 1 + + + protected + 1 + + Resizable + 1 + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + OnFilterMouseMoved + OnFilterText + + + + + + 5 + wxEXPAND + 1 + 1 1 1 @@ -747,27 +825,50 @@ + 0 + 0 1 + + + wxALIGN_LEFT + + wxALIGN_TOP 0 1 + wxALIGN_CENTER + -1 + "Signal" "Plot" "Color" "Cursor 1" "Cursor 2" + wxALIGN_CENTER + 5 + 196,50,50,54,54 1 0 Dock 0 Left + 0 + 1 + 0 + 1 + 1 1 1 + + 1 0 0 wxID_ANY - Signals - 0 + + + + 0 + 0 0 @@ -775,7 +876,7 @@ 0 1 - m_staticTextSignals + m_signalsGrid 1 @@ -783,80 +884,21 @@ 1 Resizable + wxALIGN_CENTER + 0 + + wxALIGN_CENTER + + 0 1 - - ; forward_declare + WX_GRID; widgets/wx_grid.h; forward_declare 0 - -1 - - - - 5 - wxEXPAND - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - -1,-1 - 1 - m_signals - 1 - - - protected - 1 - - Resizable - 1 - - wxLC_NO_HEADER|wxLC_REPORT|wxLC_SINGLE_SEL - wxListView; - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - onSignalDblClick - onSignalRClick + onSignalsGridCellChanged @@ -916,7 +958,7 @@ wxTAB_TRAVERSAL - bSizer9 + bCursorsSizer wxVERTICAL none @@ -1037,11 +1079,11 @@ bSizer12 wxVERTICAL none - + 5 - wxTOP|wxRIGHT - 0 - + wxEXPAND + 1 + 1 1 1 @@ -1050,27 +1092,50 @@ + 0 + 0 1 + + + wxALIGN_LEFT + + wxALIGN_TOP 0 1 + wxALIGN_CENTER + -1 + "Cursor" "Signal" "Time" "Voltage / Current" + wxALIGN_CENTER + 4 + 44,140,110,110 1 0 Dock 0 Left + 0 + 1 + 0 + 1 + 1 1 1 + + 1 0 0 wxID_ANY - Cursors - 0 + + + + 0 + 0 0 @@ -1078,7 +1143,7 @@ 0 1 - m_staticTextCursors + m_cursorsGrid 1 @@ -1086,79 +1151,21 @@ 1 Resizable + wxALIGN_CENTER + 0 + + wxALIGN_CENTER + + 0 1 - - ; forward_declare + WX_GRID; widgets/wx_grid.h; forward_declare 0 - -1 - - - - 5 - wxEXPAND - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - -1,-1 - 1 - m_cursors - 1 - - - protected - 1 - - Resizable - 1 - - wxLC_HRULES|wxLC_REPORT|wxLC_SINGLE_SEL - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - onCursorRClick + onCursorsGridCellChanged diff --git a/eeschema/sim/sim_plot_frame_base.h b/eeschema/sim/sim_plot_frame_base.h index 568cc4e789..afaf1761c7 100644 --- a/eeschema/sim/sim_plot_frame_base.h +++ b/eeschema/sim/sim_plot_frame_base.h @@ -11,7 +11,7 @@ #include #include class ACTION_TOOLBAR; -class wxListView; +class WX_GRID; #include "sim_workbook.h" #include "kiway_player.h" @@ -27,8 +27,9 @@ class wxListView; #include #include #include +#include +#include #include -#include #include /////////////////////////////////////////////////////////////////////////// @@ -58,13 +59,12 @@ class SIM_PLOT_FRAME_BASE : public KIWAY_PLAYER wxBoxSizer* m_sideSizer; wxSplitterWindow* m_splitterSignals; wxPanel* m_panelSignals; - wxStaticText* m_staticTextSignals; - wxListView* m_signals; + wxSearchCtrl* m_filter; + WX_GRID* m_signalsGrid; wxPanel* m_panelCursorsAndTune; wxSplitterWindow* m_splitterTuneValues; wxPanel* m_panelCursors; - wxStaticText* m_staticTextCursors; - wxListCtrl* m_cursors; + WX_GRID* m_cursorsGrid; wxPanel* m_tunePanel; wxStaticText* m_staticTextTune; wxBoxSizer* m_tuneSizer; @@ -74,9 +74,10 @@ class SIM_PLOT_FRAME_BASE : public KIWAY_PLAYER virtual void onPlotChanged( wxAuiNotebookEvent& event ) { event.Skip(); } virtual void onPlotClose( wxAuiNotebookEvent& event ) { event.Skip(); } virtual void onPlotClosed( wxAuiNotebookEvent& event ) { event.Skip(); } - virtual void onSignalDblClick( wxMouseEvent& event ) { event.Skip(); } - virtual void onSignalRClick( wxListEvent& event ) { event.Skip(); } - virtual void onCursorRClick( wxListEvent& event ) { event.Skip(); } + virtual void OnFilterMouseMoved( wxMouseEvent& event ) { event.Skip(); } + virtual void OnFilterText( wxCommandEvent& event ) { event.Skip(); } + virtual void onSignalsGridCellChanged( wxGridEvent& event ) { event.Skip(); } + virtual void onCursorsGridCellChanged( wxGridEvent& event ) { event.Skip(); } public: diff --git a/eeschema/sim/sim_plot_panel.cpp b/eeschema/sim/sim_plot_panel.cpp index 1514654364..700e5b1c29 100644 --- a/eeschema/sim/sim_plot_panel.cpp +++ b/eeschema/sim/sim_plot_panel.cpp @@ -134,6 +134,9 @@ public: m_unit( unit ) {}; + wxString GetUnits() const { return m_unit; } + +private: void formatLabels() override { double maxVis = parent::AbsVisibleMaxValue(); @@ -175,6 +178,9 @@ public: m_unit( unit ) {}; + wxString GetUnits() const { return m_unit; } + +private: void formatLabels() override { wxString suffix; @@ -196,50 +202,75 @@ private: }; +void CURSOR::SetCoordX( double aValue ) +{ + wxRealPoint oldCoords = m_coords; + + doSetCoordX( aValue ); + m_updateRequired = false; + m_updateRef = true; + + if( m_window ) + { + wxRealPoint delta = m_coords - oldCoords; + mpInfoLayer::Move( wxPoint( m_window->x2p( m_trace->x2s( delta.x ) ), + m_window->y2p( m_trace->y2s( delta.y ) ) ) ); + + m_window->Refresh(); + } +} + + +void CURSOR::doSetCoordX( double aValue ) +{ + m_coords.x = aValue; + + const std::vector& dataX = m_trace->GetDataX(); + const std::vector& dataY = m_trace->GetDataY(); + + if( dataX.size() <= 1 ) + return; + + // Find the closest point coordinates + auto maxXIt = std::upper_bound( dataX.begin(), dataX.end(), m_coords.x ); + int maxIdx = maxXIt - dataX.begin(); + int minIdx = maxIdx - 1; + + // Out of bounds checks + if( minIdx < 0 ) + { + minIdx = 0; + maxIdx = 1; + m_coords.x = dataX[0]; + } + else if( maxIdx >= (int) dataX.size() ) + { + maxIdx = dataX.size() - 1; + minIdx = maxIdx - 1; + m_coords.x = dataX[maxIdx]; + } + + const double leftX = dataX[minIdx]; + const double rightX = dataX[maxIdx]; + const double leftY = dataY[minIdx]; + const double rightY = dataY[maxIdx]; + + // Linear interpolation + m_coords.y = leftY + ( rightY - leftY ) / ( rightX - leftX ) * ( m_coords.x - leftX ); +} + + void CURSOR::Plot( wxDC& aDC, mpWindow& aWindow ) { if( !m_window ) m_window = &aWindow; - if( !m_visible ) - return; - - const auto& dataX = m_trace->GetDataX(); - const auto& dataY = m_trace->GetDataY(); - - if( dataX.size() <= 1 ) + if( !m_visible || m_trace->GetDataX().size() <= 1 ) return; if( m_updateRequired ) { - m_coords.x = m_trace->s2x( aWindow.p2x( m_dim.x ) ); - - // Find the closest point coordinates - auto maxXIt = std::upper_bound( dataX.begin(), dataX.end(), m_coords.x ); - int maxIdx = maxXIt - dataX.begin(); - int minIdx = maxIdx - 1; - - // Out of bounds checks - if( minIdx < 0 ) - { - minIdx = 0; - maxIdx = 1; - m_coords.x = dataX[0]; - } - else if( maxIdx >= (int) dataX.size() ) - { - maxIdx = dataX.size() - 1; - minIdx = maxIdx - 1; - m_coords.x = dataX[maxIdx]; - } - - const double leftX = dataX[minIdx]; - const double rightX = dataX[maxIdx]; - const double leftY = dataY[minIdx]; - const double rightY = dataY[maxIdx]; - - // Linear interpolation - m_coords.y = leftY + ( rightY - leftY ) / ( rightX - leftX ) * ( m_coords.x - leftX ); + doSetCoordX( m_trace->s2x( aWindow.p2x( m_dim.x ) ) ); m_updateRequired = false; // Notify the parent window about the changes @@ -339,6 +370,20 @@ SIM_PLOT_PANEL::~SIM_PLOT_PANEL() } +wxString SIM_PLOT_PANEL::GetUnitsX() const +{ + LOG_SCALE* logScale = dynamic_cast*>( m_axis_x ); + LIN_SCALE* linScale = dynamic_cast*>( m_axis_x ); + + if( logScale ) + return logScale->GetUnits(); + else if( linScale ) + return linScale->GetUnits(); + else + return wxEmptyString; +} + + void SIM_PLOT_PANEL::updateAxes() { bool skipAddToView = false; @@ -497,8 +542,11 @@ void SIM_PLOT_PANEL::UpdatePlotColors() // Update color of all traces for( auto& [ name, trace ] : m_traces ) { - if( CURSOR* cursor = trace->GetCursor() ) - cursor->SetPen( wxPen( m_colors.GetPlotColor( SIM_PLOT_COLORS::COLOR_SET::CURSOR ) ) ); + for( auto& [ id, cursor ] : trace->GetCursors() ) + { + if( cursor ) + cursor->SetPen( wxPen( m_colors.GetPlotColor( SIM_PLOT_COLORS::COLOR_SET::CURSOR ) ) ); + } } m_plotWin->UpdateAll(); @@ -523,7 +571,7 @@ void SIM_PLOT_PANEL::UpdateTraceStyle( TRACE* trace ) bool SIM_PLOT_PANEL::addTrace( const wxString& aTitle, const wxString& aName, int aPoints, - const double* aX, const double* aY, SIM_PLOT_TYPE aType ) + const double* aX, const double* aY, SIM_TRACE_TYPE aType ) { TRACE* trace = nullptr; @@ -609,8 +657,11 @@ bool SIM_PLOT_PANEL::deleteTrace( const wxString& aName ) TRACE* trace = it->second; m_traces.erase( it ); - if( CURSOR* cursor = trace->GetCursor() ) - m_plotWin->DelLayer( cursor, true ); + for( auto& [ id, cursor ] : trace->GetCursors() ) + { + if( cursor ) + m_plotWin->DelLayer( cursor, true ); + } m_plotWin->DelLayer( trace, true, true ); ResetScales(); @@ -622,30 +673,32 @@ bool SIM_PLOT_PANEL::deleteTrace( const wxString& aName ) } -void SIM_PLOT_PANEL::EnableCursor( const wxString& aName, bool aEnable ) +void SIM_PLOT_PANEL::EnableCursor( const wxString& aName, int aCursorId, bool aEnable ) { TRACE* t = GetTrace( aName ); - if( t == nullptr || t->HasCursor() == aEnable ) + if( t == nullptr || t->HasCursor( aCursorId ) == aEnable ) return; if( aEnable ) { - CURSOR* c = new CURSOR( t, this ); - int plotCenter = GetPlotWin()->GetMarginLeft() - + ( GetPlotWin()->GetXScreen() - GetPlotWin()->GetMarginLeft() - - GetPlotWin()->GetMarginRight() ) - / 2; - c->SetX( plotCenter ); - c->SetPen( wxPen( m_colors.GetPlotColor( SIM_PLOT_COLORS::COLOR_SET::CURSOR ) ) ); - t->SetCursor( c ); - m_plotWin->AddLayer( c ); + CURSOR* cursor = new CURSOR( t, this ); + mpWindow* win = GetPlotWin(); + int width = win->GetXScreen() - win->GetMarginLeft() - win->GetMarginRight(); + int center = win->GetMarginLeft() + KiROUND( width * ( aCursorId == 1 ? 0.4 : 0.6 ) ); + + cursor->SetName( aName ); + cursor->SetX( center ); + cursor->SetPen( wxPen( m_colors.GetPlotColor( SIM_PLOT_COLORS::COLOR_SET::CURSOR ) ) ); + + t->SetCursor( aCursorId, cursor ); + m_plotWin->AddLayer( cursor ); } else { - CURSOR* c = t->GetCursor(); - t->SetCursor( nullptr ); - m_plotWin->DelLayer( c, true ); + CURSOR* cursor = t->GetCursor( aCursorId ); + t->SetCursor( aCursorId, nullptr ); + m_plotWin->DelLayer( cursor, true ); } // Notify the parent window about the changes diff --git a/eeschema/sim/sim_plot_panel.h b/eeschema/sim/sim_plot_panel.h index 600b151108..6358cf2264 100644 --- a/eeschema/sim/sim_plot_panel.h +++ b/eeschema/sim/sim_plot_panel.h @@ -84,6 +84,11 @@ public: return m_coords; } + void SetCoordX( double aValue ); + +private: + void doSetCoordX( double aValue ); + private: const TRACE* m_trace; bool m_updateRequired; @@ -98,9 +103,8 @@ private: class TRACE : public mpFXYVector { public: - TRACE( const wxString& aName, SIM_PLOT_TYPE aType ) : + TRACE( const wxString& aName, SIM_TRACE_TYPE aType ) : mpFXYVector( aName ), - m_cursor( nullptr ), m_type( aType ) { SetContinuity( true ); @@ -116,8 +120,11 @@ public: */ void SetData( const std::vector& aX, const std::vector& aY ) override { - if( m_cursor ) - m_cursor->Update(); + for( auto& [ idx, cursor ] : m_cursors ) + { + if( cursor ) + cursor->Update(); + } mpFXYVector::SetData( aX, aY ); } @@ -132,27 +139,32 @@ public: return m_ys; } - bool HasCursor() const + bool HasCursor( int aCursorId ) { - return m_cursor != nullptr; + return m_cursors[ aCursorId ] != nullptr; } - void SetCursor( CURSOR* aCursor ) + void SetCursor( int aCursorId, CURSOR* aCursor ) { - m_cursor = aCursor; + m_cursors[ aCursorId ] = aCursor; } - CURSOR* GetCursor() const + CURSOR* GetCursor( int aCursorId ) { - return m_cursor; + return m_cursors[ aCursorId ]; } - SIM_PLOT_TYPE GetType() const + std::map& GetCursors() + { + return m_cursors; + } + + SIM_TRACE_TYPE GetType() const { return m_type; } - void SetTraceColour( wxColour aColour ) + void SetTraceColour( const wxColour& aColour ) { m_traceColour = aColour; } @@ -169,13 +181,13 @@ public: protected: - CURSOR* m_cursor; - SIM_PLOT_TYPE m_type; - wxColour m_traceColour; + std::map m_cursors; // No ownership; the mpWindow owns the CURSORs + SIM_TRACE_TYPE m_type; + wxColour m_traceColour; private: ///< Name of the signal parameter - wxString m_param; + wxString m_param; }; @@ -192,19 +204,21 @@ public: wxString GetLabelX() const { - return m_axis_x ? m_axis_x->GetName() : ""; + return m_axis_x ? m_axis_x->GetName() : wxS( "" ); } wxString GetLabelY1() const { - return m_axis_y1 ? m_axis_y1->GetName() : ""; + return m_axis_y1 ? m_axis_y1->GetName() : wxS( "" ); } wxString GetLabelY2() const { - return m_axis_y2 ? m_axis_y2->GetName() : ""; + return m_axis_y2 ? m_axis_y2->GetName() : wxS( "" ); } + wxString GetUnitsX() const; + bool TraceShown( const wxString& aName ) const { return m_traces.count( aName ) > 0; @@ -269,7 +283,7 @@ public: } ///< Toggle cursor for a particular trace. - void EnableCursor( const wxString& aName, bool aEnable ); + void EnableCursor( const wxString& aName, int aCursorId, bool aEnable ); ///< Reset scale ranges to fit the current traces. void ResetScales(); @@ -290,7 +304,7 @@ public: protected: bool addTrace( const wxString& aTitle, const wxString& aName, int aPoints, const double* aX, - const double* aY, SIM_PLOT_TYPE aType ); + const double* aY, SIM_TRACE_TYPE aType ); bool deleteTrace( const wxString& aName ); diff --git a/eeschema/sim/sim_types.h b/eeschema/sim/sim_types.h index 4e5d322541..239e66c8c5 100644 --- a/eeschema/sim/sim_types.h +++ b/eeschema/sim/sim_types.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2016 CERN - * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2021-2023 KiCad Developers, see AUTHORS.txt for contributors. * * @author Maciej Suminski * @@ -43,7 +43,7 @@ enum SIM_TYPE }; ///< Possible plot types -enum SIM_PLOT_TYPE +enum SIM_TRACE_TYPE { // Y axis SPT_VOLTAGE = 0x01, diff --git a/eeschema/sim/sim_workbook.cpp b/eeschema/sim/sim_workbook.cpp index 8b04ef62b3..f4c7c8dafb 100644 --- a/eeschema/sim/sim_workbook.cpp +++ b/eeschema/sim/sim_workbook.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2021 Mikołaj Wielgus - * Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2021-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 @@ -89,7 +89,7 @@ bool SIM_WORKBOOK::DeletePage( size_t page ) bool SIM_WORKBOOK::AddTrace( SIM_PLOT_PANEL* aPlotPanel, const wxString& aTitle, const wxString& aName, int aPoints, const double* aX, const double* aY, - SIM_PLOT_TYPE aType ) + SIM_TRACE_TYPE aType ) { if( aPoints && aPlotPanel->addTrace( aTitle, aName, aPoints, aX, aY, aType ) ) { diff --git a/eeschema/sim/sim_workbook.h b/eeschema/sim/sim_workbook.h index 3b731849f4..4b3d2ddbce 100644 --- a/eeschema/sim/sim_workbook.h +++ b/eeschema/sim/sim_workbook.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2021 Mikołaj Wielgus - * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2021-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 @@ -49,7 +49,7 @@ public: // Custom methods bool AddTrace( SIM_PLOT_PANEL* aPlotPanel, const wxString& aTitle, const wxString& aName, - int aPoints, const double* aX, const double* aY, SIM_PLOT_TYPE aType ); + int aPoints, const double* aX, const double* aY, SIM_TRACE_TYPE aType ); bool DeleteTrace( SIM_PLOT_PANEL* aPlotPanel, const wxString& aName ); void SetSimCommand( SIM_PANEL_BASE* aPlotPanel, const wxString& aSimCommand ) diff --git a/eeschema/sim/toolbars_sim_plot_frame.cpp b/eeschema/sim/toolbars_sim_plot_frame.cpp index 40da151e40..2fbfee334e 100644 --- a/eeschema/sim/toolbars_sim_plot_frame.cpp +++ b/eeschema/sim/toolbars_sim_plot_frame.cpp @@ -58,7 +58,6 @@ void SIM_PLOT_FRAME::ReCreateHToolbar() m_toolBar->Add( ACTIONS::zoomFitScreen ); m_toolBar->AddScaledSeparator( this ); - m_toolBar->Add( EE_ACTIONS::addSignals ); m_toolBar->Add( EE_ACTIONS::simProbe ); m_toolBar->Add( EE_ACTIONS::simTune ); @@ -123,7 +122,6 @@ void SIM_PLOT_FRAME::doReCreateMenuBar() simulationMenu->Add( EE_ACTIONS::runSimulation ); simulationMenu->AppendSeparator(); - simulationMenu->Add( EE_ACTIONS::addSignals ); simulationMenu->Add( EE_ACTIONS::simProbe ); simulationMenu->Add( EE_ACTIONS::simTune ); diff --git a/eeschema/tools/ee_actions.cpp b/eeschema/tools/ee_actions.cpp index 5aa49ea0d5..9450d4798f 100644 --- a/eeschema/tools/ee_actions.cpp +++ b/eeschema/tools/ee_actions.cpp @@ -962,12 +962,6 @@ TOOL_ACTION EE_ACTIONS::stopSimulation( "eeschema.Simulation.stopSimulation", _( "Stop Simulation" ), "", BITMAPS::sim_stop ); -TOOL_ACTION EE_ACTIONS::addSignals( "eeschema.Simulation.addSignals", - AS_GLOBAL, - 'A', "", - _( "Add Signals..." ), "", - BITMAPS::sim_add_signal ); - TOOL_ACTION EE_ACTIONS::simProbe( "eeschema.Simulation.probe", AS_GLOBAL, 'P', "", diff --git a/eeschema/tools/ee_actions.h b/eeschema/tools/ee_actions.h index 37ff5b8d6c..54a42c116b 100644 --- a/eeschema/tools/ee_actions.h +++ b/eeschema/tools/ee_actions.h @@ -256,7 +256,6 @@ public: static TOOL_ACTION simCommand; static TOOL_ACTION runSimulation; static TOOL_ACTION stopSimulation; - static TOOL_ACTION addSignals; static TOOL_ACTION showNetlist; // Net highlighting diff --git a/eeschema/tools/simulator_control.cpp b/eeschema/tools/simulator_control.cpp index 2a47178539..9429c854c9 100644 --- a/eeschema/tools/simulator_control.cpp +++ b/eeschema/tools/simulator_control.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include @@ -290,23 +289,6 @@ int SIMULATOR_CONTROL::RunSimulation( const TOOL_EVENT& aEvent ) } -int SIMULATOR_CONTROL::AddSignals( const TOOL_EVENT& aEvent ) -{ - SIM_PLOT_PANEL* plotPanel = m_plotFrame->GetCurrentPlot(); - - if( !plotPanel || !m_circuitModel || plotPanel->GetType() != m_circuitModel->GetSimType() ) - { - DisplayInfoMessage( m_plotFrame, _( "You need to run plot-providing simulation first." ) ); - return -1; - } - - DIALOG_SIGNAL_LIST dialog( m_plotFrame, m_circuitModel.get() ); - dialog.ShowModal(); - - return 0; -} - - int SIMULATOR_CONTROL::Probe( const TOOL_EVENT& aEvent ) { if( m_schematicFrame == nullptr ) @@ -435,7 +417,6 @@ void SIMULATOR_CONTROL::setTransitions() Go( &SIMULATOR_CONTROL::EditSimCommand, EE_ACTIONS::simCommand.MakeEvent() ); Go( &SIMULATOR_CONTROL::RunSimulation, EE_ACTIONS::runSimulation.MakeEvent() ); Go( &SIMULATOR_CONTROL::RunSimulation, EE_ACTIONS::stopSimulation.MakeEvent() ); - Go( &SIMULATOR_CONTROL::AddSignals, EE_ACTIONS::addSignals.MakeEvent() ); Go( &SIMULATOR_CONTROL::Probe, EE_ACTIONS::simProbe.MakeEvent() ); Go( &SIMULATOR_CONTROL::Tune, EE_ACTIONS::simTune.MakeEvent() ); diff --git a/eeschema/tools/simulator_control.h b/eeschema/tools/simulator_control.h index 9919cf1212..070a36f675 100644 --- a/eeschema/tools/simulator_control.h +++ b/eeschema/tools/simulator_control.h @@ -67,7 +67,6 @@ public: int EditSimCommand( const TOOL_EVENT& aEvent ); int RunSimulation( const TOOL_EVENT& aEvent ); - int AddSignals( const TOOL_EVENT& aEvent ); int Probe( const TOOL_EVENT& aEvent ); int Tune( const TOOL_EVENT& aEvent ); diff --git a/include/eda_pattern_match.h b/include/eda_pattern_match.h index 762b5a9c3c..33c9edde0b 100644 --- a/include/eda_pattern_match.h +++ b/include/eda_pattern_match.h @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2015-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2015-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 @@ -177,7 +177,8 @@ protected: enum COMBINED_MATCHER_CONTEXT { CTX_LIBITEM, - CTX_NETCLASS + CTX_NETCLASS, + CTX_SIGNAL }; diff --git a/qa/unittests/eeschema/sim/test_ngspice_helpers.cpp b/qa/unittests/eeschema/sim/test_ngspice_helpers.cpp index c11b218051..342a2e963b 100644 --- a/qa/unittests/eeschema/sim/test_ngspice_helpers.cpp +++ b/qa/unittests/eeschema/sim/test_ngspice_helpers.cpp @@ -131,9 +131,9 @@ BOOST_AUTO_TEST_CASE( VectorToSignal ) { struct TEST_DATA { - std::string vector; - wxString signal; - SIM_PLOT_TYPE type; + std::string vector; + wxString signal; + SIM_TRACE_TYPE type; }; std::vector testData = { @@ -189,8 +189,8 @@ BOOST_AUTO_TEST_CASE( VectorToSignal ) for( auto& step : testData ) { - wxString outputSignalName; - SIM_PLOT_TYPE retVal; + wxString outputSignalName; + SIM_TRACE_TYPE retVal; retVal = m_exporter.VectorToSignal( step.vector, outputSignalName );