Simplify undo/redo for pad edit mode.

Also simplifies high-contrast-mode handling to fix a bug when exiting
pad edit mode via an undo.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/15845
This commit is contained in:
Jeff Young 2023-10-13 13:51:27 +01:00
parent 62d959ed0e
commit a69869f72a
3 changed files with 44 additions and 46 deletions

View File

@ -356,7 +356,10 @@ void GRAPHICS_CLEANER::mergePads()
if( padToNetTieGroupMap[ pad->GetNumber() ] >= 0 ) if( padToNetTieGroupMap[ pad->GetNumber() ] >= 0 )
continue; continue;
std::vector<PCB_SHAPE*> shapes = padTool->RecombinePad( pad, m_dryRun, m_commit ); if( m_commit.GetStatus( m_parentFootprint ) == 0 )
m_commit.Modify( m_parentFootprint );
std::vector<PCB_SHAPE*> shapes = padTool->RecombinePad( pad, m_dryRun );
if( !shapes.empty() ) if( !shapes.empty() )
{ {

View File

@ -51,7 +51,7 @@ using KIGFX::PCB_RENDER_SETTINGS;
PAD_TOOL::PAD_TOOL() : PAD_TOOL::PAD_TOOL() :
PCB_TOOL_BASE( "pcbnew.PadTool" ), PCB_TOOL_BASE( "pcbnew.PadTool" ),
m_wasHighContrast( false ), m_previousHighContrastMode( HIGH_CONTRAST_MODE::NORMAL ),
m_editPad( niluuid ) m_editPad( niluuid )
{} {}
@ -68,10 +68,12 @@ void PAD_TOOL::Reset( RESET_REASON aReason )
if( board() && board()->GetItem( m_editPad ) == DELETED_BOARD_ITEM::GetInstance() ) if( board() && board()->GetItem( m_editPad ) == DELETED_BOARD_ITEM::GetInstance() )
{ {
PCB_DISPLAY_OPTIONS opts = frame()->GetDisplayOptions(); PCB_DISPLAY_OPTIONS opts = frame()->GetDisplayOptions();
bool highContrast = ( opts.m_ContrastModeDisplay != HIGH_CONTRAST_MODE::NORMAL );
if( m_wasHighContrast != highContrast ) if( m_previousHighContrastMode != opts.m_ContrastModeDisplay )
m_toolMgr->RunAction( ACTIONS::highContrastMode ); {
opts.m_ContrastModeDisplay = m_previousHighContrastMode;
frame()->SetDisplayOptions( opts );
}
frame()->GetInfoBar()->Dismiss(); frame()->GetInfoBar()->Dismiss();
@ -615,7 +617,6 @@ int PAD_TOOL::EditPad( const TOOL_EVENT& aEvent )
Activate(); Activate();
PCB_DISPLAY_OPTIONS opts = frame()->GetDisplayOptions();
KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( view()->GetPainter() ); KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( view()->GetPainter() );
PCB_RENDER_SETTINGS* settings = painter->GetSettings(); PCB_RENDER_SETTINGS* settings = painter->GetSettings();
PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection(); PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
@ -627,20 +628,24 @@ int PAD_TOOL::EditPad( const TOOL_EVENT& aEvent )
if( pad ) if( pad )
{ {
BOARD_COMMIT commit( frame() ); BOARD_COMMIT commit( frame() );
RecombinePad( pad, false, commit ); commit.Modify( pad->GetParentFootprint() );
commit.Push( _( "Recombine pad" ) ); RecombinePad( pad, false );
commit.Push( _( "Edit Pad" ) );
} }
m_editPad = niluuid; m_editPad = niluuid;
} }
else if( selection.Size() == 1 && selection[0]->Type() == PCB_PAD_T ) else if( selection.Size() == 1 && selection[0]->Type() == PCB_PAD_T )
{ {
PCB_LAYER_ID layer;
PAD* pad = static_cast<PAD*>( selection[0] ); PAD* pad = static_cast<PAD*>( selection[0] );
PCB_LAYER_ID layer = explodePad( pad ); BOARD_COMMIT commit( frame() );
m_editPad = pad->m_Uuid; commit.Modify( pad->GetParentFootprint() );
explodePad( pad, &layer );
commit.Push( _( "Edit Pad" ) );
m_wasHighContrast = ( opts.m_ContrastModeDisplay != HIGH_CONTRAST_MODE::NORMAL ); m_toolMgr->RunAction( PCB_ACTIONS::selectionClear );
frame()->SetActiveLayer( layer ); frame()->SetActiveLayer( layer );
settings->m_PadEditModePad = pad; settings->m_PadEditModePad = pad;
@ -696,7 +701,6 @@ int PAD_TOOL::OnUndoRedo( const TOOL_EVENT& aEvent )
void PAD_TOOL::enterPadEditMode() void PAD_TOOL::enterPadEditMode()
{ {
PCB_DISPLAY_OPTIONS opts = frame()->GetDisplayOptions(); PCB_DISPLAY_OPTIONS opts = frame()->GetDisplayOptions();
bool highContrast = opts.m_ContrastModeDisplay != HIGH_CONTRAST_MODE::NORMAL;
WX_INFOBAR* infoBar = frame()->GetInfoBar(); WX_INFOBAR* infoBar = frame()->GetInfoBar();
wxString msg; wxString msg;
@ -706,8 +710,13 @@ void PAD_TOOL::enterPadEditMode()
return dynamic_cast<PAD*>( aItem ) != nullptr; return dynamic_cast<PAD*>( aItem ) != nullptr;
} ); } );
if( !highContrast ) m_previousHighContrastMode = opts.m_ContrastModeDisplay;
m_toolMgr->RunAction( ACTIONS::highContrastMode );
if( opts.m_ContrastModeDisplay == HIGH_CONTRAST_MODE::NORMAL )
{
opts.m_ContrastModeDisplay = HIGH_CONTRAST_MODE::DIMMED;
frame()->SetDisplayOptions( opts );
}
if( PCB_ACTIONS::explodePad.GetHotKey() == PCB_ACTIONS::recombinePad.GetHotKey() ) if( PCB_ACTIONS::explodePad.GetHotKey() == PCB_ACTIONS::recombinePad.GetHotKey() )
{ {
@ -728,10 +737,12 @@ void PAD_TOOL::enterPadEditMode()
void PAD_TOOL::exitPadEditMode() void PAD_TOOL::exitPadEditMode()
{ {
PCB_DISPLAY_OPTIONS opts = frame()->GetDisplayOptions(); PCB_DISPLAY_OPTIONS opts = frame()->GetDisplayOptions();
bool highContrast = opts.m_ContrastModeDisplay != HIGH_CONTRAST_MODE::NORMAL;
if( m_wasHighContrast != highContrast ) if( m_previousHighContrastMode != opts.m_ContrastModeDisplay )
m_toolMgr->RunAction( ACTIONS::highContrastMode ); {
opts.m_ContrastModeDisplay = m_previousHighContrastMode;
frame()->SetDisplayOptions( opts );
}
// Note: KIGFX::REPAINT isn't enough for things that go from invisible to visible as // Note: KIGFX::REPAINT isn't enough for things that go from invisible to visible as
// they won't be found in the view layer's itemset for re-painting. // they won't be found in the view layer's itemset for re-painting.
@ -749,22 +760,17 @@ void PAD_TOOL::exitPadEditMode()
} }
PCB_LAYER_ID PAD_TOOL::explodePad( PAD* aPad ) void PAD_TOOL::explodePad( PAD* aPad, PCB_LAYER_ID* aLayer )
{ {
PCB_LAYER_ID layer;
BOARD_COMMIT commit( frame() );
if( aPad->IsOnLayer( F_Cu ) ) if( aPad->IsOnLayer( F_Cu ) )
layer = F_Cu; *aLayer = F_Cu;
else if( aPad->IsOnLayer( B_Cu ) ) else if( aPad->IsOnLayer( B_Cu ) )
layer = B_Cu; *aLayer = B_Cu;
else else
layer = *aPad->GetLayerSet().UIOrder(); *aLayer = *aPad->GetLayerSet().UIOrder();
if( aPad->GetShape() == PAD_SHAPE::CUSTOM ) if( aPad->GetShape() == PAD_SHAPE::CUSTOM )
{ {
commit.Modify( aPad );
for( const std::shared_ptr<PCB_SHAPE>& primitive : aPad->GetPrimitives() ) for( const std::shared_ptr<PCB_SHAPE>& primitive : aPad->GetPrimitives() )
{ {
PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( primitive->Duplicate() ); PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( primitive->Duplicate() );
@ -772,7 +778,7 @@ PCB_LAYER_ID PAD_TOOL::explodePad( PAD* aPad )
shape->SetParent( board()->GetFirstFootprint() ); shape->SetParent( board()->GetFirstFootprint() );
shape->Rotate( VECTOR2I( 0, 0 ), aPad->GetOrientation() ); shape->Rotate( VECTOR2I( 0, 0 ), aPad->GetOrientation() );
shape->Move( aPad->ShapePos() ); shape->Move( aPad->ShapePos() );
shape->SetLayer( layer ); shape->SetLayer( *aLayer );
if( shape->IsProxyItem() && shape->GetShape() == SHAPE_T::SEGMENT ) if( shape->IsProxyItem() && shape->GetShape() == SHAPE_T::SEGMENT )
{ {
@ -782,7 +788,8 @@ PCB_LAYER_ID PAD_TOOL::explodePad( PAD* aPad )
shape->SetWidth( pcbIUScale.mmToIU( ZONE_THERMAL_RELIEF_COPPER_WIDTH_MM ) ); shape->SetWidth( pcbIUScale.mmToIU( ZONE_THERMAL_RELIEF_COPPER_WIDTH_MM ) );
} }
commit.Add( shape ); board()->GetFirstFootprint()->Add( shape );
frame()->GetCanvas()->GetView()->Add( shape );
} }
aPad->SetShape( aPad->GetAnchorPadShape() ); aPad->SetShape( aPad->GetAnchorPadShape() );
@ -791,14 +798,10 @@ PCB_LAYER_ID PAD_TOOL::explodePad( PAD* aPad )
aPad->SetFlags( ENTERED ); aPad->SetFlags( ENTERED );
m_editPad = aPad->m_Uuid; m_editPad = aPad->m_Uuid;
commit.Push( _("Edit pad shapes") );
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear );
return layer;
} }
std::vector<PCB_SHAPE*> PAD_TOOL::RecombinePad( PAD* aPad, bool aIsDryRun, BOARD_COMMIT& aCommit ) std::vector<PCB_SHAPE*> PAD_TOOL::RecombinePad( PAD* aPad, bool aIsDryRun )
{ {
int maxError = board()->GetDesignSettings().m_MaxError; int maxError = board()->GetDesignSettings().m_MaxError;
FOOTPRINT* footprint = aPad->GetParentFootprint(); FOOTPRINT* footprint = aPad->GetParentFootprint();
@ -875,8 +878,6 @@ std::vector<PCB_SHAPE*> PAD_TOOL::RecombinePad( PAD* aPad, bool aIsDryRun, BOARD
// custom-shape pad. // custom-shape pad.
if( !aIsDryRun && findNext( layer ) && aPad->GetShape() != PAD_SHAPE::CUSTOM ) if( !aIsDryRun && findNext( layer ) && aPad->GetShape() != PAD_SHAPE::CUSTOM )
{ {
aCommit.Modify( aPad );
if( aPad->GetShape() == PAD_SHAPE::CIRCLE || aPad->GetShape() == PAD_SHAPE::RECTANGLE ) if( aPad->GetShape() == PAD_SHAPE::CIRCLE || aPad->GetShape() == PAD_SHAPE::RECTANGLE )
{ {
// Use the existing pad as an anchor // Use the existing pad as an anchor
@ -919,8 +920,6 @@ std::vector<PCB_SHAPE*> PAD_TOOL::RecombinePad( PAD* aPad, bool aIsDryRun, BOARD
primitive->Rotate( VECTOR2I( 0, 0 ), - aPad->GetOrientation() ); primitive->Rotate( VECTOR2I( 0, 0 ), - aPad->GetOrientation() );
aPad->AddPrimitive( primitive ); aPad->AddPrimitive( primitive );
aCommit.Remove( fpShape );
} }
// See if there are other shapes that match and mark them for delete. (KiCad won't // See if there are other shapes that match and mark them for delete. (KiCad won't
@ -929,9 +928,6 @@ std::vector<PCB_SHAPE*> PAD_TOOL::RecombinePad( PAD* aPad, bool aIsDryRun, BOARD
{ {
other->SetFlags( SKIP_STRUCT ); other->SetFlags( SKIP_STRUCT );
mergedShapes.push_back( other ); mergedShapes.push_back( other );
if( !aIsDryRun )
aCommit.Remove( other );
} }
} }

View File

@ -71,10 +71,9 @@ public:
* Recombine an exploded pad (or one produced with overlapping polygons in an older version). * Recombine an exploded pad (or one produced with overlapping polygons in an older version).
* @param aPad the pad to run the recombination algorithm on * @param aPad the pad to run the recombination algorithm on
* @param aIsDryRun if true the list will be generated but no changes will be made * @param aIsDryRun if true the list will be generated but no changes will be made
* @param aCommit the commit to add any changes to
* @return a list of PCB_SHAPEs that will be combined * @return a list of PCB_SHAPEs that will be combined
*/ */
std::vector<PCB_SHAPE*> RecombinePad( PAD* aPad, bool aIsDryRun, BOARD_COMMIT& aCommit ); std::vector<PCB_SHAPE*> RecombinePad( PAD* aPad, bool aIsDryRun );
private: private:
///< Bind handlers to corresponding TOOL_ACTIONs. ///< Bind handlers to corresponding TOOL_ACTIONs.
@ -89,7 +88,7 @@ private:
///< Push pad settings from a pad to other pads on board or footprint. ///< Push pad settings from a pad to other pads on board or footprint.
int pushPadSettings( const TOOL_EVENT& aEvent ); int pushPadSettings( const TOOL_EVENT& aEvent );
PCB_LAYER_ID explodePad( PAD* aPad ); void explodePad( PAD* aPad, PCB_LAYER_ID* aLayer );
void enterPadEditMode(); void enterPadEditMode();
void exitPadEditMode(); void exitPadEditMode();
@ -97,7 +96,7 @@ private:
private: private:
wxString m_lastPadNumber; wxString m_lastPadNumber;
bool m_wasHighContrast; HIGH_CONTRAST_MODE m_previousHighContrastMode;
KIID m_editPad; KIID m_editPad;
}; };