7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-21 21:43:43 +00:00

Add layer pair cycle action

This is the second piece of the layer pair preset quick
switcher that allows a action (i.e. hotkey) to cycle between
the enabled preset layer pairs.

Fixes: https://gitlab.com/kicad/code/kicad/-/issues/15227
This commit is contained in:
John Beard 2024-07-31 19:31:07 +08:00
parent edf13bdfd0
commit 24c3102638
8 changed files with 194 additions and 12 deletions

View File

@ -23,10 +23,24 @@
#include "layer_pairs.h"
#include <wx/translation.h>
wxDEFINE_EVENT( PCB_LAYER_PAIR_PRESETS_CHANGED, wxCommandEvent );
wxDEFINE_EVENT( PCB_CURRENT_LAYER_PAIR_CHANGED, wxCommandEvent );
static bool IsAnEnabledPreset( const LAYER_PAIR& aPair, const LAYER_PAIR_SETTINGS& aSettings )
{
const auto presets = aSettings.GetLayerPairs();
const auto matcher = [&aPair]( const LAYER_PAIR_INFO& aPreset )
{
return aPreset.GetLayerPair().HasSameLayers( aPair ) && aPreset.IsEnabled();
};
return std::any_of( presets.begin(), presets.end(), matcher );
}
LAYER_PAIR_SETTINGS::LAYER_PAIR_SETTINGS( const LAYER_PAIR_SETTINGS& aOther )
{
m_pairs = aOther.m_pairs;
@ -49,6 +63,13 @@ bool LAYER_PAIR_SETTINGS::addLayerPairInternal( LAYER_PAIR_INFO aPairInfo )
return false;
}
// If we're adding a pair that matches the last manual pair
// we no longer need the manual one
if( m_lastManualPair && m_lastManualPair->HasSameLayers( newPair ) )
{
m_lastManualPair.reset();
}
m_pairs.push_back( std::move( aPairInfo ) );
return true;
}
@ -103,6 +124,42 @@ std::span<LAYER_PAIR_INFO> LAYER_PAIR_SETTINGS::GetLayerPairs()
return m_pairs;
}
std::vector<LAYER_PAIR_INFO> LAYER_PAIR_SETTINGS::GetEnabledLayerPairs( int& aCurrent ) const
{
std::vector<LAYER_PAIR_INFO> enabledPairs;
aCurrent = -1;
if( m_lastManualPair )
{
enabledPairs.emplace_back( LAYER_PAIR_INFO{
*m_lastManualPair,
true,
_( "Manual" ),
} );
if( m_currentPair.HasSameLayers( *m_lastManualPair ) )
{
aCurrent = 0;
}
}
for( const LAYER_PAIR_INFO& pair : m_pairs )
{
if( pair.IsEnabled() )
{
enabledPairs.push_back( pair );
if( m_currentPair.HasSameLayers( pair.GetLayerPair() ) )
{
aCurrent = enabledPairs.size() - 1;
}
}
}
return enabledPairs;
}
void LAYER_PAIR_SETTINGS::SetLayerPairs( std::span<const LAYER_PAIR_INFO> aPairs )
{
// Replace all pairs with the given list
@ -122,6 +179,12 @@ void LAYER_PAIR_SETTINGS::SetLayerPairs( std::span<const LAYER_PAIR_INFO> aPairs
void LAYER_PAIR_SETTINGS::SetCurrentLayerPair( const LAYER_PAIR& aPair )
{
m_currentPair = aPair;
if( !IsAnEnabledPreset( aPair, *this ) )
{
m_lastManualPair = aPair;
}
wxCommandEvent* evt = new wxCommandEvent( PCB_CURRENT_LAYER_PAIR_CHANGED, wxID_ANY );
QueueEvent( evt );
}

View File

@ -69,6 +69,14 @@ public:
std::span<const LAYER_PAIR_INFO> GetLayerPairs() const;
std::span<LAYER_PAIR_INFO> GetLayerPairs();
/**
* Get a vector of all enabled layer pairs, in order.
*
* This includes a "manual" pair, if one is set
* and isn't in the list of presets.
*/
std::vector<LAYER_PAIR_INFO> GetEnabledLayerPairs( int& aCurrentIndex ) const;
/**
* Replace the stored layer pairs with the given list.
*
@ -90,6 +98,10 @@ private:
// Ordered store of all preset layer pairs
std::vector<LAYER_PAIR_INFO> m_pairs;
// Keep track of the last manual pair (set, but not a preset)
// for quick switching back
std::optional<LAYER_PAIR> m_lastManualPair;
LAYER_PAIR m_currentPair;
};

View File

@ -27,6 +27,7 @@
#include <lseq.h>
#include <layer_presentation.h>
class LAYER_PAIR;
class PCB_BASE_FRAME;
/**
@ -49,6 +50,8 @@ public:
*/
void SetBoardFrame( PCB_BASE_FRAME* aFrame ) { m_boardFrame = aFrame; }
wxString getLayerPairName( const LAYER_PAIR& aPair ) const;
private:
PCB_BASE_FRAME* m_boardFrame;
};

View File

@ -87,6 +87,14 @@ LSEQ PCB_LAYER_PRESENTATION::getOrderedEnabledLayers() const
return m_boardFrame->GetBoard()->GetEnabledLayers().UIOrder();
}
wxString PCB_LAYER_PRESENTATION::getLayerPairName( const LAYER_PAIR& aPair ) const
{
const wxString layerAName = getLayerName( aPair.GetLayerA() );
const wxString layerBName = getLayerName( aPair.GetLayerB() );
return layerAName + wxT( " / " ) + layerBName;
}
/**
* Display a PCB layers list in a dialog to select one layer from this list.
@ -425,20 +433,13 @@ private:
}
}
wxString constructLayerPairLabel( const LAYER_PAIR& aLayerPair )
{
const wxString layerAName = m_layerPresentation.getLayerName( aLayerPair.GetLayerA() );
const wxString layerBName = m_layerPresentation.getLayerName( aLayerPair.GetLayerB() );
return layerAName + wxT( " / " ) + layerBName;
}
void fillRowFromLayerPair( int aRow, const LAYER_PAIR_INFO& aLayerPairInfo )
{
wxASSERT_MSG( aRow < m_grid.GetNumberRows(), "Row index out of bounds" );
const LAYER_PAIR& layerPair = aLayerPairInfo.GetLayerPair();
const wxString layerNames = constructLayerPairLabel( layerPair );
const wxString layerNames = m_layerPresentation.getLayerPairName( layerPair );
m_grid.SetCellValue( aRow, (int) COLNUMS::LAYERNAMES, layerNames );
@ -482,9 +483,9 @@ private:
m_layerPairSettings.SetCurrentLayerPair( layerPair );
}
LAYER_PRESENTATION& m_layerPresentation;
WX_GRID& m_grid;
LAYER_PAIR_SETTINGS& m_layerPairSettings;
PCB_LAYER_PRESENTATION& m_layerPresentation;
WX_GRID& m_grid;
LAYER_PAIR_SETTINGS& m_layerPairSettings;
// Lifetime managment of the swatches
std::vector<std::unique_ptr<wxBitmap>> m_swatches;

View File

@ -1810,6 +1810,13 @@ TOOL_ACTION PCB_ACTIONS::layerAlphaDec( TOOL_ACTION_ARGS()
.Tooltip( _( "Make the current layer more transparent" ) )
.Icon( BITMAPS::contrast_mode ) );
TOOL_ACTION PCB_ACTIONS::layerPairPresetsCycle( TOOL_ACTION_ARGS()
.Name( "pcbnew.Control.layerPairPresetCycle" )
.Scope( AS_GLOBAL )
.DefaultHotkey( MD_SHIFT + 'V' )
.FriendlyName( _( "Cycle Layer Pair Presets" ) )
.Tooltip( _( "Cycle between preset layer pairs" ) ) );
TOOL_ACTION PCB_ACTIONS::layerChanged( TOOL_ACTION_ARGS()
.Name( "pcbnew.Control.layerChanged" )
.Scope( AS_GLOBAL )
@ -2465,3 +2472,6 @@ TOOL_ACTION PCB_ACTIONS::ddImportFootprint( TOOL_ACTION_ARGS()
const TOOL_EVENT PCB_EVENTS::SnappingModeChangedByKeyEvent( TC_MESSAGE, TA_ACTION,
"common.Interactive.snappingModeChangedByKey" );
const TOOL_EVENT PCB_EVENTS::LayerPairPresetChangedByKeyEvent( TC_MESSAGE, TA_ACTION,
"pcbnew.Control.layerPairPresetChangedByKey" );

View File

@ -374,6 +374,7 @@ public:
static TOOL_ACTION layerAlphaInc;
static TOOL_ACTION layerAlphaDec;
static TOOL_ACTION layerToggle;
static TOOL_ACTION layerPairPresetsCycle;
// Group to link all actions that directly select layers
static TOOL_ACTION_GROUP layerDirectSwitchActions();
@ -585,6 +586,7 @@ class PCB_EVENTS
public:
/// Hotkey feedback
const static TOOL_EVENT SnappingModeChangedByKeyEvent;
const static TOOL_EVENT LayerPairPresetChangedByKeyEvent;
};
#endif

View File

@ -42,7 +42,9 @@
#include <pcb_dimension.h>
#include <gal/graphics_abstraction_layer.h>
#include <footprint.h>
#include <layer_pairs.h>
#include <pcb_group.h>
#include <pcb_layer_presentation.h>
#include <pcb_textbox.h>
#include <pcb_track.h>
#include <pcb_generator.h>
@ -68,6 +70,7 @@
#include <widgets/wx_infobar.h>
#include <wx/hyperlink.h>
using namespace std::placeholders;
@ -560,6 +563,88 @@ int PCB_CONTROL::LayerAlphaDec( const TOOL_EVENT& aEvent )
}
int PCB_CONTROL::CycleLayerPresets( const TOOL_EVENT& aEvent )
{
PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
if( !editFrame )
return 0;
LAYER_PAIR_SETTINGS* settings = editFrame->GetLayerPairSettings();
if( !settings )
return 0;
int currentIndex;
std::vector<LAYER_PAIR_INFO> presets = settings->GetEnabledLayerPairs( currentIndex );
if( presets.size() < 2 )
return 0;
if( currentIndex < 0 )
{
wxASSERT_MSG( false, "Current layer pair not found in layer settings" );
currentIndex = 0;
}
const int nextIndex = ( currentIndex + 1 ) % presets.size();
const LAYER_PAIR& nextPair = presets[nextIndex].GetLayerPair();
settings->SetCurrentLayerPair( nextPair );
m_toolMgr->PostEvent( PCB_EVENTS::LayerPairPresetChangedByKeyEvent );
return 0;
}
int PCB_CONTROL::LayerPresetFeedback( const TOOL_EVENT& aEvent )
{
if( !Pgm().GetCommonSettings()->m_Input.hotkey_feedback )
return 0;
PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
if( !editFrame )
return 0;
LAYER_PAIR_SETTINGS* settings = editFrame->GetLayerPairSettings();
if( !settings )
return 0;
PCB_LAYER_PRESENTATION layerPresentation( editFrame );
int currentIndex;
std::vector<LAYER_PAIR_INFO> presets = settings->GetEnabledLayerPairs( currentIndex );
wxArrayString labels;
for( const LAYER_PAIR_INFO& layerPairInfo : presets )
{
wxString label = layerPresentation.getLayerPairName( layerPairInfo.GetLayerPair() );
if( layerPairInfo.GetName() )
{
label += wxT( " (" ) + *layerPairInfo.GetName() + wxT( ")" );
}
labels.Add( label );
}
if( !editFrame->GetHotkeyPopup() )
editFrame->CreateHotkeyPopup();
HOTKEY_CYCLE_POPUP* popup = editFrame->GetHotkeyPopup();
if( popup )
{
int selection = currentIndex;
popup->Popup( _( "Preset Layer Pairs" ), labels, selection );
}
return 0;
}
void PCB_CONTROL::DoSetGridOrigin( KIGFX::VIEW* aView, PCB_BASE_FRAME* aFrame,
EDA_ITEM* originViewItem, const VECTOR2D& aPoint )
{
@ -1715,7 +1800,7 @@ int PCB_CONTROL::FlipPcbView( const TOOL_EVENT& aEvent )
return 0;
}
// clang-format off
void PCB_CONTROL::setTransitions()
{
Go( &PCB_CONTROL::AddLibrary, ACTIONS::newLibrary.MakeEvent() );
@ -1779,6 +1864,9 @@ void PCB_CONTROL::setTransitions()
Go( &PCB_CONTROL::LayerAlphaInc, PCB_ACTIONS::layerAlphaInc.MakeEvent() );
Go( &PCB_CONTROL::LayerAlphaDec, PCB_ACTIONS::layerAlphaDec.MakeEvent() );
Go( &PCB_CONTROL::CycleLayerPresets, PCB_ACTIONS::layerPairPresetsCycle.MakeEvent() );
Go( &PCB_CONTROL::LayerPresetFeedback, PCB_EVENTS::LayerPairPresetChangedByKeyEvent );
// Grid control
Go( &PCB_CONTROL::GridPlaceOrigin, ACTIONS::gridSetOrigin.MakeEvent() );
Go( &PCB_CONTROL::GridResetOrigin, ACTIONS::gridResetOrigin.MakeEvent() );
@ -1813,3 +1901,4 @@ void PCB_CONTROL::setTransitions()
Go( &PCB_CONTROL::DdAddLibrary, ACTIONS::ddAddLibrary.MakeEvent() );
Go( &PCB_CONTROL::DdImportFootprint, PCB_ACTIONS::ddImportFootprint.MakeEvent() );
}
// clang-format on

View File

@ -79,6 +79,8 @@ public:
int LayerToggle( const TOOL_EVENT& aEvent );
int LayerAlphaInc( const TOOL_EVENT& aEvent );
int LayerAlphaDec( const TOOL_EVENT& aEvent );
int CycleLayerPresets( const TOOL_EVENT& aEvent );
int LayerPresetFeedback( const TOOL_EVENT& aEvent );
// Grid control
int GridPlaceOrigin( const TOOL_EVENT& aEvent );