Implement undo/redo around Pad Edit Mode changes.

This commit is contained in:
Jeff Young 2023-09-01 18:46:51 +01:00
parent aacb85bdab
commit 69a1b30b8a
9 changed files with 135 additions and 58 deletions

View File

@ -986,3 +986,8 @@ const TOOL_EVENT EVENTS::GridChangedByKeyEvent( TC_MESSAGE, TA_ACTION,
const TOOL_EVENT EVENTS::ContrastModeChangedByKeyEvent( TC_MESSAGE, TA_ACTION,
"common.Interactive.contrastModeChangedByKeyEvent" );
// System-wide undo/redo Events
const TOOL_EVENT EVENTS::UndoRedoPreEvent( TC_MESSAGE, TA_UNDO_REDO_POST, AS_GLOBAL );
const TOOL_EVENT EVENTS::UndoRedoPostEvent( TC_MESSAGE, TA_UNDO_REDO_POST, AS_GLOBAL );

View File

@ -230,6 +230,10 @@ public:
///< Used for hotkey feedback
const static TOOL_EVENT GridChangedByKeyEvent;
const static TOOL_EVENT ContrastModeChangedByKeyEvent;
const static TOOL_EVENT UndoRedoPreEvent;
const static TOOL_EVENT UndoRedoPostEvent;
};
#endif // __ACTIONS_H

View File

@ -411,6 +411,13 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
if( view )
view->Update( boardItem );
if( boardItem->Type() == PCB_FOOTPRINT_T )
{
PAD* pad1 = static_cast<FOOTPRINT*>( boardItem )->Pads()[0];
bool padEntered = pad1->IsEntered();
wxString padNumber = pad1->GetNumber();
}
itemsChanged.push_back( boardItem );
// if no undo entry is needed, the copy would create a memory leak

View File

@ -1158,7 +1158,7 @@ void PCB_PAINTER::draw( const PAD* aPad, int aLayer )
VECTOR2D position = padBBox.Centre();
VECTOR2D padsize = VECTOR2D( padBBox.GetSize() );
if( aPad->GetFlags() & ENTERED )
if( aPad->IsEntered() )
{
FOOTPRINT* fp = aPad->GetParentFootprint();

View File

@ -615,10 +615,9 @@ int PAD_TOOL::EditPad( const TOOL_EVENT& aEvent )
Activate();
PCB_DISPLAY_OPTIONS opts = frame()->GetDisplayOptions();
PCB_RENDER_SETTINGS* settings = static_cast<PCB_RENDER_SETTINGS*>( view()->GetPainter()->GetSettings() );
WX_INFOBAR* infoBar = frame()->GetInfoBar();
KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( view()->GetPainter() );
PCB_RENDER_SETTINGS* settings = painter->GetSettings();
PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
wxString msg;
if( m_editPad != niluuid )
{
@ -638,65 +637,117 @@ int PAD_TOOL::EditPad( const TOOL_EVENT& aEvent )
PAD* pad = static_cast<PAD*>( selection[0] );
PCB_LAYER_ID layer = explodePad( pad );
m_editPad = pad->m_Uuid;
m_wasHighContrast = ( opts.m_ContrastModeDisplay != HIGH_CONTRAST_MODE::NORMAL );
frame()->SetActiveLayer( layer );
settings->m_PadEditModePad = pad;
canvas()->GetView()->UpdateAllItemsConditionally( KIGFX::REPAINT,
[&]( KIGFX::VIEW_ITEM* aItem ) -> bool
{
return dynamic_cast<PAD*>( aItem ) != nullptr;
} );
if( !m_wasHighContrast )
m_toolMgr->RunAction( ACTIONS::highContrastMode );
if( PCB_ACTIONS::explodePad.GetHotKey() == PCB_ACTIONS::recombinePad.GetHotKey() )
{
msg.Printf( _( "Pad Edit Mode. Press %s again to exit." ),
KeyNameFromKeyCode( PCB_ACTIONS::recombinePad.GetHotKey() ) );
}
else
{
msg.Printf( _( "Pad Edit Mode. Press %s to exit." ),
KeyNameFromKeyCode( PCB_ACTIONS::recombinePad.GetHotKey() ) );
}
infoBar->RemoveAllButtons();
infoBar->ShowMessage( msg, wxICON_INFORMATION );
m_editPad = pad->m_Uuid;
enterPadEditMode();
}
if( m_editPad == niluuid )
{
bool highContrast = ( opts.m_ContrastModeDisplay != HIGH_CONTRAST_MODE::NORMAL );
if( m_wasHighContrast != highContrast )
m_toolMgr->RunAction( ACTIONS::highContrastMode );
settings->m_PadEditModePad = nullptr;
// 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.
canvas()->GetView()->UpdateAllItemsConditionally( KIGFX::ALL,
[&]( KIGFX::VIEW_ITEM* aItem ) -> bool
{
return dynamic_cast<PAD*>( aItem ) != nullptr;
} );
// Refresh now (otherwise there's an uncomfortably long pause while the infoBar
// closes before refresh).
canvas()->ForceRefresh();
infoBar->Dismiss();
exitPadEditMode();
}
return 0;
}
int PAD_TOOL::OnUndoRedo( const TOOL_EVENT& aEvent )
{
PAD* flaggedPad = nullptr;
KIID flaggedPadId = niluuid;
for( FOOTPRINT* fp : board()->Footprints() )
{
for( PAD* pad : fp->Pads() )
{
if( pad->IsEntered() )
{
flaggedPad = pad;
flaggedPadId = pad->m_Uuid;
break;
}
}
}
if( flaggedPadId != m_editPad )
{
KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( view()->GetPainter() );
PCB_RENDER_SETTINGS* settings = painter->GetSettings();
m_editPad = flaggedPadId;
settings->m_PadEditModePad = flaggedPad;
if( flaggedPad )
enterPadEditMode();
else
exitPadEditMode();
}
return 0;
}
void PAD_TOOL::enterPadEditMode()
{
PCB_DISPLAY_OPTIONS opts = frame()->GetDisplayOptions();
bool highContrast = opts.m_ContrastModeDisplay != HIGH_CONTRAST_MODE::NORMAL;
WX_INFOBAR* infoBar = frame()->GetInfoBar();
wxString msg;
canvas()->GetView()->UpdateAllItemsConditionally( KIGFX::REPAINT,
[&]( KIGFX::VIEW_ITEM* aItem ) -> bool
{
return dynamic_cast<PAD*>( aItem ) != nullptr;
} );
if( !highContrast )
m_toolMgr->RunAction( ACTIONS::highContrastMode );
if( PCB_ACTIONS::explodePad.GetHotKey() == PCB_ACTIONS::recombinePad.GetHotKey() )
{
msg.Printf( _( "Pad Edit Mode. Press %s again to exit." ),
KeyNameFromKeyCode( PCB_ACTIONS::recombinePad.GetHotKey() ) );
}
else
{
msg.Printf( _( "Pad Edit Mode. Press %s to exit." ),
KeyNameFromKeyCode( PCB_ACTIONS::recombinePad.GetHotKey() ) );
}
infoBar->RemoveAllButtons();
infoBar->ShowMessage( msg, wxICON_INFORMATION );
}
void PAD_TOOL::exitPadEditMode()
{
PCB_DISPLAY_OPTIONS opts = frame()->GetDisplayOptions();
bool highContrast = opts.m_ContrastModeDisplay != HIGH_CONTRAST_MODE::NORMAL;
if( m_wasHighContrast != highContrast )
m_toolMgr->RunAction( ACTIONS::highContrastMode );
// 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.
canvas()->GetView()->UpdateAllItemsConditionally( KIGFX::ALL,
[&]( KIGFX::VIEW_ITEM* aItem ) -> bool
{
return dynamic_cast<PAD*>( aItem ) != nullptr;
} );
// Refresh now (otherwise there's an uncomfortably long pause while the infoBar
// closes before refresh).
canvas()->ForceRefresh();
frame()->GetInfoBar()->Dismiss();
}
PCB_LAYER_ID PAD_TOOL::explodePad( PAD* aPad )
{
PCB_LAYER_ID layer;
@ -964,4 +1015,6 @@ void PAD_TOOL::setTransitions()
Go( &PAD_TOOL::EditPad, PCB_ACTIONS::explodePad.MakeEvent() );
Go( &PAD_TOOL::EditPad, PCB_ACTIONS::recombinePad.MakeEvent() );
Go( &PAD_TOOL::OnUndoRedo, EVENTS::UndoRedoPostEvent );
}

