Preserve plot panel order in simulator notebook

This commit is contained in:
Mikolaj Wielgus 2021-05-12 01:27:34 +02:00 committed by Wayne Stambaugh
parent afc6d29fde
commit 33c6bdd121
7 changed files with 132 additions and 70 deletions

View File

@ -340,7 +340,16 @@ void SIM_PLOT_FRAME::updateTitle()
}
void SIM_PLOT_FRAME::onModify()
void SIM_PLOT_FRAME::updateWorkbook()
{
// We need to keep track of the plot panel positions
for( unsigned int i = 0; i < m_plotNotebook->GetPageCount(); i++ )
m_workbook->SetPlotPanelPosition(
dynamic_cast<SIM_PANEL_BASE*>( m_plotNotebook->GetPage( i ) ), i );
}
void SIM_PLOT_FRAME::updateFrame()
{
updateTitle();
}
@ -518,7 +527,7 @@ SIM_PANEL_BASE* SIM_PLOT_FRAME::NewPlotPanel( wxString aSimCommand )
m_plotNotebook->AddPage( dynamic_cast<wxWindow*>( plotPanel ), pageTitle, true );
onModify();
updateFrame();
return plotPanel;
}
@ -685,7 +694,7 @@ void SIM_PLOT_FRAME::removePlot( const wxString& aPlotName, bool aErase )
updateSignalList();
wxCommandEvent dummy;
onCursorUpdate( dummy );
onModify();
updateFrame();
}
@ -794,7 +803,7 @@ bool SIM_PLOT_FRAME::updatePlot( const TRACE_DESC& aDescriptor, SIM_PLOT_PANEL*
offset += inner;
}
onModify();
updateFrame();
return true;
}
}
@ -803,7 +812,7 @@ bool SIM_PLOT_FRAME::updatePlot( const TRACE_DESC& aDescriptor, SIM_PLOT_PANEL*
data_x.data(), data_y.data(), aDescriptor.GetType() ) )
m_workbook->AddTrace( aPanel, aDescriptor.GetTitle(), aDescriptor );
onModify();
updateFrame();
return true;
}
@ -922,7 +931,7 @@ bool SIM_PLOT_FRAME::loadWorkbook( const wxString& aPath )
if( !file.Open() )
{
onModify();
updateFrame();
return false;
}
@ -931,7 +940,7 @@ bool SIM_PLOT_FRAME::loadWorkbook( const wxString& aPath )
if( !file.GetFirstLine().ToLong( &plotsCount ) ) // GetFirstLine instead of GetNextLine
{
file.Close();
onModify();
updateFrame();
return false;
}
@ -941,7 +950,7 @@ bool SIM_PLOT_FRAME::loadWorkbook( const wxString& aPath )
if( !file.GetNextLine().ToLong( &plotType ) )
{
onModify();
updateFrame();
return false;
}
@ -959,7 +968,7 @@ bool SIM_PLOT_FRAME::loadWorkbook( const wxString& aPath )
if( !file.GetNextLine().ToLong( &tracesCount ) )
{
onModify();
updateFrame();
return false;
}
@ -971,7 +980,7 @@ bool SIM_PLOT_FRAME::loadWorkbook( const wxString& aPath )
if( !file.GetNextLine().ToLong( &traceType ) )
{
file.Close();
onModify();
updateFrame();
return false;
}
@ -981,7 +990,7 @@ bool SIM_PLOT_FRAME::loadWorkbook( const wxString& aPath )
if( name.IsEmpty() || param.IsEmpty() )
{
file.Close();
onModify();
updateFrame();
return false;
}
@ -994,7 +1003,7 @@ bool SIM_PLOT_FRAME::loadWorkbook( const wxString& aPath )
// Successfully loading a workbook does not count as modyfying it.
m_workbook->ClrModified();
onModify();
updateFrame();
return true;
}
@ -1020,32 +1029,23 @@ bool SIM_PLOT_FRAME::saveWorkbook( const wxString& aPath )
file.Create();
}
unsigned long plotCount = 0;
std::vector<const SIM_PANEL_BASE*> plotPanels = m_workbook->GetSortedPlotPanels();
// XXX: Count all valid plots. Replace this once we move the workbook format to JSON or
// S-expressions.
for( const auto& plot : m_workbook->GetPlots() )
file.AddLine( wxString::Format( "%llu", plotPanels.size() ) );
for( const SIM_PANEL_BASE*& plotPanel : plotPanels )
{
if( plot.first )
plotCount++;
}
SIM_WORKBOOK::PLOT_INFO plot = m_workbook->GetPlot( plotPanel );
file.AddLine( wxString::Format( "%llu", plotCount ) );
file.AddLine( wxString::Format( "%d", plotPanel->GetType() ) );
file.AddLine( plot.m_simCommand );
file.AddLine( wxString::Format( "%llu", plot.m_traces.size() ) );
for( const auto& plot : m_workbook->GetPlots() )
{
if( plot.first )
for( const auto& trace : plot.m_traces )
{
file.AddLine( wxString::Format( "%d", plot.first->GetType() ) );
file.AddLine( plot.second.m_simCommand );
file.AddLine( wxString::Format( "%llu", plot.second.m_traces.size() ) );
for( const auto& trace : plot.second.m_traces )
{
file.AddLine( wxString::Format( "%d", trace.second.GetType() ) );
file.AddLine( trace.second.GetName() );
file.AddLine( trace.second.GetParam() );
}
file.AddLine( wxString::Format( "%d", trace.second.GetType() ) );
file.AddLine( trace.second.GetName() );
file.AddLine( trace.second.GetParam() );
}
}
@ -1056,7 +1056,7 @@ bool SIM_PLOT_FRAME::saveWorkbook( const wxString& aPath )
// the frame is closed and then opened again.
m_simulator->Settings()->SetWorkbookFilename( wxFileName( savePath ).GetFullName() );
m_workbook->ClrModified();
onModify();
updateFrame();
return res;
}
@ -1097,7 +1097,7 @@ void SIM_PLOT_FRAME::menuNewPlot( wxCommandEvent& aEvent )
if( prevPlot )
{
m_workbook->SetSimCommand( newPlot, m_workbook->GetSimCommand( prevPlot ) );
onModify();
updateFrame();
}
}
}
@ -1322,7 +1322,13 @@ void SIM_PLOT_FRAME::onPlotClose( wxAuiNotebookEvent& event )
m_workbook->RemovePlotPanel( plotPanel );
wxCommandEvent dummy;
onCursorUpdate( dummy );
onModify();
}
void SIM_PLOT_FRAME::onPlotClosed( wxAuiNotebookEvent& event )
{
updateWorkbook();
updateFrame();
}
@ -1331,6 +1337,16 @@ void SIM_PLOT_FRAME::onPlotChanged( wxAuiNotebookEvent& event )
updateSignalList();
wxCommandEvent dummy;
onCursorUpdate( dummy );
updateWorkbook();
updateFrame();
}
void SIM_PLOT_FRAME::onPlotDragged( wxAuiNotebookEvent& event )
{
updateWorkbook();
updateFrame();
}
@ -1415,7 +1431,7 @@ void SIM_PLOT_FRAME::onSettings( wxCommandEvent& event )
m_workbook->SetSimCommand( plotPanelWindow, newCommand );
m_simulator->Init();
onModify();
updateFrame();
}
}
@ -1654,7 +1670,7 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent )
updateSignalList();
plotPanel->GetPlotWin()->UpdateAll();
plotPanel->ResetScales();
onModify();
updateFrame();
}
else if( simType == ST_OP )
{

View File

@ -149,11 +149,16 @@ private:
*/
void updateTitle();
/**
* Update the workbook to match the changes in the frame.
*/
void updateWorkbook();
/**
* Update the frame to match the changes to the workbook. Should be always called after the
* workbook was modified.
*/
void onModify();
void updateFrame();
/**
* Give icons to menuitems of the main menubar.
@ -267,8 +272,10 @@ private:
}
// Event handlers
void onPlotChanged( wxAuiNotebookEvent& event ) override;
void onPlotClose( wxAuiNotebookEvent& event ) override;
void onPlotClosed( wxAuiNotebookEvent& event ) override;
void onPlotChanged( wxAuiNotebookEvent& event ) override;
void onPlotDragged( wxAuiNotebookEvent& event ) override;
void onSignalDblClick( wxMouseEvent& event ) override;
void onSignalRClick( wxListEvent& event ) override;

View File

@ -46,7 +46,7 @@ SIM_PLOT_FRAME_BASE::SIM_PLOT_FRAME_BASE( wxWindow* parent, wxWindowID id, const
m_fileMenu->AppendSeparator();
wxMenuItem* m_exitSim;
m_exitSim = new wxMenuItem( m_fileMenu, wxID_CLOSE, wxString( _("Close Simulation") ) + wxT('\t') + wxT("CTRL+W"), wxEmptyString, wxITEM_NORMAL );
m_exitSim = new wxMenuItem( m_fileMenu, wxID_CLOSE, wxString( _("Close") ) + wxT('\t') + wxT("CTRL+W"), wxEmptyString, wxITEM_NORMAL );
m_fileMenu->Append( m_exitSim );
m_mainMenu->Append( m_fileMenu, _("File") );
@ -290,8 +290,10 @@ SIM_PLOT_FRAME_BASE::SIM_PLOT_FRAME_BASE( wxWindow* parent, wxWindowID id, const
this->Connect( m_showDotted->GetId(), wxEVT_UPDATE_UI, wxUpdateUIEventHandler( SIM_PLOT_FRAME_BASE::menuShowDottedUpdate ) );
m_viewMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::menuWhiteBackground ), this, m_showWhiteBackground->GetId());
this->Connect( m_showWhiteBackground->GetId(), wxEVT_UPDATE_UI, wxUpdateUIEventHandler( SIM_PLOT_FRAME_BASE::menuShowWhiteBackgroundUpdate ) );
m_plotNotebook->Connect( wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotDragged ), NULL, this );
m_plotNotebook->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotChanged ), NULL, this );
m_plotNotebook->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotClose ), NULL, this );
m_plotNotebook->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 );
}
@ -303,8 +305,10 @@ SIM_PLOT_FRAME_BASE::~SIM_PLOT_FRAME_BASE()
this->Disconnect( ID_MENU_SHOW_LEGEND, wxEVT_UPDATE_UI, wxUpdateUIEventHandler( SIM_PLOT_FRAME_BASE::menuShowLegendUpdate ) );
this->Disconnect( ID_MENU_DOTTED, wxEVT_UPDATE_UI, wxUpdateUIEventHandler( SIM_PLOT_FRAME_BASE::menuShowDottedUpdate ) );
this->Disconnect( ID_MENU_WHITE_BG, wxEVT_UPDATE_UI, wxUpdateUIEventHandler( SIM_PLOT_FRAME_BASE::menuShowWhiteBackgroundUpdate ) );
m_plotNotebook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotDragged ), NULL, this );
m_plotNotebook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotChanged ), NULL, this );
m_plotNotebook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotClose ), NULL, this );
m_plotNotebook->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 );

View File

@ -27,7 +27,7 @@
<property name="ui_table">UI</property>
<property name="use_enum">0</property>
<property name="use_microsoft_bom">0</property>
<object class="Frame" expanded="0">
<object class="Frame" expanded="1">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
@ -54,7 +54,7 @@
<property name="window_name">SIM_PLOT_FRAME</property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<property name="xrc_skip_sizer">1</property>
<object class="wxMenuBar" expanded="0">
<object class="wxMenuBar" expanded="1">
<property name="bg"></property>
<property name="context_help"></property>
<property name="context_menu">1</property>
@ -76,7 +76,7 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<object class="wxMenu" expanded="0">
<object class="wxMenu" expanded="1">
<property name="label">File</property>
<property name="name">m_fileMenu</property>
<property name="permission">protected</property>
@ -183,7 +183,7 @@
<property name="help"></property>
<property name="id">wxID_CLOSE</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Close Simulation</property>
<property name="label">Close</property>
<property name="name">m_exitSim</property>
<property name="permission">none</property>
<property name="shortcut">CTRL+W</property>
@ -191,7 +191,7 @@
<event name="OnMenuSelection">menuExit</event>
</object>
</object>
<object class="wxMenu" expanded="0">
<object class="wxMenu" expanded="1">
<property name="label">Simulation</property>
<property name="name">m_simulationMenu</property>
<property name="permission">protected</property>
@ -286,7 +286,7 @@
<property name="unchecked_bitmap"></property>
</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>
@ -402,7 +402,7 @@
</object>
</object>
</object>
<object class="wxBoxSizer" expanded="0">
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">m_sizerMain</property>
<property name="orient">wxVERTICAL</property>
@ -469,11 +469,11 @@
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="0">
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxSplitterWindow" expanded="0">
<object class="wxSplitterWindow" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -530,8 +530,8 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxBORDER_NONE</property>
<object class="splitteritem" expanded="0">
<object class="wxPanel" expanded="0">
<object class="splitteritem" expanded="1">
<object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -582,16 +582,16 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<object class="wxBoxSizer" expanded="0">
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size">-1,-1</property>
<property name="name">m_sizer11</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">protected</property>
<object class="sizeritem" expanded="0">
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxSplitterWindow" expanded="0">
<object class="wxSplitterWindow" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -648,8 +648,8 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<object class="splitteritem" expanded="0">
<object class="wxPanel" expanded="0">
<object class="splitteritem" expanded="1">
<object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -763,15 +763,17 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnAuiNotebookEndDrag">onPlotDragged</event>
<event name="OnAuiNotebookPageChanged">onPlotChanged</event>
<event name="OnAuiNotebookPageClose">onPlotClose</event>
<event name="OnAuiNotebookPageClosed">onPlotClosed</event>
</object>
</object>
</object>
</object>
</object>
<object class="splitteritem" expanded="0">
<object class="wxPanel" expanded="0">
<object class="splitteritem" expanded="1">
<object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -899,8 +901,8 @@
</object>
</object>
</object>
<object class="splitteritem" expanded="0">
<object class="wxPanel" expanded="0">
<object class="splitteritem" expanded="1">
<object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -951,16 +953,16 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<object class="wxBoxSizer" expanded="0">
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">m_sideSizer</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">protected</property>
<object class="sizeritem" expanded="0">
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxSplitterWindow" expanded="0">
<object class="wxSplitterWindow" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -1017,8 +1019,8 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<object class="splitteritem" expanded="0">
<object class="wxPanel" expanded="0">
<object class="splitteritem" expanded="1">
<object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -1202,8 +1204,8 @@
</object>
</object>
</object>
<object class="splitteritem" expanded="0">
<object class="wxPanel" expanded="0">
<object class="splitteritem" expanded="1">
<object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>

View File

@ -110,8 +110,10 @@ class SIM_PLOT_FRAME_BASE : public KIWAY_PLAYER
virtual void menuShowDottedUpdate( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void menuWhiteBackground( wxCommandEvent& event ) { event.Skip(); }
virtual void menuShowWhiteBackgroundUpdate( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void onPlotDragged( wxAuiNotebookEvent& event ) { event.Skip(); }
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(); }

View File

@ -70,6 +70,23 @@ void SIM_WORKBOOK::RemovePlotPanel( SIM_PANEL_BASE* aPlotPanel )
}
std::vector<const SIM_PANEL_BASE*> SIM_WORKBOOK::GetSortedPlotPanels() const
{
std::vector<const SIM_PANEL_BASE*> plotPanels;
for( const auto& plot : m_plots )
plotPanels.push_back( plot.first );
std::sort( plotPanels.begin(), plotPanels.end(),
[&]( const SIM_PANEL_BASE*& a, const SIM_PANEL_BASE*& b )
{
return m_plots.at( a ).pos < m_plots.at( b ).pos;
});
return plotPanels;
}
void SIM_WORKBOOK::AddTrace( const SIM_PANEL_BASE* aPlotPanel, const wxString& aName,
const TRACE_DESC& aTrace )
{

View File

@ -90,6 +90,9 @@ public:
///< Spice directive used to execute the simulation
wxString m_simCommand;
///< The current position of the plot in the notebook
unsigned int pos;
};
typedef std::map<const SIM_PANEL_BASE*, PLOT_INFO> PLOT_MAP;
@ -101,6 +104,7 @@ public:
void AddPlotPanel( SIM_PANEL_BASE* aPlotPanel );
void RemovePlotPanel( SIM_PANEL_BASE* aPlotPanel );
std::vector<const SIM_PANEL_BASE*> GetSortedPlotPanels() const;
bool HasPlotPanel( SIM_PANEL_BASE* aPlotPanel ) const
{
@ -122,6 +126,14 @@ public:
return m_plots.at( aPlotPanel ).m_traces.cend();
}
void SetPlotPanelPosition( const SIM_PANEL_BASE* aPlotPanel, unsigned int pos )
{
if( pos != m_plots.at( aPlotPanel ).pos )
m_flagModified = true;
m_plots.at( aPlotPanel ).pos = pos;
}
void SetSimCommand( const SIM_PANEL_BASE* aPlotPanel, const wxString& aSimCommand )
{
if( m_plots.at( aPlotPanel ).m_simCommand != aSimCommand )
@ -135,14 +147,16 @@ public:
return m_plots.at( aPlotPanel ).m_simCommand;
}
const PLOT_MAP GetPlots() const { return m_plots; }
PLOT_INFO GetPlot( const SIM_PANEL_BASE* aPlotPanel ) const
{
return m_plots.at( aPlotPanel );
}
const TRACE_MAP GetTraces( const SIM_PANEL_BASE* aPlotPanel ) const
{
return m_plots.at( aPlotPanel ).m_traces;
}
void ClrModified() { m_flagModified = false; }
bool IsModified() const { return m_flagModified; }