Right click context menu for signals (including adding cursors)
This commit is contained in:
parent
d5ce31dc8e
commit
f3fabeb9fb
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -206,7 +206,7 @@
|
|||
<event name="OnUpdateUI"></event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="wxMenu" expanded="0">
|
||||
<object class="wxMenu" expanded="1">
|
||||
<property name="label">View</property>
|
||||
<property name="name">m_viewMenu</property>
|
||||
<property name="permission">protected</property>
|
||||
|
@ -790,7 +790,7 @@
|
|||
<event name="OnPaint"></event>
|
||||
<event name="OnRightDClick"></event>
|
||||
<event name="OnRightDown"></event>
|
||||
<event name="OnRightUp"></event>
|
||||
<event name="OnRightUp">onSignalRClick</event>
|
||||
<event name="OnSetFocus"></event>
|
||||
<event name="OnSize"></event>
|
||||
<event name="OnUpdateUI"></event>
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -29,46 +29,24 @@
|
|||
#include <widgets/mathplot.h>
|
||||
#include <map>
|
||||
|
||||
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<double>& GetDataX() const
|
||||
{
|
||||
return m_xs;
|
||||
}
|
||||
|
||||
const std::vector<double>& 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<double>& aXs, const std::vector<double>& aYs )
|
||||
{
|
||||
mpFXYVector::SetData( aXs, aYs );
|
||||
|
||||
if( m_cursor )
|
||||
m_cursor->Update();
|
||||
}
|
||||
|
||||
const wxString& GetSpiceName() const
|
||||
{
|
||||
return m_spiceName;
|
||||
}
|
||||
|
||||
const std::vector<double>& GetDataX() const
|
||||
{
|
||||
return m_xs;
|
||||
}
|
||||
|
||||
const std::vector<double>& 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<wxString, TRACE*>& 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();
|
||||
|
||||
|
|
|
@ -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<double> &xs,const std::vector<double> &ys);
|
||||
virtual void SetData( const std::vector<double> &xs,const std::vector<double> &ys);
|
||||
|
||||
/** Clears all the data, leaving the layer empty.
|
||||
* @sa SetData
|
||||
|
|
Loading…
Reference in New Issue