Browse Source

ADDED: AUI Memory

Using the new wx3.3 routines to serialize the state of our AUI elements,
we store them using JSON in the preferences for each window

I have left the SavePerspective in place for now to see how legacy
(mostly *nix) builds handle this and provide a smooth transition to 3.3

Fixes https://gitlab.com/kicad/code/kicad/-/issues/2381
master
Seth Hillbrand 2 weeks ago
parent
commit
61ab7cc915
  1. 1
      common/CMakeLists.txt
  2. 41
      common/eda_base_frame.cpp
  3. 5
      common/settings/app_settings.cpp
  4. 623
      common/widgets/aui_json_serializer.cpp
  5. 1
      cvpcb/display_footprints_frame.cpp
  6. 1
      eeschema/sch_edit_frame.cpp
  7. 7
      eeschema/symbol_editor/symbol_edit_frame.cpp
  8. 1
      eeschema/symbol_viewer_frame.cpp
  9. 1
      gerbview/CMakeLists.txt
  10. 5
      include/eda_base_frame.h
  11. 2
      include/settings/app_settings.h
  12. 40
      include/widgets/aui_json_serializer.h
  13. 2
      pcbnew/footprint_edit_frame.cpp
  14. 19
      pcbnew/footprint_wizard_frame.cpp
  15. 2
      pcbnew/footprint_wizard_frame.h
  16. 2
      pcbnew/pcb_edit_frame.cpp

1
common/CMakeLists.txt

