Improve delete-unused-layers to better handle multi-layer items.

Fixes https://gitlab.com/kicad/code/kicad/issues/5116
This commit is contained in:
Jeff Young 2020-08-09 12:22:09 +01:00
parent f2d91862c7
commit 4317881012
14 changed files with 93 additions and 86 deletions

View File

@ -181,11 +181,15 @@ public:
/**
* Function GetLayerSet
* returns a "layer mask", which is a bitmap of all layers on which the
* TRACK segment or VIA physically resides.
* @return int - a layer mask, see layers_id_colors_visibility.h.
* returns a std::bitset of all layers on which the item physically resides.
*/
virtual LSET GetLayerSet() const { return LSET( m_Layer ); }
virtual void SetLayerSet( LSET aLayers )
{
wxFAIL_MSG( "Attempted to SetLayerSet() on a single-layer object." );
// Derived classes which support multiple layers must implement this
}
/**
* Function SetLayer
@ -196,8 +200,6 @@ public:
*/
virtual void SetLayer( PCB_LAYER_ID aLayer )
{
// trap any invalid layers, then go find the caller and fix it.
// wxASSERT( unsigned( aLayer ) < unsigned( NB_PCB_LAYERS ) );
m_Layer = aLayer;
}

View File

@ -87,19 +87,6 @@ MARKER_PCB* MARKER_PCB::Deserialize( const wxString& data )
}
/* tests to see if this object is on the given layer.
* DRC markers are not really on a copper layer, but
* MARKER_PCB::IsOnCopperLayer return true if aLayer is a cooper layer,
* because this test is often used to locad a marker
* param aLayer The layer to test for.
* return bool - true if on given layer, else false.
*/
bool MARKER_PCB::IsOnLayer( PCB_LAYER_ID aLayer ) const
{
return IsCopperLayer( aLayer );
}
void MARKER_PCB::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
{
aList.emplace_back( _( "Type" ), _( "Marker" ), DARKCYAN );

View File

@ -78,8 +78,6 @@ public:
return HitTestMarker( aPosition, aAccuracy );
}
bool IsOnLayer( PCB_LAYER_ID aLayer ) const override;
GAL_LAYER_ID GetColorLayer() const;
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;

View File

@ -331,7 +331,7 @@ public:
bool IsDirty() const { return m_shapesDirty; }
void SetLayerSet( LSET aLayerMask ) { m_layerMask = aLayerMask; }
void SetLayerSet( LSET aLayers ) override { m_layerMask = aLayers; }
LSET GetLayerSet() const override { return m_layerMask; }
void SetAttribute( PAD_ATTR_T aAttribute );

View File