View File

@ -60,6 +60,8 @@ public:
*/
int EditPad( const TOOL_EVENT& aEvent );
int OnUndoRedo( const TOOL_EVENT& aEvent );
bool InPadEditMode() { return m_editPad != niluuid; }
wxString GetLastPadNumber() const { return m_lastPadNumber; }
@ -89,6 +91,9 @@ private:
PCB_LAYER_ID explodePad( PAD* aPad );
void enterPadEditMode();
void exitPadEditMode();
private:
wxString m_lastPadNumber;

View File

@ -1307,7 +1307,7 @@ void PCB_POINT_EDITOR::updateItem() const
{
for( PAD* pad : shape->GetParentFootprint()->Pads() )
{
if( pad->GetFlags() & ENTERED )
if( pad->IsEntered() )
view()->Update( pad );
}
}

View File

@ -2442,14 +2442,17 @@ void PCB_SELECTION_TOOL::RebuildSelection()
highlight( item, SELECTED, &m_selection );
}
if( item == m_enteredGroup )
if( item->Type() == PCB_GROUP_T )
{
item->SetFlags( ENTERED );
enteredGroupFound = true;
}
else
{
item->ClearFlags( ENTERED );
if( item == m_enteredGroup )
{
item->SetFlags( ENTERED );
enteredGroupFound = true;
}
else
{
item->ClearFlags( ENTERED );
}
}
return INSPECT_RESULT::CONTINUE;

View File

@ -241,7 +241,7 @@ void PCB_BASE_EDIT_FRAME::RestoreCopyFromRedoList( wxCommandEvent& aEvent )
return;
// Inform tools that redo command was issued
m_toolManager->ProcessEvent( { TC_MESSAGE, TA_UNDO_REDO_PRE, AS_GLOBAL } );
m_toolManager->ProcessEvent( EVENTS::UndoRedoPreEvent );
// Get the old list
PICKED_ITEMS_LIST* list = PopCommandFromRedoList();
@ -255,7 +255,7 @@ void PCB_BASE_EDIT_FRAME::RestoreCopyFromRedoList( wxCommandEvent& aEvent )
OnModify();
m_toolManager->ProcessEvent( { TC_MESSAGE, TA_UNDO_REDO_POST, AS_GLOBAL } );
m_toolManager->ProcessEvent( EVENTS::UndoRedoPostEvent );
m_toolManager->PostEvent( EVENTS::SelectedItemsModified );
GetCanvas()->Refresh();