From f0bd25b39797e5c1f947872696cb672dc2975bac Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sun, 29 Jan 2023 17:35:19 +0000 Subject: [PATCH] ADDED use-settable simulation trace colors. Fixes https://gitlab.com/kicad/code/kicad/issues/2536 --- common/widgets/grid_color_swatch_helpers.cpp | 21 +++++-- eeschema/dialogs/dialog_sim_model.cpp | 4 +- .../netlist_exporter_spice.cpp | 2 +- eeschema/sim/sim_plot_frame.cpp | 32 +++++++--- eeschema/sim/sim_plot_frame_base.cpp | 2 +- eeschema/sim/sim_plot_frame_base.fbp | 2 +- eeschema/sim/sim_plot_panel.cpp | 59 ++++++++++++++++--- eeschema/sim/sim_plot_panel.h | 16 ++--- 8 files changed, 104 insertions(+), 34 deletions(-) diff --git a/common/widgets/grid_color_swatch_helpers.cpp b/common/widgets/grid_color_swatch_helpers.cpp index b3da3b80a4..66f286b1dc 100644 --- a/common/widgets/grid_color_swatch_helpers.cpp +++ b/common/widgets/grid_color_swatch_helpers.cpp @@ -143,7 +143,7 @@ void GRID_CELL_COLOR_SELECTOR::Create( wxWindow* aParent, wxWindowID aId, wxEvtHandler* aEventHandler ) { // wxWidgets needs a control to hold on to the event handler - m_control = new wxCheckBox( aParent, wxID_ANY, wxEmptyString ); + m_control = new wxTextCtrl( aParent, wxID_ANY, wxEmptyString ); wxGridCellEditor::Create( aParent, aId, aEventHandler ); } @@ -159,16 +159,25 @@ void GRID_CELL_COLOR_SELECTOR::BeginEdit( int row, int col, wxGrid* grid ) { m_value.SetFromWxString( grid->GetTable()->GetValue( row, col ) ); - DIALOG_COLOR_PICKER dialog( m_parent, m_value, false ); + grid->CallAfter( + [=]() + { + DIALOG_COLOR_PICKER dialog( m_parent, m_value, false ); - if( dialog.ShowModal() == wxID_OK ) - m_value = dialog.GetColor(); + if( dialog.ShowModal() == wxID_OK ) + m_value = dialog.GetColor(); - m_grid->GetTable()->SetValue( row, col, GetValue() ); + m_grid->GetTable()->SetValue( row, col, GetValue() ); + m_grid->ForceRefresh(); + + // Let any clients know + wxGridEvent event( m_grid->GetId(), wxEVT_GRID_CELL_CHANGED, m_grid, row, col ); + event.SetString( GetValue() ); + m_grid->GetEventHandler()->ProcessEvent( event ); + } ); // That's it; we're all done m_grid->HideCellEditControl(); - m_grid->ForceRefresh(); } diff --git a/eeschema/dialogs/dialog_sim_model.cpp b/eeschema/dialogs/dialog_sim_model.cpp index 9248248b47..7b3b696500 100644 --- a/eeschema/dialogs/dialog_sim_model.cpp +++ b/eeschema/dialogs/dialog_sim_model.cpp @@ -704,7 +704,7 @@ bool DIALOG_SIM_MODEL::loadLibrary( const wxString& aLibraryP std::string modelName = SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY::NAME_FIELD ); - for( auto& [baseModelName, baseModel] : library()->GetModels() ) + for( const auto& [baseModelName, baseModel] : library()->GetModels() ) { if( baseModelName == modelName ) m_libraryModelsMgr.CreateModel( &baseModel, sourcePins, m_fields ); @@ -720,7 +720,7 @@ bool DIALOG_SIM_MODEL::loadLibrary( const wxString& aLibraryP wxArrayString modelNames; - for( auto& [name, model] : library()->GetModels() ) + for( const auto& [name, model] : library()->GetModels() ) modelNames.Add( name ); m_modelNameChoice->Clear(); diff --git a/eeschema/netlist_exporters/netlist_exporter_spice.cpp b/eeschema/netlist_exporters/netlist_exporter_spice.cpp index a854a7ab08..0d42f1843d 100644 --- a/eeschema/netlist_exporters/netlist_exporter_spice.cpp +++ b/eeschema/netlist_exporters/netlist_exporter_spice.cpp @@ -588,7 +588,7 @@ void NETLIST_EXPORTER_SPICE::writeInclude( OUTPUTFORMATTER& aFormatter, unsigned void NETLIST_EXPORTER_SPICE::writeIncludes( OUTPUTFORMATTER& aFormatter, unsigned aNetlistOptions ) { - for( auto& [path, library] : m_libMgr.GetLibraries() ) + for( const auto& [path, library] : m_libMgr.GetLibraries() ) { if( dynamic_cast( &library.get() ) ) writeInclude( aFormatter, aNetlistOptions, path ); diff --git a/eeschema/sim/sim_plot_frame.cpp b/eeschema/sim/sim_plot_frame.cpp index 1b67a65741..77d4092626 100644 --- a/eeschema/sim/sim_plot_frame.cpp +++ b/eeschema/sim/sim_plot_frame.cpp @@ -654,9 +654,10 @@ void SIM_PLOT_FRAME::OnFilterMouseMoved( wxMouseEvent& aEvent ) void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent ) { - int row = aEvent.GetRow(); - int col = aEvent.GetCol(); - wxString text = m_signalsGrid->GetCellValue( row, col ); + int row = aEvent.GetRow(); + int col = aEvent.GetCol(); + wxString text = m_signalsGrid->GetCellValue( row, col ); + SIM_PLOT_PANEL* plot = GetCurrentPlot(); if( col == COL_SIGNAL_SHOW ) { @@ -684,11 +685,25 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent ) { removeTrace( m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME ) ); } + + // Update enabled/visible states of other controls + updateSignalsGrid(); + } + 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 ); + + if( trace ) + { + trace->SetTraceColour( color.ToColour() ); + plot->UpdateTraceStyle( trace ); + plot->UpdatePlotColors(); + } } 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 ); @@ -696,9 +711,10 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent ) plot->EnableCursor( signalName, col == COL_CURSOR_1 ? 1 : 2, enable ); } - } - updateSignalsGrid(); + // Update cursor checkboxes (which are really radio buttons) + updateSignalsGrid(); + } } @@ -1808,7 +1824,7 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent ) std::vector traceInfo; // Get information about all the traces on the plot, remove and add again - for( auto& [name, trace] : plotPanel->GetTraces() ) + for( const auto& [name, trace] : plotPanel->GetTraces() ) { struct TRACE_DESC placeholder; placeholder.m_name = trace->GetName(); diff --git a/eeschema/sim/sim_plot_frame_base.cpp b/eeschema/sim/sim_plot_frame_base.cpp index e83107752c..88dc3cae18 100644 --- a/eeschema/sim/sim_plot_frame_base.cpp +++ b/eeschema/sim/sim_plot_frame_base.cpp @@ -172,7 +172,7 @@ SIM_PLOT_FRAME_BASE::SIM_PLOT_FRAME_BASE( wxWindow* parent, wxWindowID id, const // Columns m_cursorsGrid->SetColSize( 0, 44 ); - m_cursorsGrid->SetColSize( 1, 140 ); + m_cursorsGrid->SetColSize( 1, 152 ); m_cursorsGrid->SetColSize( 2, 110 ); m_cursorsGrid->SetColSize( 3, 110 ); m_cursorsGrid->EnableDragColMove( false ); diff --git a/eeschema/sim/sim_plot_frame_base.fbp b/eeschema/sim/sim_plot_frame_base.fbp index b55f27b1f1..c7fa53daec 100644 --- a/eeschema/sim/sim_plot_frame_base.fbp +++ b/eeschema/sim/sim_plot_frame_base.fbp @@ -1110,7 +1110,7 @@ "Cursor" "Signal" "Time" "Voltage / Current" wxALIGN_CENTER 4 - 44,140,110,110 + 44,152,110,110 1 0 diff --git a/eeschema/sim/sim_plot_panel.cpp b/eeschema/sim/sim_plot_panel.cpp index 700e5b1c29..ca49fd4424 100644 --- a/eeschema/sim/sim_plot_panel.cpp +++ b/eeschema/sim/sim_plot_panel.cpp @@ -260,6 +260,18 @@ void CURSOR::doSetCoordX( double aValue ) } +wxString CURSOR::getID() +{ + for( const auto& [ id, cursor ] : m_trace->GetCursors() ) + { + if( cursor == this ) + return wxString::Format( _( "%d" ), id ); + } + + return wxEmptyString; +} + + void CURSOR::Plot( wxDC& aDC, mpWindow& aWindow ) { if( !m_window ) @@ -298,7 +310,10 @@ void CURSOR::Plot( wxDC& aDC, mpWindow& aWindow ) wxCoord bottomPx = m_drawOutsideMargins ? aWindow.GetScrY() : aWindow.GetScrY() - aWindow.GetMarginBottom(); - wxPen pen = GetPen(); + wxPen pen = GetPen(); + wxColour fg = GetPen().GetColour(); + + pen.SetColour( COLOR4D( m_trace->GetTraceColour() ).Mix( fg, 0.6 ).ToColour() ); pen.SetStyle( m_continuous ? wxPENSTYLE_SOLID : wxPENSTYLE_LONG_DASH ); aDC.SetPen( pen ); @@ -306,7 +321,35 @@ void CURSOR::Plot( wxDC& aDC, mpWindow& aWindow ) aDC.DrawLine( leftPx, cursorPos.y, rightPx, cursorPos.y ); if( leftPx < cursorPos.x && cursorPos.x < rightPx ) + { aDC.DrawLine( cursorPos.x, topPx, cursorPos.x, bottomPx ); + + wxString id = getID(); + wxSize size = aDC.GetTextExtent( wxS( "M" ) ); + wxRect textRect( wxPoint( cursorPos.x + 1 - size.x / 2, topPx - 4 - size.y ), size ); + wxBrush brush; + wxPoint poly[3]; + + // Because a "1" looks off-center if it's actually centred. + if( id == "1" ) + textRect.x -= 1; + + // We want an equalateral triangle, so use size.y for both axes. + size.y += 3; + // Make sure it's an even number so the slopes of the sides will be identical. + size.y = ( size.y / 2 ) * 2; + poly[0] = { cursorPos.x - 1 - size.y / 2, topPx - size.y }; + poly[1] = { cursorPos.x + 1 + size.y / 2, topPx - size.y }; + poly[2] = { cursorPos.x, topPx }; + + brush.SetStyle( wxBRUSHSTYLE_SOLID ); + brush.SetColour( m_trace->GetTraceColour() ); + aDC.SetBrush( brush ); + aDC.DrawPolygon( 3, poly ); + + aDC.SetTextForeground( fg ); + aDC.DrawLabel( id, textRect, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL ); + } } @@ -345,7 +388,7 @@ SIM_PLOT_PANEL::SIM_PLOT_PANEL( const wxString& aCommand, int aOptions, wxWindow m_plotWin = new mpWindow( this, wxID_ANY, pos, size, style ); m_plotWin->LimitView( true ); - m_plotWin->SetMargins( 50, 80, 50, 80 ); + m_plotWin->SetMargins( 35, 70, 35, 70 ); UpdatePlotColors(); @@ -447,7 +490,7 @@ void SIM_PLOT_PANEL::updateAxes() if( m_axis_x ) { m_axis_x->SetTicks( false ); - m_axis_x->SetNameAlign ( mpALIGN_BOTTOM ); + m_axis_x->SetNameAlign( mpALIGN_BOTTOM ); m_plotWin->AddLayer( m_axis_x ); } @@ -455,14 +498,14 @@ void SIM_PLOT_PANEL::updateAxes() if( m_axis_y1 ) { m_axis_y1->SetTicks( false ); - m_axis_y1->SetNameAlign ( mpALIGN_LEFT ); + m_axis_y1->SetNameAlign( mpALIGN_LEFT ); m_plotWin->AddLayer( m_axis_y1 ); } if( m_axis_y2 ) { m_axis_y2->SetTicks( false ); - m_axis_y2->SetNameAlign ( mpALIGN_RIGHT ); + m_axis_y2->SetNameAlign( mpALIGN_RIGHT ); m_plotWin->AddLayer( m_axis_y2 ); } } @@ -540,9 +583,9 @@ void SIM_PLOT_PANEL::UpdatePlotColors() m_colors.GetPlotColor( SIM_PLOT_COLORS::COLOR_SET::AXIS ) ); // Update color of all traces - for( auto& [ name, trace ] : m_traces ) + for( const auto& [ name, trace ] : m_traces ) { - for( auto& [ id, cursor ] : trace->GetCursors() ) + for( const auto& [ id, cursor ] : trace->GetCursors() ) { if( cursor ) cursor->SetPen( wxPen( m_colors.GetPlotColor( SIM_PLOT_COLORS::COLOR_SET::CURSOR ) ) ); @@ -657,7 +700,7 @@ bool SIM_PLOT_PANEL::deleteTrace( const wxString& aName ) TRACE* trace = it->second; m_traces.erase( it ); - for( auto& [ id, cursor ] : trace->GetCursors() ) + for( const auto& [ id, cursor ] : trace->GetCursors() ) { if( cursor ) m_plotWin->DelLayer( cursor, true ); diff --git a/eeschema/sim/sim_plot_panel.h b/eeschema/sim/sim_plot_panel.h index 6358cf2264..1365a7f41f 100644 --- a/eeschema/sim/sim_plot_panel.h +++ b/eeschema/sim/sim_plot_panel.h @@ -44,7 +44,7 @@ class TRACE; class CURSOR : public mpInfoLayer { public: - CURSOR( const TRACE* aTrace, SIM_PLOT_PANEL* aPlotPanel ) : + CURSOR( TRACE* aTrace, SIM_PLOT_PANEL* aPlotPanel ) : mpInfoLayer( wxRect( 0, 0, DRAG_MARGIN, DRAG_MARGIN ), wxTRANSPARENT_BRUSH ), m_trace( aTrace ), m_updateRequired( true ), @@ -89,12 +89,14 @@ public: private: void doSetCoordX( double aValue ); + wxString getID(); + private: - const TRACE* m_trace; - bool m_updateRequired; - bool m_updateRef; - wxRealPoint m_coords; - mpWindow* m_window; + TRACE* m_trace; + bool m_updateRequired; + bool m_updateRef; + wxRealPoint m_coords; + mpWindow* m_window; static constexpr int DRAG_MARGIN = 10; }; @@ -169,7 +171,7 @@ public: m_traceColour = aColour; } - wxColour GetTraceColour() + wxColour GetTraceColour() const { return m_traceColour; }