@ -397,6 +397,23 @@ LSET VIA::GetLayerSet() const
}
void VIA::SetLayerSet( LSET aLayerSet )
{
bool first = true;
for( PCB_LAYER_ID layer : aLayerSet.Seq() )
{
if( first )
{
m_Layer = layer;
first = false;
}
m_BottomLayer = layer;
}
}
void VIA::SetLayerPair( PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer )
{

View File

@ -381,6 +381,7 @@ public:
bool IsOnLayer( PCB_LAYER_ID aLayer ) const override;
virtual LSET GetLayerSet() const override;
virtual void SetLayerSet( LSET aLayers ) override;
/**
* Function SetLayerPair

View File

@ -107,8 +107,7 @@ public:
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
void SetLayerSet( LSET aLayerSet );
void SetLayerSet( LSET aLayerSet ) override;
virtual LSET GetLayerSet() const override;
wxString GetZoneName() const { return m_zoneName; }

View File

@ -586,12 +586,7 @@ SEARCH_RESULT PCB_LAYER_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData )
{
BOARD_ITEM* item = (BOARD_ITEM*) testItem;
if( item->Type() == PCB_PAD_T ) // multilayer
{
if( static_cast<D_PAD*>( item )->IsOnLayer( m_layer_id ) )
Append( testItem );
}
else if( item->GetLayer() == m_layer_id )
if( item->IsOnLayer( m_layer_id ) )
Append( testItem );
return SEARCH_RESULT::CONTINUE;

View File

@ -417,17 +417,15 @@ bool DIALOG_COPPER_ZONE::AcceptOptions( bool aUseExportableSetupOnly )
return true;
// Get the layer selection for this zone
int layer = -1;
int layers = 0;
for( int ii = 0; ii < m_layers->GetItemCount(); ++ii )
{
if( m_layers->GetToggleValue( (unsigned) ii, 0 ) )
{
layer = ii;
break;
}
layers++;
}
if( layer < 0 )
if( layers == 0 )
{
DisplayError( this, _( "No layer selected." ) );
return false;
@ -468,10 +466,12 @@ void DIALOG_COPPER_ZONE::OnLayerSelection( wxDataViewEvent& event )
int row = m_layers->ItemToRow( event.GetItem() );
bool checked = m_layers->GetToggleValue( row, 0 );
wxVariant layerID;
m_layers->GetValue( layerID, row, 2 );
m_settings.m_Layers.set( ToLAYER_ID( layerID.GetInteger() ),
m_layers->GetToggleValue( row, 0 ) );
m_settings.m_Layers.set( ToLAYER_ID( layerID.GetInteger() ), checked );
}

View File

@ -517,19 +517,26 @@ bool PANEL_SETUP_LAYERS::TransferDataFromWindow()
{
PCB_LAYER_COLLECTOR collector;
for( auto layer_id : removedLayers )
for( PCB_LAYER_ID layer_id : removedLayers )
{
collector.SetLayerId( layer_id );
collector.Collect( m_pcb, GENERAL_COLLECTOR::BoardLevelItems );
// Bye-bye items on removed layer.
if( collector.GetCount() != 0 )
for( int i = 0; i < collector.GetCount(); i++ )
{
BOARD_ITEM* item = collector[i];
LSET layers = item->GetLayerSet();
layers.reset( layer_id );
hasRemovedBoardItems = true;
for( int i = 0; i < collector.GetCount(); i++ )
if( layers.any() )
{
item->SetLayerSet( layers );
}
else
{
BOARD_ITEM* item = collector[i];
m_pcb->Remove( item );
delete item;
}
@ -756,13 +763,15 @@ bool PANEL_SETUP_LAYERS::compareCopperLayerCount( BOARD* aWorkingBoard, BOARD* a
if( newNumLayers < currNumLayers )
{
wxMessageDialog dlg( this,
wxString::Format(
wxT( "Imported settings have fewer copper layers than current board (%i instead of %i)."
"\n\nContinue and delete extra inner copper layers from current board?" ),
newNumLayers, currNumLayers ),
_( "Inner Layers To Be Deleted" ),
wxICON_WARNING | wxSTAY_ON_TOP | wxYES | wxNO | wxNO_DEFAULT );
wxString msg = wxString::Format( _( "Imported settings have fewer copper layers than "
"the current board (%i instead of %i).\n\n"
"Continue and delete the extra inner copper layers "
"from the current board?" ),
newNumLayers,
currNumLayers );
wxMessageDialog dlg( this, msg, _( "Inner Layers To Be Deleted" ),
wxICON_WARNING | wxSTAY_ON_TOP | wxYES | wxNO | wxNO_DEFAULT );
if( wxID_NO == dlg.ShowModal() )
okToDeleteCopperLayers = false;

View File

@ -382,31 +382,30 @@ void FOOTPRINT_EDIT_FRAME::OnEditItemRequest( BOARD_ITEM* aItem )
case PCB_MODULE_ZONE_AREA_T:
{
ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( aItem );
bool success = false;
if( zone )
{
ZONE_SETTINGS zoneSettings;
zoneSettings << *zone;
if( zone->GetIsKeepout() )
{
success = InvokeKeepoutAreaEditor( this, &zoneSettings );
}
else if( zone->IsOnCopperLayer() )
{
success = InvokeCopperZonesEditor( this, &zoneSettings );
}
else
{
success = InvokeNonCopperZonesEditor( this, &zoneSettings );
}
bool success = false;
ZONE_SETTINGS zoneSettings;
if( success )
{
BOARD_COMMIT commit( this );
commit.Modify( zone );
commit.Push( _( "Edit Zone" ) );
zoneSettings.ExportSetting( *zone );
}
zoneSettings << *static_cast<ZONE_CONTAINER*>( aItem );
if( zone->GetIsKeepout() )
{
success = InvokeKeepoutAreaEditor( this, &zoneSettings );
}
else if( zone->IsOnCopperLayer() )
{
success = InvokeCopperZonesEditor( this, &zoneSettings );
}
else
{
success = InvokeNonCopperZonesEditor( this, &zoneSettings );
}
if( success )
{
BOARD_COMMIT commit( this );
commit.Modify( zone );
commit.Push( _( "Edit Zone" ) );
zoneSettings.ExportSetting( *static_cast<ZONE_CONTAINER*>( aItem ) );
}
}
break;

View File

@ -51,16 +51,16 @@ ZONE_CREATE_HELPER::~ZONE_CREATE_HELPER()
std::unique_ptr<ZONE_CONTAINER> ZONE_CREATE_HELPER::createNewZone( bool aKeepout )
{
auto& frame = *m_tool.getEditFrame<PCB_BASE_EDIT_FRAME>();
auto& board = *m_tool.getModel<BOARD>();
PCB_BASE_EDIT_FRAME* frame = m_tool.getEditFrame<PCB_BASE_EDIT_FRAME>();
BOARD* board = frame->GetBoard();
BOARD_ITEM_CONTAINER* parent = m_tool.m_frame->GetModel();
KIGFX::VIEW_CONTROLS* controls = m_tool.GetManager()->GetViewControls();
std::set<int> highlightedNets = board->GetHighLightNetCodes();
// Get the current default settings for zones
ZONE_SETTINGS zoneInfo = frame.GetZoneSettings();
ZONE_SETTINGS zoneInfo = frame->GetZoneSettings();
zoneInfo.m_Layers.reset().set( m_params.m_layer ); // TODO(JE) multilayer defaults?
zoneInfo.m_NetcodeSelection =
board.GetHighLightNetCodes().empty() ? -1 : *board.GetHighLightNetCodes().begin();
zoneInfo.m_NetcodeSelection = highlightedNets.empty() ? -1 : *highlightedNets.begin();
zoneInfo.SetIsKeepout( m_params.m_keepout );
zoneInfo.m_Zone_45_Only = ( m_params.m_leaderMode == POLYGON_GEOM_MANAGER::LEADER_MODE::DEG45 );
@ -84,14 +84,14 @@ std::unique_ptr<ZONE_CONTAINER> ZONE_CREATE_HELPER::createNewZone( bool aKeepout
int dialogResult;
if( m_params.m_keepout )
dialogResult = InvokeKeepoutAreaEditor( &frame, &zoneInfo );
dialogResult = InvokeKeepoutAreaEditor( frame, &zoneInfo );
else
{
// TODO(JE) combine these dialogs?
if( ( zoneInfo.m_Layers & LSET::AllCuMask() ).any() )
dialogResult = InvokeCopperZonesEditor( &frame, &zoneInfo );
dialogResult = InvokeCopperZonesEditor( frame, &zoneInfo );
else
dialogResult = InvokeNonCopperZonesEditor( &frame, &zoneInfo );
dialogResult = InvokeNonCopperZonesEditor( frame, &zoneInfo );
}
if( dialogResult == wxID_CANCEL )
@ -104,9 +104,9 @@ std::unique_ptr<ZONE_CONTAINER> ZONE_CREATE_HELPER::createNewZone( bool aKeepout
// and a MODULE_ZONE_CONTAINER if created in the footprint editor
wxASSERT( !m_tool.m_editModules || ( parent->Type() == PCB_MODULE_T ) );
auto newZone = m_tool.m_editModules ?
std::make_unique<MODULE_ZONE_CONTAINER>( parent ) :
std::make_unique<ZONE_CONTAINER>( parent );
std::unique_ptr<ZONE_CONTAINER> newZone = m_tool.m_editModules ?
std::make_unique<MODULE_ZONE_CONTAINER>( parent ) :
std::make_unique<ZONE_CONTAINER>( parent );
// Apply the selected settings
zoneInfo.ExportSetting( *newZone );

View File

@ -185,6 +185,7 @@ const static wxSize LAYER_BITMAP_SIZE( 28, 28 ); // wxCocoa impl unhappy if thi
const static wxSize LAYER_BITMAP_SIZE( 24, 16 );
#endif
// A helper for setting up a dialog list for specifying zone layers. Used by all three
// zone settings dialogs.
void ZONE_SETTINGS::SetupLayersList( wxDataViewListCtrl* aList, PCB_BASE_FRAME* aFrame,
@ -195,8 +196,9 @@ void ZONE_SETTINGS::SetupLayersList( wxDataViewListCtrl* aList, PCB_BASE_FRAME*
LSET layers = aShowCopper ? LSET::AllCuMask( board->GetCopperLayerCount() )
: LSET::AllNonCuMask();
// In the Footprint Editor In1_Cu is used as a proxy for "all inner layers"
if( aFpEditorMode )
layers.set( In1_Cu ); // a proxy for "all inner layers"
layers.set( In1_Cu );
wxDataViewColumn* checkColumn = aList->AppendToggleColumn( wxEmptyString );
wxDataViewColumn* layerColumn = aList->AppendIconTextColumn( wxEmptyString );

View File

@ -77,8 +77,6 @@ public:
return HitTestMarker( aPosition, aAccuracy );
}
bool IsOnLayer( PCB_LAYER_ID aLayer ) const override;
GAL_LAYER_ID GetColorLayer() const;
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;