diff --git a/include/widgets/bitmap_toggle.h b/include/widgets/bitmap_toggle.h index 9474c59707..faef9674a8 100644 --- a/include/widgets/bitmap_toggle.h +++ b/include/widgets/bitmap_toggle.h @@ -25,7 +25,7 @@ #ifndef _BITMAP_TOGGLE_H #define _BITMAP_TOGGLE_H -#include +#include #include #include @@ -54,6 +54,16 @@ public: ///< Read the checkbox state 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: bool m_checked; diff --git a/include/widgets/color_swatch.h b/include/widgets/color_swatch.h index 26d2838f22..d9578315d0 100644 --- a/include/widgets/color_swatch.h +++ b/include/widgets/color_swatch.h @@ -99,6 +99,16 @@ public: */ 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. * diff --git a/include/widgets/indicator_icon.h b/include/widgets/indicator_icon.h index ee347ec3f8..a161715c92 100644 --- a/include/widgets/indicator_icon.h +++ b/include/widgets/indicator_icon.h @@ -24,7 +24,7 @@ #ifndef ROW_INDICATOR__H_ #define ROW_INDICATOR__H_ -#include +#include #include class wxStaticBitmap; @@ -97,6 +97,16 @@ public: */ 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: ///< An class that delivers icons for the indicator (currently just diff --git a/pcbnew/widgets/appearance_controls.cpp b/pcbnew/widgets/appearance_controls.cpp index 5972c59040..6b352bc8b9 100644 --- a/pcbnew/widgets/appearance_controls.cpp +++ b/pcbnew/widgets/appearance_controls.cpp @@ -1408,10 +1408,6 @@ void APPEARANCE_CONTROLS::rebuildLayers() m_windowLayersSizerItem->SetFlag( m_windowLayersSizerItem->GetFlag() & ~wxTOP ); #endif - m_layerSettings.clear(); - m_layerSettingsMap.clear(); - m_layersOuterSizer->Clear( true ); - auto appendLayer = [&]( std::unique_ptr& aSetting ) { @@ -1500,39 +1496,21 @@ void APPEARANCE_CONTROLS::rebuildLayers() 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 - // m_windowLayers (below the layer items) - m_windowLayers->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this ); - - wxString dsc; - - // show all coppers first, with front on top, back on bottom, then technical layers - for( LSEQ cu_stack = enabled.CuStack(); cu_stack; ++cu_stack ) - { - PCB_LAYER_ID layer = *cu_stack; - - switch( layer ) - { - case F_Cu: dsc = _( "Front copper layer" ); break; - case B_Cu: dsc = _( "Back copper layer" ); break; - default: dsc = _( "Inner copper layer" ); break; - } - - m_layerSettings.emplace_back( - std::make_unique( board->GetLayerName( layer ), layer, dsc ) ); - - std::unique_ptr& 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 ); - } - } + auto updateLayer = + [&]( std::unique_ptr& aSetting ) + { + int layer = aSetting->id; + aSetting->visible = visible[layer]; + aSetting->ctl_panel->Show(); + aSetting->ctl_panel->SetId( layer ); + aSetting->ctl_indicator->SetWindowID( layer ); + aSetting->ctl_color->SetWindowID( layer ); + aSetting->ctl_color->SetSwatchColor( theme->GetColor( layer ), false ); + aSetting->ctl_visibility->SetWindowID( layer ); + aSetting->ctl_text->SetLabelText( aSetting->label ); + aSetting->ctl_text->SetId( layer ); + aSetting->ctl_text->SetToolTip( aSetting->tooltip ); + }; // technical layers are shown in this order: // Because they are static, wxGetTranslation must be explicitly @@ -1570,6 +1548,76 @@ void APPEARANCE_CONTROLS::rebuildLayers() { 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() ); + + // 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& 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 ) { PCB_LAYER_ID layer = entry.layerId; @@ -1577,20 +1625,26 @@ void APPEARANCE_CONTROLS::rebuildLayers() if( !enabled[layer] ) continue; - m_layerSettings.emplace_back( std::make_unique( - board->GetLayerName( layer ), layer, wxGetTranslation( entry.tooltip ) ) ); + std::unique_ptr& setting = *layer_it; - std::unique_ptr& 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(); - appendLayer( setting ); - if( m_isFpEditor && LSET::ForbiddenFootprintLayers().test( layer ) ) { setting->ctl_text->Disable(); setting->ctl_color->SetToolTip( wxEmptyString ); } + + ++layer_it; } m_layersOuterSizer->AddSpacer( 10 );