Speed up pcbnew loading/updating

Rather than detaching and re-attaching the layer panels with the
attendant overhead, we keep each panel intact and only update its
contents.  Since the bindings are the same, this saves substantial time
on pcb loading as well as when closing the board setup dialog
This commit is contained in:
Seth Hillbrand 2021-10-09 13:22:09 -07:00
parent 8f74085ca4
commit 41e7284fdc
4 changed files with 128 additions and 44 deletions

View File

@ -25,7 +25,7 @@
#ifndef _BITMAP_TOGGLE_H #ifndef _BITMAP_TOGGLE_H
#define _BITMAP_TOGGLE_H #define _BITMAP_TOGGLE_H
#include <wx/bitmap.h> #include <wx/statbmp.h>
#include <wx/panel.h> #include <wx/panel.h>
#include <gal/color4d.h> #include <gal/color4d.h>
@ -54,6 +54,16 @@ public:
///< Read the checkbox state ///< Read the checkbox state
bool GetValue() const { return m_checked; } bool GetValue() const { return m_checked; }
/**
* Updates the window ID of this control and its children
* @param aId new Window ID to set
*/
void SetWindowID( wxWindowID aId )
{
SetId( aId );
m_bitmap->SetId( aId );
}
private: private:
bool m_checked; bool m_checked;

View File

@ -99,6 +99,16 @@ public:
*/ */
KIGFX::COLOR4D GetSwatchColor() const; KIGFX::COLOR4D GetSwatchColor() const;
/**
* Updates the window ID of this control and its children
* @param aId new Window ID to set
*/
void SetWindowID( wxWindowID aId )
{
SetId( aId );
m_swatch->SetId( aId );
}
/** /**
* Prompt for a new colour, using the colour picker dialog. * Prompt for a new colour, using the colour picker dialog.
* *

View File

@ -24,7 +24,7 @@
#ifndef ROW_INDICATOR__H_ #ifndef ROW_INDICATOR__H_
#define ROW_INDICATOR__H_ #define ROW_INDICATOR__H_
#include <wx/bitmap.h> #include <wx/statbmp.h>
#include <wx/panel.h> #include <wx/panel.h>
class wxStaticBitmap; class wxStaticBitmap;
@ -97,6 +97,16 @@ public:
*/ */
ICON_ID GetIndicatorState() const; ICON_ID GetIndicatorState() const;
/**
* Updates the window ID of this control and its children
* @param aId new Window ID to set
*/
void SetWindowID( wxWindowID aId )
{
SetId( aId );
m_bitmap->SetId( aId );
}
private: private:
///< An class that delivers icons for the indicator (currently just ///< An class that delivers icons for the indicator (currently just

View File

