From 69a1b30b8a7c4909458c51f1b74291b3a1b1d912 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Fri, 1 Sep 2023 18:46:51 +0100 Subject: [PATCH] Implement undo/redo around Pad Edit Mode changes. --- common/tool/actions.cpp | 5 + include/tool/actions.h | 4 + pcbnew/board_commit.cpp | 7 ++ pcbnew/pcb_painter.cpp | 2 +- pcbnew/tools/pad_tool.cpp | 147 +++++++++++++++++++--------- pcbnew/tools/pad_tool.h | 5 + pcbnew/tools/pcb_point_editor.cpp | 2 +- pcbnew/tools/pcb_selection_tool.cpp | 17 ++-- pcbnew/undo_redo.cpp | 4 +- 9 files changed, 135 insertions(+), 58 deletions(-) diff --git a/common/tool/actions.cpp b/common/tool/actions.cpp index a3516de381..02cf14999a 100644 --- a/common/tool/actions.cpp +++ b/common/tool/actions.cpp @@ -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 ); diff --git a/include/tool/actions.h b/include/tool/actions.h index 773b7e1ef9..bd0ed8d278 100644 --- a/include/tool/actions.h +++ b/include/tool/actions.h @@ -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 diff --git a/pcbnew/board_commit.cpp b/pcbnew/board_commit.cpp index 6e5d580a10..bf3dab51a8 100644 --- a/pcbnew/board_commit.cpp +++ b/pcbnew/board_commit.cpp @@ -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( 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 diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index d003ef6642..4acebe722f 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -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(); diff --git a/pcbnew/tools/pad_tool.cpp b/pcbnew/tools/pad_tool.cpp index 6e562fed66..16796638ad 100644 --- a/pcbnew/tools/pad_tool.cpp +++ b/pcbnew/tools/pad_tool.cpp @@ -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( view()->GetPainter()->GetSettings() ); - WX_INFOBAR* infoBar = frame()->GetInfoBar(); + KIGFX::PCB_PAINTER* painter = static_cast( view()->GetPainter() ); + PCB_RENDER_SETTINGS* settings = painter->GetSettings(); PCB_SELECTION& selection = m_toolMgr->GetTool()->GetSelection(); - wxString msg; if( m_editPad != niluuid ) { @@ -638,65 +637,117 @@ int PAD_TOOL::EditPad( const TOOL_EVENT& aEvent ) PAD* pad = static_cast( 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( 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( 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( 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( 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( 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 ); } diff --git a/pcbnew/tools/pad_tool.h b/pcbnew/tools/pad_tool.h index bb31006d2c..3fb6f6c4fb 100644 --- a/pcbnew/tools/pad_tool.h +++ b/pcbnew/tools/pad_tool.h @@ -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; diff --git a/pcbnew/tools/pcb_point_editor.cpp b/pcbnew/tools/pcb_point_editor.cpp index 0b8143b704..bb421d32c3 100644 --- a/pcbnew/tools/pcb_point_editor.cpp +++ b/pcbnew/tools/pcb_point_editor.cpp @@ -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 ); } } diff --git a/pcbnew/tools/pcb_selection_tool.cpp b/pcbnew/tools/pcb_selection_tool.cpp index 9b47295e23..87151c2aed 100644 --- a/pcbnew/tools/pcb_selection_tool.cpp +++ b/pcbnew/tools/pcb_selection_tool.cpp @@ -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; diff --git a/pcbnew/undo_redo.cpp b/pcbnew/undo_redo.cpp index 918e9060af..3f42b616c4 100644 --- a/pcbnew/undo_redo.cpp +++ b/pcbnew/undo_redo.cpp @@ -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();