From f3fabeb9fbeea74f575376ffe1fb27162ed5831f Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 11 Aug 2016 14:41:25 +0200 Subject: [PATCH] Right click context menu for signals (including adding cursors) --- eeschema/sim/sim_plot_frame.cpp | 73 ++++++++++++++++++ eeschema/sim/sim_plot_frame.h | 22 ++++++ eeschema/sim/sim_plot_frame_base.cpp | 2 + eeschema/sim/sim_plot_frame_base.fbp | 4 +- eeschema/sim/sim_plot_frame_base.h | 1 + eeschema/sim/sim_plot_panel.cpp | 49 ++++++++++-- eeschema/sim/sim_plot_panel.h | 110 +++++++++++++++++++-------- include/widgets/mathplot.h | 4 +- 8 files changed, 222 insertions(+), 43 deletions(-) diff --git a/eeschema/sim/sim_plot_frame.cpp b/eeschema/sim/sim_plot_frame.cpp index b459d69052..202804f3f1 100644 --- a/eeschema/sim/sim_plot_frame.cpp +++ b/eeschema/sim/sim_plot_frame.cpp @@ -235,6 +235,24 @@ void SIM_PLOT_FRAME::onSignalDblClick( wxCommandEvent& event ) } +void SIM_PLOT_FRAME::onSignalRClick( wxMouseEvent& event ) +{ + int idx = m_signals->HitTest( event.GetPosition() ); + + if( idx != wxNOT_FOUND ) + m_signals->SetSelection( idx ); + + idx = m_signals->GetSelection(); + + if( idx != wxNOT_FOUND ) + { + const wxString& netName = m_signals->GetString( idx ); + SIGNAL_CONTEXT_MENU ctxMenu( netName, this ); + m_signals->PopupMenu( &ctxMenu ); + } +} + + void SIM_PLOT_FRAME::onSimulate( wxCommandEvent& event ) { if( isSimulationRunning() ) @@ -291,6 +309,8 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent ) for( const auto& trace : plotPanel->GetTraces() ) updatePlot( trace.second->GetSpiceName(), trace.second->GetName(), plotPanel ); + + plotPanel->UpdateAll(); } } @@ -301,3 +321,56 @@ void SIM_PLOT_FRAME::onSimReport( wxCommandEvent& aEvent ) m_simConsole->Newline(); m_simConsole->MoveEnd(); /// @todo does not work.. } + + +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->CurrentPlot(); + + if( plot->IsShown( m_signal ) ) + { + Append( HIDE_SIGNAL, wxT( "Hide signal" ) ); + + TRACE* trace = plot->GetTrace( m_signal ); + + if( trace->HasCursor() ) + Append( HIDE_CURSOR, wxT( "Hide cursor" ) ); + else + Append( SHOW_CURSOR, wxT( "Show cursor" ) ); + } + else + { + Append( SHOW_SIGNAL, wxT( "Show signal" ) ); + } + + Connect( wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler( SIGNAL_CONTEXT_MENU::onMenuEvent ), NULL, this ); +} + + +void SIM_PLOT_FRAME::SIGNAL_CONTEXT_MENU::onMenuEvent( wxMenuEvent& aEvent ) +{ + SIM_PLOT_PANEL* plot = m_plotFrame->CurrentPlot(); + + switch( aEvent.GetId() ) + { + case SHOW_SIGNAL: + m_plotFrame->AddVoltagePlot( m_signal ); + break; + + break; + case HIDE_SIGNAL: + plot->DeleteTrace( m_signal ); + break; + + case SHOW_CURSOR: + plot->EnableCursor( m_signal, true ); + break; + + case HIDE_CURSOR: + plot->EnableCursor( m_signal, false ); + break; + } +} + diff --git a/eeschema/sim/sim_plot_frame.h b/eeschema/sim/sim_plot_frame.h index 7ebd542f60..cc27d69cd7 100644 --- a/eeschema/sim/sim_plot_frame.h +++ b/eeschema/sim/sim_plot_frame.h @@ -99,6 +99,7 @@ class SIM_PLOT_FRAME : public SIM_PLOT_FRAME_BASE // Event handlers void onSignalDblClick( wxCommandEvent& event ) override; + void onSignalRClick( wxMouseEvent& event ) override; void onSimulate( wxCommandEvent& event ) override; void onPlaceProbe( wxCommandEvent& event ) override; @@ -111,6 +112,27 @@ class SIM_PLOT_FRAME : public SIM_PLOT_FRAME_BASE SCH_EDIT_FRAME* m_schematicFrame; NETLIST_EXPORTER_PSPICE* m_exporter; SPICE_SIMULATOR* m_simulator; + + // 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; + + enum SIGNAL_CONTEXT_MENU_EVENTS + { + SHOW_SIGNAL, + HIDE_SIGNAL, + SHOW_CURSOR, + HIDE_CURSOR + }; + }; }; wxDEFINE_EVENT( wxEVT_SIM_REPORT, wxCommandEvent ); diff --git a/eeschema/sim/sim_plot_frame_base.cpp b/eeschema/sim/sim_plot_frame_base.cpp index cfb4b4475d..2af6beee43 100644 --- a/eeschema/sim/sim_plot_frame_base.cpp +++ b/eeschema/sim/sim_plot_frame_base.cpp @@ -157,6 +157,7 @@ SIM_PLOT_FRAME_BASE::SIM_PLOT_FRAME_BASE( wxWindow* parent, wxWindowID id, const this->Connect( m_menuShowGrid->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::menuShowGrid ) ); this->Connect( m_menuShowGrid->GetId(), wxEVT_UPDATE_UI, wxUpdateUIEventHandler( SIM_PLOT_FRAME_BASE::menuShowGridState ) ); m_signals->Connect( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::onSignalDblClick ), NULL, this ); + m_signals->Connect( wxEVT_RIGHT_UP, wxMouseEventHandler( SIM_PLOT_FRAME_BASE::onSignalRClick ), NULL, this ); m_simulateBtn->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::onSimulate ), NULL, this ); m_probeBtn->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::onPlaceProbe ), NULL, this ); m_tuneBtn->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::onTune ), NULL, this ); @@ -175,6 +176,7 @@ SIM_PLOT_FRAME_BASE::~SIM_PLOT_FRAME_BASE() this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::menuShowGrid ) ); this->Disconnect( wxID_ANY, wxEVT_UPDATE_UI, wxUpdateUIEventHandler( SIM_PLOT_FRAME_BASE::menuShowGridState ) ); m_signals->Disconnect( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::onSignalDblClick ), NULL, this ); + m_signals->Disconnect( wxEVT_RIGHT_UP, wxMouseEventHandler( SIM_PLOT_FRAME_BASE::onSignalRClick ), NULL, this ); m_simulateBtn->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::onSimulate ), NULL, this ); m_probeBtn->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::onPlaceProbe ), NULL, this ); m_tuneBtn->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::onTune ), NULL, this ); diff --git a/eeschema/sim/sim_plot_frame_base.fbp b/eeschema/sim/sim_plot_frame_base.fbp index e837859bb3..6113f943d7 100644 --- a/eeschema/sim/sim_plot_frame_base.fbp +++ b/eeschema/sim/sim_plot_frame_base.fbp @@ -206,7 +206,7 @@ - + View m_viewMenu protected @@ -790,7 +790,7 @@ - + onSignalRClick diff --git a/eeschema/sim/sim_plot_frame_base.h b/eeschema/sim/sim_plot_frame_base.h index 9e76574943..34d9556b10 100644 --- a/eeschema/sim/sim_plot_frame_base.h +++ b/eeschema/sim/sim_plot_frame_base.h @@ -69,6 +69,7 @@ class SIM_PLOT_FRAME_BASE : public KIWAY_PLAYER virtual void menuShowGrid( wxCommandEvent& event ) { event.Skip(); } virtual void menuShowGridState( wxUpdateUIEvent& event ) { event.Skip(); } virtual void onSignalDblClick( wxCommandEvent& event ) { event.Skip(); } + virtual void onSignalRClick( wxMouseEvent& event ) { event.Skip(); } virtual void onSimulate( wxCommandEvent& event ) { event.Skip(); } virtual void onPlaceProbe( wxCommandEvent& event ) { event.Skip(); } virtual void onTune( wxCommandEvent& event ) { event.Skip(); } diff --git a/eeschema/sim/sim_plot_panel.cpp b/eeschema/sim/sim_plot_panel.cpp index a2d02e025b..c960615965 100644 --- a/eeschema/sim/sim_plot_panel.cpp +++ b/eeschema/sim/sim_plot_panel.cpp @@ -43,7 +43,7 @@ void CURSOR::Plot( wxDC& aDC, mpWindow& aWindow ) if( dataX.size() <= 1 ) return; - if( m_moved ) + if( m_updateRequired ) { m_coords.x = aWindow.p2x( m_dim.x ); @@ -72,7 +72,7 @@ void CURSOR::Plot( wxDC& aDC, mpWindow& aWindow ) const double rightY = dataY[maxIdx]; m_coords.y = leftY + ( rightY - leftY ) / ( rightX - leftX ) * ( m_coords.x - leftX ); - m_moved = false; + m_updateRequired = false; } else { @@ -156,12 +156,17 @@ bool SIM_PLOT_PANEL::AddTrace( const wxString& aSpiceName, const wxString& aName bool SIM_PLOT_PANEL::DeleteTrace( const wxString& aName ) { - auto trace = m_traces.find( aName ); + auto it = m_traces.find( aName ); - if( trace != m_traces.end() ) + if( it != m_traces.end() ) { - m_traces.erase( trace ); - DelLayer( trace->second, true, true ); + m_traces.erase( it ); + TRACE* trace = it->second; + + if( CURSOR* cursor = trace->GetCursor() ) + DelLayer( cursor, true ); + + DelLayer( trace, true, true ); return true; } @@ -174,7 +179,7 @@ void SIM_PLOT_PANEL::DeleteAllTraces() { for( auto& t : m_traces ) { - DelLayer( t.second, true ); + DeleteTrace( t.first ); } m_traces.clear(); @@ -196,6 +201,36 @@ bool SIM_PLOT_PANEL::IsGridShown() const } +bool SIM_PLOT_PANEL::HasCursorEnabled( const wxString& aName ) const +{ + TRACE* t = GetTrace( aName ); + + return t ? t->HasCursor() : false; +} + + +void SIM_PLOT_PANEL::EnableCursor( const wxString& aName, bool aEnable ) +{ + TRACE* t = GetTrace( aName ); + + if( t == nullptr || t->HasCursor() == aEnable ) + return; + + if( aEnable ) + { + CURSOR* c = new CURSOR( t ); + t->SetCursor( c ); + AddLayer( c ); + } + else + { + CURSOR* c = t->GetCursor(); + t->SetCursor( NULL ); + DelLayer( c, true ); + } +} + + wxColour SIM_PLOT_PANEL::generateColor() { /// @todo have a look at: diff --git a/eeschema/sim/sim_plot_panel.h b/eeschema/sim/sim_plot_panel.h index d25896d755..202a9fb5f2 100644 --- a/eeschema/sim/sim_plot_panel.h +++ b/eeschema/sim/sim_plot_panel.h @@ -29,46 +29,24 @@ #include #include -class TRACE : public mpFXYVector -{ -public: - TRACE( const wxString& aName, const wxString& aSpiceName ) - : mpFXYVector( aName ), m_spiceName( aSpiceName ) - { - SetContinuity( true ); - ShowName( false ); - } - - const wxString& GetSpiceName() const - { - return m_spiceName; - } - - const std::vector& GetDataX() const - { - return m_xs; - } - - const std::vector& GetDataY() const - { - return m_ys; - } - -private: - wxString m_spiceName; -}; +class TRACE; class CURSOR : public mpInfoLayer { public: CURSOR( const TRACE* aTrace ) : mpInfoLayer( wxRect( 0, 0, DRAG_MARGIN, DRAG_MARGIN ), wxTRANSPARENT_BRUSH ), - m_trace( aTrace ), m_moved( false ), m_coords( 0.0, 0.0 ), m_window( nullptr ) + m_trace( aTrace ), m_updateRequired( false ), m_coords( 0.0, 0.0 ), m_window( nullptr ) { } void Plot( wxDC& aDC, mpWindow& aWindow ) override; + void Update() + { + m_updateRequired = true; + } + bool Inside( wxPoint& aPoint ) { if( !m_window ) @@ -80,7 +58,7 @@ public: void Move( wxPoint aDelta ) override { - m_moved = true; + Update(); mpInfoLayer::Move( aDelta ); } @@ -100,13 +78,68 @@ public: private: const TRACE* m_trace; - bool m_moved; + bool m_updateRequired; wxRealPoint m_coords; mpWindow* m_window; const int DRAG_MARGIN = 10; }; + +class TRACE : public mpFXYVector +{ +public: + TRACE( const wxString& aName, const wxString& aSpiceName ) + : mpFXYVector( aName ), m_spiceName( aSpiceName ), m_cursor( nullptr ) + { + SetContinuity( true ); + ShowName( false ); + } + + void SetData( const std::vector& aXs, const std::vector& aYs ) + { + mpFXYVector::SetData( aXs, aYs ); + + if( m_cursor ) + m_cursor->Update(); + } + + const wxString& GetSpiceName() const + { + return m_spiceName; + } + + const std::vector& GetDataX() const + { + return m_xs; + } + + const std::vector& GetDataY() const + { + return m_ys; + } + + bool HasCursor() const + { + return m_cursor != nullptr; + } + + void SetCursor( CURSOR* aCursor ) + { + m_cursor = aCursor; + } + + CURSOR* GetCursor() const + { + return m_cursor; + } + +private: + wxString m_spiceName; + CURSOR* m_cursor; +}; + + class SIM_PLOT_PANEL : public mpWindow { public: @@ -120,22 +153,33 @@ public: bool DeleteTrace( const wxString& aName ); + void DeleteAllTraces(); + bool IsShown( const wxString& aName ) const { return ( m_traces.count( aName ) != 0 ); } - void DeleteAllTraces(); - const std::map& GetTraces() const { return m_traces; } + TRACE* GetTrace( const wxString& aName ) const + { + auto trace = m_traces.find( aName ); + + return trace == m_traces.end() ? NULL : trace->second; + } + void ShowGrid( bool aEnable = true ); bool IsGridShown() const; + bool HasCursorEnabled( const wxString& aName ) const; + + void EnableCursor( const wxString& aName, bool aEnable ); + private: wxColour generateColor(); diff --git a/include/widgets/mathplot.h b/include/widgets/mathplot.h index bef38ede5a..430f4e7a9a 100644 --- a/include/widgets/mathplot.h +++ b/include/widgets/mathplot.h @@ -1267,11 +1267,13 @@ class WXDLLIMPEXP_MATHPLOT mpFXYVector : public mpFXY */ mpFXYVector(wxString name = wxEmptyString, int flags = mpALIGN_NE); + virtual ~mpFXYVector() {} + /** Changes the internal data: the set of points to draw. Both vectors MUST be of the same length. This method DOES NOT refresh the mpWindow; do it manually. * @sa Clear */ - void SetData( const std::vector &xs,const std::vector &ys); + virtual void SetData( const std::vector &xs,const std::vector &ys); /** Clears all the data, leaving the layer empty. * @sa SetData