@ -1408,10 +1408,6 @@ void APPEARANCE_CONTROLS::rebuildLayers()
m_windowLayersSizerItem->SetFlag( m_windowLayersSizerItem->GetFlag() & ~wxTOP ); m_windowLayersSizerItem->SetFlag( m_windowLayersSizerItem->GetFlag() & ~wxTOP );
#endif #endif
m_layerSettings.clear();
m_layerSettingsMap.clear();
m_layersOuterSizer->Clear( true );
auto appendLayer = auto appendLayer =
[&]( std::unique_ptr<APPEARANCE_SETTING>& aSetting ) [&]( std::unique_ptr<APPEARANCE_SETTING>& aSetting )
{ {
@ -1500,39 +1496,21 @@ void APPEARANCE_CONTROLS::rebuildLayers()
label->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this ); label->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
}; };
// Add right click handling to show the conterxt menu when clicking to the free area in auto updateLayer =
// m_windowLayers (below the layer items) [&]( std::unique_ptr<APPEARANCE_SETTING>& aSetting )
m_windowLayers->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this ); {
int layer = aSetting->id;
wxString dsc; aSetting->visible = visible[layer];
aSetting->ctl_panel->Show();
// show all coppers first, with front on top, back on bottom, then technical layers aSetting->ctl_panel->SetId( layer );
for( LSEQ cu_stack = enabled.CuStack(); cu_stack; ++cu_stack ) aSetting->ctl_indicator->SetWindowID( layer );
{ aSetting->ctl_color->SetWindowID( layer );
PCB_LAYER_ID layer = *cu_stack; aSetting->ctl_color->SetSwatchColor( theme->GetColor( layer ), false );
aSetting->ctl_visibility->SetWindowID( layer );
switch( layer ) aSetting->ctl_text->SetLabelText( aSetting->label );
{ aSetting->ctl_text->SetId( layer );
case F_Cu: dsc = _( "Front copper layer" ); break; aSetting->ctl_text->SetToolTip( aSetting->tooltip );
case B_Cu: dsc = _( "Back copper layer" ); break; };
default: dsc = _( "Inner copper layer" ); break;
}
m_layerSettings.emplace_back(
std::make_unique<APPEARANCE_SETTING>( board->GetLayerName( layer ), layer, dsc ) );
std::unique_ptr<APPEARANCE_SETTING>& setting = m_layerSettings.back();
m_layerSettingsMap[layer] = setting.get();
appendLayer( setting );
if( m_isFpEditor && LSET::ForbiddenFootprintLayers().test( layer ) )
{
setting->ctl_text->Disable();
setting->ctl_color->SetToolTip( wxEmptyString );
}
}
// technical layers are shown in this order: // technical layers are shown in this order:
// Because they are static, wxGetTranslation must be explicitly // Because they are static, wxGetTranslation must be explicitly
@ -1570,6 +1548,76 @@ void APPEARANCE_CONTROLS::rebuildLayers()
{ User_9, _( "User defined layer 9" ) }, { User_9, _( "User defined layer 9" ) },
}; };
// There is a spacer added to the end of the list that we need to remove and re-add
// after possibly adding additional layers
if( m_layersOuterSizer->GetItemCount() > 0 )
{
m_layersOuterSizer->Detach( m_layersOuterSizer->GetItemCount() - 1 );
}
// Otherwise, this is the first time we are updating the control, so we need to attach
// the handler
else
{
// Add right click handling to show the context menu when clicking to the free area in
// m_windowLayers (below the layer items)
m_windowLayers->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
}
std::size_t total_layers = enabled.CuStack().size();
for( const auto& entry : non_cu_seq )
{
if( enabled[entry.layerId] )
total_layers++;
}
// Adds layers to the panel until we have enough to hold our total count
while( total_layers > m_layerSettings.size() )
m_layerSettings.push_back( std::make_unique<APPEARANCE_SETTING>() );
// We never delete layers from the panel, only hide them. This saves us
// having to recreate the (possibly) later with minimal overhead
for( std::size_t ii = total_layers; ii < m_layerSettings.size(); ++ii )
{
if( m_layerSettings[ii]->ctl_panel )
m_layerSettings[ii]->ctl_panel->Show( false );
}
auto layer_it = m_layerSettings.begin();
// show all coppers first, with front on top, back on bottom, then technical layers
for( LSEQ cu_stack = enabled.CuStack(); cu_stack; ++cu_stack, ++layer_it )
{
PCB_LAYER_ID layer = *cu_stack;
wxString dsc;
switch( layer )
{
case F_Cu: dsc = _( "Front copper layer" ); break;
case B_Cu: dsc = _( "Back copper layer" ); break;
default: dsc = _( "Inner copper layer" ); break;
}
std::unique_ptr<APPEARANCE_SETTING>& setting = *layer_it;
setting->label = board->GetLayerName( layer );
setting->id = layer;
setting->tooltip = dsc;
if( setting->ctl_panel == nullptr )
appendLayer( setting );
else
updateLayer( setting );
m_layerSettingsMap[layer] = setting.get();
if( m_isFpEditor && LSET::ForbiddenFootprintLayers().test( layer ) )
{
setting->ctl_text->Disable();
setting->ctl_color->SetToolTip( wxEmptyString );
}
}
for( const auto& entry : non_cu_seq ) for( const auto& entry : non_cu_seq )
{ {
PCB_LAYER_ID layer = entry.layerId; PCB_LAYER_ID layer = entry.layerId;
@ -1577,20 +1625,26 @@ void APPEARANCE_CONTROLS::rebuildLayers()
if( !enabled[layer] ) if( !enabled[layer] )
continue; continue;
m_layerSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>( std::unique_ptr<APPEARANCE_SETTING>& setting = *layer_it;
board->GetLayerName( layer ), layer, wxGetTranslation( entry.tooltip ) ) );
std::unique_ptr<APPEARANCE_SETTING>& setting = m_layerSettings.back(); setting->label = board->GetLayerName( layer );
setting->id = layer;
setting->tooltip = entry.tooltip;
if( setting->ctl_panel == nullptr )
appendLayer( setting );
else
updateLayer( setting );
m_layerSettingsMap[layer] = setting.get(); m_layerSettingsMap[layer] = setting.get();
appendLayer( setting );
if( m_isFpEditor && LSET::ForbiddenFootprintLayers().test( layer ) ) if( m_isFpEditor && LSET::ForbiddenFootprintLayers().test( layer ) )
{ {
setting->ctl_text->Disable(); setting->ctl_text->Disable();
setting->ctl_color->SetToolTip( wxEmptyString ); setting->ctl_color->SetToolTip( wxEmptyString );
} }
++layer_it;
} }
m_layersOuterSizer->AddSpacer( 10 ); m_layersOuterSizer->AddSpacer( 10 );