@ -166,6 +166,7 @@ set( KICOMMON_SRCS
dialogs/dialog_rc_job_base.cpp
widgets/bitmap_button.cpp
widgets/aui_json_serializer.cpp
widgets/html_window.cpp
widgets/kistatusbar.cpp
widgets/number_badge.cpp

41
common/eda_base_frame.cpp

@ -64,6 +64,7 @@
#include <widgets/paged_dialog.h>
#include <widgets/wx_busy_indicator.h>
#include <widgets/wx_infobar.h>
#include <widgets/aui_json_serializer.h>
#include <widgets/wx_aui_art_providers.h>
#include <widgets/wx_grid.h>
#include <widgets/wx_treebook.h>
@ -78,6 +79,8 @@
#include <kiplatform/io.h>
#include <kiplatform/ui.h>
#include <nlohmann/json.hpp>
#include <functional>
#include <kiface_ids.h>
@ -938,6 +941,7 @@ void EDA_BASE_FRAME::LoadWindowSettings( const WINDOW_SETTINGS* aCfg )
LoadWindowState( aCfg->state );
m_perspective = aCfg->perspective;
m_auiLayoutState = aCfg->aui_state;
m_mruPath = aCfg->mru_path;
TOOLS_HOLDER::CommonSettingsChanged();
@ -976,7 +980,22 @@ void EDA_BASE_FRAME::SaveWindowSettings( WINDOW_SETTINGS* aCfg )
// Once this is fully implemented, wxAuiManager will be used to maintain
// the persistence of the main frame and all it's managed windows and
// all of the legacy frame persistence position code can be removed.
#if wxCHECK_VERSION( 3, 3, 0 )
{
WX_AUI_JSON_SERIALIZER serializer( m_auimgr );
nlohmann::json state = serializer.Serialize();
if( state.is_null() || state.empty() )
aCfg->aui_state = nlohmann::json();
else
aCfg->aui_state = state;
aCfg->perspective.clear();
}
#else
aCfg->perspective = m_auimgr.SavePerspective().ToStdString();
aCfg->aui_state = nlohmann::json();
#endif
aCfg->mru_path = m_mruPath;
}
@ -1084,6 +1103,28 @@ void EDA_BASE_FRAME::FinishAUIInitialization()
}
void EDA_BASE_FRAME::RestoreAuiLayout()
{
#if wxCHECK_VERSION( 3, 3, 0 )
bool restored = false;
if( !m_auiLayoutState.is_null() && !m_auiLayoutState.empty() )
{
WX_AUI_JSON_SERIALIZER serializer( m_auimgr );
if( serializer.Deserialize( m_auiLayoutState ) )
restored = true;
}
if( !restored && !m_perspective.IsEmpty() )
m_auimgr.LoadPerspective( m_perspective );
#else
if( !m_perspective.IsEmpty() )
m_auimgr.LoadPerspective( m_perspective );
#endif
}
void EDA_BASE_FRAME::ShowInfoBarError( const wxString& aErrorMsg, bool aShowCloseButton,
WX_INFOBAR::MESSAGE_TYPE aType )
{

5
common/settings/app_settings.cpp

@ -30,6 +30,8 @@
#include <settings/common_settings.h>
#include <settings/grid_settings.h>
#include <settings/parameters.h>
#include <nlohmann/json.hpp>
#include <zoom_defines.h>
@ -425,6 +427,9 @@ void APP_SETTINGS_BASE::addParamsForWindow( WINDOW_SETTINGS* aWindow, const std:
m_params.emplace_back( new PARAM<wxString>( aJsonPath + ".perspective",
&aWindow->perspective, wxS( "" ) ) );
m_params.emplace_back( new PARAM<nlohmann::json>( aJsonPath + ".aui_state",
&aWindow->aui_state, nlohmann::json() ) );
m_params.emplace_back( new PARAM<int>( aJsonPath + ".pos_x", &aWindow->state.pos_x, 0 ) );
m_params.emplace_back( new PARAM<int>( aJsonPath + ".pos_y", &aWindow->state.pos_y, 0 ) );

623
common/widgets/aui_json_serializer.cpp

@ -0,0 +1,623 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The 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 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, see <http://www.gnu.org/licenses/>.
*/
#include <widgets/aui_json_serializer.h>
#include <settings/aui_settings.h>
#include <wx/aui/framemanager.h>
#if wxCHECK_VERSION( 3, 3, 0 )
#include <wx/aui/serializer.h>
#include <wx/aui/auibook.h>
#endif
#include <wx/log.h>
#include <wx/window.h>
#include <nlohmann/json.hpp>
#include <algorithm>
#include <limits>
#include <set>
#include <stdexcept>
#include <string>
#include <vector>
namespace
{
#if wxCHECK_VERSION( 3, 3, 0 )
struct PANE_METADATA
{
wxAuiPaneInfo* paneInfo;
wxString name;
wxString windowName;
wxString className;
wxString caption;
bool isToolbar;
bool isCenter;
bool isNotebook;
size_t index;
};
static wxString getWindowName( wxWindow* aWindow )
{
if( !aWindow )
return wxString();
wxString name = aWindow->GetName();
if( name.IsEmpty() )
// Fallback: use label if available (GetWindowVariant returns enum, not a string)
name = aWindow->GetLabel();
return name;
}
static PANE_METADATA buildMetadata( wxAuiPaneInfo& aInfo, size_t aIndex )
{
PANE_METADATA meta;
meta.paneInfo = &aInfo;
meta.name = aInfo.name;
meta.caption = aInfo.caption;
meta.isToolbar = aInfo.IsToolbar();
meta.isCenter = ( aInfo.dock_direction == wxAUI_DOCK_CENTER );
meta.isNotebook = aInfo.window && wxDynamicCast( aInfo.window, wxAuiNotebook );
meta.index = aIndex;
if( aInfo.window )
{
meta.windowName = getWindowName( aInfo.window );
if( aInfo.window->GetClassInfo() )
meta.className = aInfo.window->GetClassInfo()->GetClassName();
}
return meta;
}
static void addDockLayout( nlohmann::json& aNode, const wxAuiDockLayoutInfo& aLayout )
{
nlohmann::json dock = nlohmann::json::object();
dock["direction"] = aLayout.dock_direction;
dock["layer"] = aLayout.dock_layer;
dock["row"] = aLayout.dock_row;
dock["position"] = aLayout.dock_pos;
dock["proportion"] = aLayout.dock_proportion;
dock["size"] = aLayout.dock_size;
aNode["dock"] = std::move( dock );
}
static void readDockLayout( const nlohmann::json& aNode, wxAuiDockLayoutInfo& aLayout )
{
if( !aNode.is_object() )
return;
aLayout.dock_direction = aNode.value( "direction", aLayout.dock_direction );
aLayout.dock_layer = aNode.value( "layer", aLayout.dock_layer );
aLayout.dock_row = aNode.value( "row", aLayout.dock_row );
aLayout.dock_pos = aNode.value( "position", aLayout.dock_pos );
aLayout.dock_proportion = aNode.value( "proportion", aLayout.dock_proportion );
aLayout.dock_size = aNode.value( "size", aLayout.dock_size );
}
class JSON_SERIALIZER : public wxAuiSerializer
{
public:
explicit JSON_SERIALIZER( wxAuiManager& aManager ) : m_manager( aManager ), m_paneIndex( 0 )
{
m_root = nlohmann::json::object();
}
nlohmann::json GetState() const
{
return m_root;
}
void BeforeSave() override
{
m_root["format"] = "kicad.wxaui";
m_root["version"] = 1;
}
void BeforeSavePanes() override
{
m_panes = nlohmann::json::array();
m_paneIndex = 0;
}
void SavePane( const wxAuiPaneLayoutInfo& aPane ) override
{
nlohmann::json pane = nlohmann::json::object();
pane["name"] = aPane.name.ToStdString();
addDockLayout( pane, aPane );
if( aPane.floating_pos != wxDefaultPosition || aPane.floating_size != wxDefaultSize )
{
nlohmann::json floating = nlohmann::json::object();
floating["rect"] = wxRect( aPane.floating_pos, aPane.floating_size );
pane["floating"] = std::move( floating );
}
if( aPane.is_maximized )
pane["maximized"] = true;
if( aPane.is_hidden )
pane["hidden"] = true;
wxAuiPaneInfo& info = m_manager.GetPane( aPane.name );
nlohmann::json meta = nlohmann::json::object();
meta["toolbar"] = info.IsToolbar();
meta["center"] = ( info.dock_direction == wxAUI_DOCK_CENTER );
meta["notebook"] = info.window && wxDynamicCast( info.window, wxAuiNotebook );
meta["index"] = m_paneIndex++;
if( info.window )
{
wxString windowName = getWindowName( info.window );
if( !windowName.IsEmpty() )
meta["window_name"] = windowName.ToStdString();
if( info.window->GetClassInfo() )
meta["class_name"] = wxString( info.window->GetClassInfo()->GetClassName() ).ToStdString();
}
if( !info.caption.IsEmpty() )
meta["caption"] = info.caption.ToStdString();
pane["meta"] = std::move( meta );
m_panes.push_back( std::move( pane ) );
}
void AfterSavePanes() override
{
m_root["panes"] = std::move( m_panes );
}
void BeforeSaveNotebooks() override
{
m_notebooks = nlohmann::json::array();
}
void BeforeSaveNotebook( const wxString& aName ) override
{
m_currentNotebook = nlohmann::json::object();
m_currentNotebook["name"] = aName.ToStdString();
wxAuiPaneInfo& info = m_manager.GetPane( aName );
nlohmann::json meta = nlohmann::json::object();
if( info.window )
{
wxString windowName = getWindowName( info.window );
if( !windowName.IsEmpty() )
meta["window_name"] = windowName.ToStdString();
if( info.window->GetClassInfo() )
meta["class_name"] = wxString( info.window->GetClassInfo()->GetClassName() ).ToStdString();
}
if( !info.caption.IsEmpty() )
meta["caption"] = info.caption.ToStdString();
meta["toolbar"] = info.IsToolbar();
meta["center"] = ( info.dock_direction == wxAUI_DOCK_CENTER );
meta["notebook"] = true;
m_currentNotebook["meta"] = std::move( meta );
m_currentNotebook["tabs"] = nlohmann::json::array();
}
void SaveNotebookTabControl( const wxAuiTabLayoutInfo& aTab ) override
{
nlohmann::json tab = nlohmann::json::object();
addDockLayout( tab, aTab );
if( !aTab.pages.empty() )
tab["pages"] = aTab.pages;
if( !aTab.pinned.empty() )
tab["pinned"] = aTab.pinned;
if( aTab.active >= 0 )
tab["active"] = aTab.active;
m_currentNotebook["tabs"].push_back( std::move( tab ) );
}
void AfterSaveNotebook() override
{
m_notebooks.push_back( std::move( m_currentNotebook ) );
m_currentNotebook = nlohmann::json();
}
void AfterSaveNotebooks() override
{
if( !m_notebooks.empty() )
m_root["notebooks"] = std::move( m_notebooks );
}
void AfterSave() override {}
private:
wxAuiManager& m_manager;
nlohmann::json m_root;
nlohmann::json m_panes;
nlohmann::json m_notebooks;
nlohmann::json m_currentNotebook;
size_t m_paneIndex;
};
class JSON_DESERIALIZER : public wxAuiDeserializer
{
public:
JSON_DESERIALIZER( wxAuiManager& aManager, const nlohmann::json& aState )
: wxAuiDeserializer( aManager ), m_manager( aManager ), m_state( aState )
{
if( !m_state.is_object() )
throw std::runtime_error( "Invalid AUI layout state" );
const std::string format = m_state.value( "format", std::string() );
if( format != "kicad.wxaui" )
throw std::runtime_error( "Unsupported AUI layout format" );
int version = m_state.value( "version", 0 );
if( version != 1 )
throw std::runtime_error( "Unsupported AUI layout version" );
if( m_state.contains( "panes" ) && m_state["panes"].is_array() )
m_serializedPanes = m_state["panes"].get<std::vector<nlohmann::json>>();
if( m_state.contains( "notebooks" ) && m_state["notebooks"].is_array() )
m_serializedNotebooks = m_state["notebooks"].get<std::vector<nlohmann::json>>();
}
std::vector<wxAuiPaneLayoutInfo> LoadPanes() override
{
std::vector<wxAuiPaneLayoutInfo> panes;
wxAuiPaneInfoArray paneArray = m_manager.GetAllPanes();
std::vector<PANE_METADATA> metadata;
metadata.reserve( paneArray.GetCount() );
for( size_t i = 0; i < paneArray.GetCount(); ++i )
metadata.push_back( buildMetadata( paneArray[i], i ) );
std::set<wxAuiPaneInfo*> used;
for( const nlohmann::json& jsonPane : m_serializedPanes )
{
if( !jsonPane.is_object() )
continue;
wxAuiPaneLayoutInfo pane( wxString::FromUTF8( jsonPane.value( "name", std::string() ) ) );
readDockLayout( jsonPane.value( "dock", nlohmann::json::object() ), pane );
if( jsonPane.contains( "floating" ) )
{
const nlohmann::json& floating = jsonPane["floating"];
if( floating.contains( "rect" ) )
{
wxRect rect = floating["rect"].get<wxRect>();
pane.floating_pos = rect.GetPosition();
pane.floating_size = rect.GetSize();
}
}
pane.is_maximized = jsonPane.value( "maximized", false );
pane.is_hidden = jsonPane.value( "hidden", false );
wxAuiPaneInfo* actualPane = matchPane( jsonPane, metadata, used );
if( actualPane )
{
pane.name = actualPane->name;
used.insert( actualPane );
panes.push_back( pane );
}
}
return panes;
}
std::vector<wxAuiTabLayoutInfo> LoadNotebookTabs( const wxString& aName ) override
{
const wxAuiPaneInfo& paneInfo = m_manager.GetPane( aName );
auto loadTabs = []( const nlohmann::json& aNotebook )
{
std::vector<wxAuiTabLayoutInfo> tabs;
if( !aNotebook.contains( "tabs" ) || !aNotebook["tabs"].is_array() )
return tabs;
for( const nlohmann::json& tabJson : aNotebook["tabs"].get<std::vector<nlohmann::json>>() )
{
if( !tabJson.is_object() )
continue;
wxAuiTabLayoutInfo info;
readDockLayout( tabJson.value( "dock", nlohmann::json::object() ), info );
if( tabJson.contains( "pages" ) )
{
info.pages.clear();
for( int page : tabJson["pages"].get<std::vector<int>>() )
info.pages.push_back( page );
}
if( tabJson.contains( "pinned" ) )
{
info.pinned.clear();
for( int page : tabJson["pinned"].get<std::vector<int>>() )
info.pinned.push_back( page );
}
info.active = tabJson.value( "active", info.active );
tabs.push_back( info );
}
return tabs;
};
for( const nlohmann::json& notebook : m_serializedNotebooks )
{
if( !notebook.is_object() )
continue;
wxString storedName = wxString::FromUTF8( notebook.value( "name", std::string() ) );
if( storedName == aName )
return loadTabs( notebook );
}
if( !paneInfo.IsOk() )
return {};
wxString windowName = paneInfo.window ? getWindowName( paneInfo.window ) : wxString();
wxString className;
if( paneInfo.window && paneInfo.window->GetClassInfo() )
className = paneInfo.window->GetClassInfo()->GetClassName();
for( const nlohmann::json& notebook : m_serializedNotebooks )
{
if( !notebook.is_object() )
continue;
const nlohmann::json& meta = notebook.value( "meta", nlohmann::json::object() );
const wxString storedWindowName = wxString::FromUTF8( meta.value( "window_name", std::string() ) );
const wxString storedClassName = wxString::FromUTF8( meta.value( "class_name", std::string() ) );
const bool toolbar = meta.value( "toolbar", false );
const bool center = meta.value( "center", false );
const bool notebookFlag = meta.value( "notebook", false );
if( toolbar != paneInfo.IsToolbar() || center != ( paneInfo.dock_direction == wxAUI_DOCK_CENTER ) )
continue;
if( !notebookFlag )
continue;
if( !windowName.IsEmpty() && !storedWindowName.IsEmpty() && windowName == storedWindowName )
return loadTabs( notebook );
if( !className.IsEmpty() && !storedClassName.IsEmpty() && className == storedClassName )
return loadTabs( notebook );
}
return {};
}
wxWindow* CreatePaneWindow( wxAuiPaneInfo& ) override
{
return nullptr;
}
private:
wxAuiPaneInfo* matchPane( const nlohmann::json& aJson,
const std::vector<PANE_METADATA>& aMetadata,
const std::set<wxAuiPaneInfo*>& aUsed ) const
{
auto selectCandidate = [&aUsed]( wxAuiPaneInfo* pane ) -> bool
{
return pane && aUsed.find( pane ) == aUsed.end();
};
wxString storedName = wxString::FromUTF8( aJson.value( "name", std::string() ) );
if( !storedName.IsEmpty() )
{
wxAuiPaneInfo& pane = m_manager.GetPane( storedName );
if( pane.IsOk() && selectCandidate( &pane ) )
return &pane;
}
wxAuiPaneInfo* match = nullptr;
const nlohmann::json& meta = aJson.value( "meta", nlohmann::json::object() );
const wxString windowName = wxString::FromUTF8( meta.value( "window_name", std::string() ) );
const wxString className = wxString::FromUTF8( meta.value( "class_name", std::string() ) );
const wxString caption = wxString::FromUTF8( meta.value( "caption", std::string() ) );
const bool isToolbar = meta.value( "toolbar", false );
const bool isCenter = meta.value( "center", false );
const bool isNotebook = meta.value( "notebook", false );
const size_t index = meta.value( "index", std::numeric_limits<size_t>::max() );
auto findBy = [&]( auto predicate ) -> wxAuiPaneInfo*
{
wxAuiPaneInfo* candidate = nullptr;
for( const PANE_METADATA& data : aMetadata )
{
if( !predicate( data ) )
continue;
if( !selectCandidate( data.paneInfo ) )
continue;
if( candidate )
return nullptr;
candidate = data.paneInfo;
}
return candidate;
};
if( !windowName.IsEmpty() )
{
match = findBy( [&]( const PANE_METADATA& data )
{
return data.windowName == windowName;
} );
if( match )
return match;
}
if( !className.IsEmpty() )
{
match = findBy( [&]( const PANE_METADATA& data )
{
if( data.className != className )
return false;
if( data.isToolbar != isToolbar )
return false;
if( data.isCenter != isCenter )
return false;
if( data.isNotebook != isNotebook )
return false;
return true;
} );
if( match )
return match;
}
if( index != std::numeric_limits<size_t>::max() )
{
match = findBy( [&]( const PANE_METADATA& data )
{
return data.index == index;
} );
if( match )
return match;
}
if( !caption.IsEmpty() )
{
match = findBy( [&]( const PANE_METADATA& data )
{
return data.caption == caption;
} );
if( match )
return match;
}
match = findBy( [&]( const PANE_METADATA& data )
{
if( data.isToolbar != isToolbar )
return false;
if( data.isNotebook != isNotebook )
return false;
return true;
} );
return match;
}
wxAuiManager& m_manager;
nlohmann::json m_state;
std::vector<nlohmann::json> m_serializedPanes;
std::vector<nlohmann::json> m_serializedNotebooks;
};
#endif
} // namespace
WX_AUI_JSON_SERIALIZER::WX_AUI_JSON_SERIALIZER( wxAuiManager& aManager ) : m_manager( aManager )
{
}
nlohmann::json WX_AUI_JSON_SERIALIZER::Serialize() const
{
#if wxCHECK_VERSION( 3, 3, 0 )
try
{
JSON_SERIALIZER serializer( m_manager );
m_manager.SaveLayout( serializer );
return serializer.GetState();
}
catch( const std::exception& err )
{
wxLogWarning( "Failed to serialize AUI layout: %s", err.what() );
}
#endif
return nlohmann::json();
}
bool WX_AUI_JSON_SERIALIZER::Deserialize( const nlohmann::json& aState ) const
{
#if wxCHECK_VERSION( 3, 3, 0 )
if( aState.is_null() || aState.empty() )
return false;
try
{
JSON_DESERIALIZER deserializer( m_manager, aState );
m_manager.LoadLayout( deserializer );
return true;
}
catch( const std::exception& err )
{
wxLogWarning( "Failed to deserialize AUI layout: %s", err.what() );
}
#endif
return false;
}

1
cvpcb/display_footprints_frame.cpp

@ -136,6 +136,7 @@ DISPLAY_FOOTPRINTS_FRAME::DISPLAY_FOOTPRINTS_FRAME( KIWAY* aKiway, wxWindow* aPa
m_auimgr.AddPane( m_messagePanel, EDA_PANE().Messages().Name( wxS( "MsgPanel" ) )
.Bottom().Layer( 6 ) );
RestoreAuiLayout();
FinishAUIInitialization();
auto& galOpts = GetGalDisplayOptions();

1
eeschema/sch_edit_frame.cpp

@ -277,6 +277,7 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
.DestroyOnClose( false )
.Show( m_show_search ) );
RestoreAuiLayout();
FinishAUIInitialization();
wxAuiPaneInfo& hierarchy_pane = m_auimgr.GetPane( SchematicHierarchyPaneName() );

7
eeschema/symbol_editor/symbol_edit_frame.cpp

@ -218,11 +218,12 @@ SYMBOL_EDIT_FRAME::SYMBOL_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
.MinSize( FromDIP( 250 ), -1 ).BestSize( FromDIP( 250 ), -1 ) );
m_auimgr.AddPane( m_propertiesPanel, defaultPropertiesPaneInfo( this ) );
// Show or hide m_propertiesPanel depending on current settings:
wxAuiPaneInfo& propertiesPaneInfo = m_auimgr.GetPane( PropertiesPaneName() );
m_auimgr.AddPane( m_selectionFilterPanel, defaultSchSelectionFilterPaneInfo( this ) );
RestoreAuiLayout();
// Show or hide m_propertiesPanel depending on current settings:
wxAuiPaneInfo& propertiesPaneInfo = m_auimgr.GetPane( PropertiesPaneName() );
wxAuiPaneInfo& selectionFilterPane = m_auimgr.GetPane( wxS( "SelectionFilter" ) );
// The selection filter doesn't need to grow in the vertical direction when docked
selectionFilterPane.dock_proportion = 0;

1
eeschema/symbol_viewer_frame.cpp

@ -217,6 +217,7 @@ SYMBOL_VIEWER_FRAME::SYMBOL_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
m_auimgr.AddPane( GetCanvas(), EDA_PANE().Canvas().Name( "DrawFrame" ).Center() );
RestoreAuiLayout();
m_auimgr.Update();
if( m_libListWidth > 0 )

1
gerbview/CMakeLists.txt

@ -156,6 +156,7 @@ target_link_libraries( gerbview_kiface
PRIVATE
nlohmann_json
gal
kicommon
common
core
gerbview_kiface_objects

5
include/eda_base_frame.h

@ -37,6 +37,8 @@
#include <optional>
#include <vector>
#include <nlohmann/json_fwd.hpp>
#include <wx/aui/aui.h>
#include <layer_ids.h>
#include <frame_type.h>
@ -238,6 +240,8 @@ public:
void CreateInfoBar();
void RestoreAuiLayout();
void FinishAUIInitialization();
/**
@ -802,6 +806,7 @@ private:
wxAuiManager m_auimgr;
wxString m_perspective; // wxAuiManager perspective.
nlohmann::json m_auiLayoutState;
WX_INFOBAR* m_infoBar; // Infobar for the frame
APPEARANCE_CONTROLS_3D* m_appearancePanel;
wxString m_configName; // Prefix used to identify some params (frame

2
include/settings/app_settings.h

@ -22,6 +22,7 @@
#define _APP_SETTINGS_H
#include <gal/color4d.h>
#include <nlohmann/json_fwd.hpp>
#include <settings/json_settings.h>
#include <settings/grid_settings.h>
@ -97,6 +98,7 @@ struct KICOMMON_API WINDOW_SETTINGS
WINDOW_STATE state;
wxString mru_path;
wxString perspective;
nlohmann::json aui_state;
std::vector<double> zoom_factors;
CURSOR_SETTINGS cursor;

40
include/widgets/aui_json_serializer.h

@ -0,0 +1,40 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The 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 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef KICAD_WIDGETS_AUI_JSON_SERIALIZER_H
#define KICAD_WIDGETS_AUI_JSON_SERIALIZER_H
#include <nlohmann/json_fwd.hpp>
#include <kicommon.h>
class wxAuiManager;
class KICOMMON_API WX_AUI_JSON_SERIALIZER
{
public:
explicit WX_AUI_JSON_SERIALIZER( wxAuiManager& aManager );
nlohmann::json Serialize() const;
bool Deserialize( const nlohmann::json& aState ) const;
private:
wxAuiManager& m_manager;
};
#endif

2
pcbnew/footprint_edit_frame.cpp

@ -250,6 +250,8 @@ FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
m_auimgr.AddPane( GetCanvas(), EDA_PANE().Canvas().Name( "DrawFrame" )
.Center() );
RestoreAuiLayout();
m_auimgr.GetPane( "LayersManager" ).Show( m_show_layer_manager_tools );
m_auimgr.GetPane( "SelectionFilter" ).Show( m_show_layer_manager_tools );
m_auimgr.GetPane( PropertiesPaneName() ).Show( GetSettings()->m_AuiPanels.show_properties );

19
pcbnew/footprint_wizard_frame.cpp

@ -36,8 +36,11 @@
#include <footprint_edit_frame.h>
#include <footprint_editor_settings.h>
#include <pcbnew_id.h>
#include <widgets/aui_json_serializer.h>
#include <wx/listbox.h>
#include <wx/statline.h>
#include <nlohmann/json.hpp>
#include <wx/tokenzr.h>
#include <wx/numformatter.h>
#include <wx/wupdlock.h>
@ -509,6 +512,7 @@ void FOOTPRINT_WIZARD_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
PCB_BASE_FRAME::LoadSettings( cfg );
m_auiPerspective = cfg->m_FootprintViewer.perspective;
m_viewerAuiState = cfg->m_FootprintViewer.aui_state;
}
@ -519,7 +523,22 @@ void FOOTPRINT_WIZARD_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
PCB_BASE_FRAME::SaveSettings( cfg );
#if wxCHECK_VERSION( 3, 3, 0 )
{
WX_AUI_JSON_SERIALIZER serializer( m_auimgr );
nlohmann::json state = serializer.Serialize();
if( state.is_null() || state.empty() )
cfg->m_FootprintViewer.aui_state = nlohmann::json();
else
cfg->m_FootprintViewer.aui_state = state;
cfg->m_FootprintViewer.perspective.clear();
}
#else
cfg->m_FootprintViewer.perspective = m_auimgr.SavePerspective().ToStdString();
cfg->m_FootprintViewer.aui_state = nlohmann::json();
#endif
}

2
pcbnew/footprint_wizard_frame.h

@ -33,6 +33,7 @@
#include <wx/gdicmn.h>
#include <footprint_wizard.h>
#include <pcb_base_edit_frame.h>
#include <nlohmann/json_fwd.hpp>
class wxSashLayoutWindow;
class wxSashEvent;
@ -191,6 +192,7 @@ private:
wxTextCtrl* m_buildMessageBox;
wxString m_auiPerspective; ///< Encoded string describing the AUI layout
nlohmann::json m_viewerAuiState;
bool m_wizardListShown; ///< A show-once flag for the wizard list
};

2
pcbnew/pcb_edit_frame.cpp

@ -378,6 +378,7 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
.DestroyOnClose( false )
.CloseButton( true ) );
RestoreAuiLayout();
m_auimgr.GetPane( "LayersManager" ).Show( m_show_layer_manager_tools );
m_auimgr.GetPane( "SelectionFilter" ).Show( m_show_layer_manager_tools );
@ -388,7 +389,6 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
// The selection filter doesn't need to grow in the vertical direction when docked
m_auimgr.GetPane( "SelectionFilter" ).dock_proportion = 0;
FinishAUIInitialization();
if( aui_cfg.right_panel_width > 0 )

Loading…
Cancel
Save