Implement undo/redo for footprint children.

Our special-cases to handle the fact that we didn't do this had far
outgrown the code necessary to actually handle it.
This commit is contained in:
Jeff Young 2023-07-15 17:37:17 +01:00
parent 3233bbe0ba
commit 1218f61d0a
16 changed files with 276 additions and 654 deletions

View File

@ -254,7 +254,7 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
bool isSyntheticClick = symbol && evt->IsActivate() && evt->HasPosition()
&& evt->Matches( aEvent );
if( evt->IsCancelInteractive() || evt->IsAction( &ACTIONS::undo ) )
if( evt->IsCancelInteractive() || ( symbol && evt->IsAction( &ACTIONS::undo ) ) )
{
m_frame->GetInfoBar()->Dismiss();
@ -451,7 +451,7 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
{
cleanup();
}
else if( evt->IsAction( &ACTIONS::redo ) )
else if( symbol && evt->IsAction( &ACTIONS::redo ) )
{
wxBell();
}
@ -550,7 +550,7 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
bool isSyntheticClick = image && evt->IsActivate() && evt->HasPosition()
&& evt->Matches( aEvent );
if( evt->IsCancelInteractive() || evt->IsAction( &ACTIONS::undo ) )
if( evt->IsCancelInteractive() || ( image && evt->IsAction( &ACTIONS::undo ) ) )
{
m_frame->GetInfoBar()->Dismiss();
@ -689,7 +689,7 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
{
cleanup();
}
else if( evt->IsAction( &ACTIONS::redo ) )
else if( image && evt->IsAction( &ACTIONS::redo ) )
{
wxBell();
}
@ -806,7 +806,7 @@ int SCH_DRAWING_TOOLS::SingleClickPlace( const TOOL_EVENT& aEvent )
cursorPos = grid.BestSnapAnchor( cursorPos, LAYER_CONNECTABLE, nullptr );
controls->ForceCursorPosition( true, cursorPos );
if( evt->IsCancelInteractive() || evt->IsAction( &ACTIONS::undo ) )
if( evt->IsCancelInteractive() )
{
m_frame->PopTool( aEvent );
break;
@ -934,10 +934,6 @@ int SCH_DRAWING_TOOLS::SingleClickPlace( const TOOL_EVENT& aEvent )
evt->SetPassEvent();
}
}
else if( evt->IsAction( &ACTIONS::redo ) )
{
wxBell();
}
else
{
evt->SetPassEvent();
@ -1551,7 +1547,7 @@ int SCH_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
bool isSyntheticClick = item && evt->IsActivate() && evt->HasPosition()
&& evt->Matches( aEvent );
if( evt->IsCancelInteractive() || evt->IsAction( &ACTIONS::undo ) )
if( evt->IsCancelInteractive() || ( item && evt->IsAction( &ACTIONS::undo ) ) )
{
if( item )
{
@ -1700,7 +1696,7 @@ int SCH_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
m_menu.ShowContextMenu( m_selectionTool->GetSelection() );
}
else if( evt->IsAction( &ACTIONS::redo ) )
else if( item && evt->IsAction( &ACTIONS::redo ) )
{
wxBell();
}
@ -1771,7 +1767,7 @@ int SCH_DRAWING_TOOLS::DrawSheet( const TOOL_EVENT& aEvent )
bool isSyntheticClick = sheet && evt->IsActivate() && evt->HasPosition()
&& evt->Matches( aEvent );
if( evt->IsCancelInteractive() || evt->IsAction( &ACTIONS::undo ) )
if( evt->IsCancelInteractive() || ( sheet && evt->IsAction( &ACTIONS::undo ) ) )
{
m_frame->GetInfoBar()->Dismiss();
@ -1897,7 +1893,7 @@ int SCH_DRAWING_TOOLS::DrawSheet( const TOOL_EVENT& aEvent )
m_menu.ShowContextMenu( m_selectionTool->GetSelection() );
}
else if( evt->IsAction( &ACTIONS::redo ) )
else if( sheet && evt->IsAction( &ACTIONS::redo ) )
{
wxBell();
}

View File

@ -32,6 +32,7 @@
#include <vector>
#include <wx/string.h>
#include <undo_redo_container.h>
#include <kiid.h>
class EDA_ITEM;
class BASE_SCREEN;
@ -43,9 +44,7 @@ enum CHANGE_TYPE {
CHT_MODIFY = 4,
CHT_TYPE = CHT_ADD | CHT_REMOVE | CHT_MODIFY,
///< Flag to indicate the change is already applied,
///< just notify observers (not compatible with CHT_MODIFY)
CHT_DONE = 8,
CHT_DONE = 8, ///< Flag to indicate the change is already applied
CHT_FLAGS = CHT_DONE
};
@ -151,9 +150,10 @@ public:
protected:
struct COMMIT_LINE
{
EDA_ITEM* m_item; ///< Main item that is added/deleted/modified
EDA_ITEM* m_copy; ///< Optional copy of the item
CHANGE_TYPE m_type; ///< Modification type
EDA_ITEM* m_item; ///< Main item that is added/deleted/modified
EDA_ITEM* m_copy; ///< Optional copy of the item
CHANGE_TYPE m_type; ///< Modification type
KIID m_parent = NilUuid(); ///< Parent item (primarily for undo of deleted items)
BASE_SCREEN* m_screen;
};

View File

@ -44,30 +44,20 @@ using namespace std::placeholders;
BOARD_COMMIT::BOARD_COMMIT( TOOL_BASE* aTool ) :
m_toolMgr( aTool->GetManager() ),
m_isFootprintEditor( false ),
m_isBoardEditor( false )
{
if( PCB_TOOL_BASE* pcb_tool = dynamic_cast<PCB_TOOL_BASE*>( aTool ) )
{
m_isFootprintEditor = pcb_tool->IsFootprintEditor();
m_isBoardEditor = pcb_tool->IsBoardEditor();
}
}
BOARD_COMMIT::BOARD_COMMIT( EDA_DRAW_FRAME* aFrame ) :
m_toolMgr( aFrame->GetToolManager() ),
m_isFootprintEditor( aFrame->IsType( FRAME_FOOTPRINT_EDITOR ) ),
m_isBoardEditor( aFrame->IsType( FRAME_PCB_EDITOR ) )
{
}
BOARD_COMMIT::~BOARD_COMMIT()
{
}
BOARD* BOARD_COMMIT::GetBoard() const
{
return static_cast<BOARD*>( m_toolMgr->GetModel() );
@ -78,68 +68,15 @@ COMMIT& BOARD_COMMIT::Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType, BASE_SCRE
{
wxCHECK( aItem, *this );
aItem->ClearFlags( IS_MODIFIED_CHILD );
// If aItem belongs a footprint, the full footprint will be saved because undo/redo does
// not handle "sub items" modifications. This has implications for some udpate mechanisms,
// such as auto-zone-refill and teardrop regeneration, so we need to store a bit more
// information.
if( aChangeType == CHT_MODIFY )
if( aChangeType == CHT_MODIFY && aItem->Type() == PCB_GROUP_T )
{
if( aItem->Type() == PCB_FOOTPRINT_T )
{
static_cast<FOOTPRINT*>( aItem )->RunOnChildren(
[&]( BOARD_ITEM* child )
{
child->SetFlags( IS_MODIFIED_CHILD );
} );
return COMMIT::Stage( aItem, aChangeType );
}
else if( aItem->GetParent() && aItem->GetParent()->Type() == PCB_FOOTPRINT_T )
{
FOOTPRINT* parentFootprint = static_cast<FOOTPRINT*>( aItem->GetParent() );
bool parentFootprintStaged = alg::contains( m_changedItems, parentFootprint );
if( !parentFootprintStaged )
{
parentFootprint->RunOnChildren(
[&]( BOARD_ITEM* child )
{
child->ClearFlags( IS_MODIFIED_CHILD );
} );
}
if( aItem->Type() == PCB_GROUP_T )
{
static_cast<PCB_GROUP*>( aItem )->RunOnChildren(
[&]( BOARD_ITEM* child )
{
child->SetFlags( IS_MODIFIED_CHILD );
} );
}
else
{
aItem->SetFlags( IS_MODIFIED_CHILD );
}
if( !parentFootprintStaged )
return COMMIT::Stage( parentFootprint, aChangeType );
return *this;
}
else if( aItem->Type() == PCB_GROUP_T )
{
// Many operations on group (move, rotate, etc.) are applied directly to their
// children, so it's the children that must be staged.
static_cast<PCB_GROUP*>( aItem )->RunOnChildren(
[&]( BOARD_ITEM* child )
{
COMMIT::Stage( child, aChangeType );
} );
return COMMIT::Stage( aItem, aChangeType );
}
// Many operations on group (move, rotate, etc.) are applied directly to their
// children, so it's the children that must be staged.
static_cast<PCB_GROUP*>( aItem )->RunOnChildren(
[&]( BOARD_ITEM* child )
{
COMMIT::Stage( child, aChangeType );
} );
}
return COMMIT::Stage( aItem, aChangeType );
@ -169,24 +106,12 @@ void BOARD_COMMIT::dirtyIntersectingZones( BOARD_ITEM* item, int aChangeType )
if( item->Type() == PCB_ZONE_T )
zoneFillerTool->DirtyZone( static_cast<ZONE*>( item ) );
if( item->Type() == PCB_FOOTPRINT_T )
{
static_cast<FOOTPRINT*>( item )->RunOnChildren(
[&]( BOARD_ITEM* child )
{
if( aChangeType != CHT_MODIFY || ( child->GetFlags() & IS_MODIFIED_CHILD ) )
dirtyIntersectingZones( child, aChangeType );
child->ClearFlags( IS_MODIFIED_CHILD );
} );
}
else if( item->Type() == PCB_GROUP_T )
if( item->Type() == PCB_GROUP_T )
{
static_cast<PCB_GROUP*>( item )->RunOnChildren(
[&]( BOARD_ITEM* child )
{
dirtyIntersectingZones( child, aChangeType );
child->ClearFlags( IS_MODIFIED_CHILD );
} );
}
else
@ -214,8 +139,6 @@ void BOARD_COMMIT::dirtyIntersectingZones( BOARD_ITEM* item, int aChangeType )
}
}
}
item->ClearFlags( IS_MODIFIED_CHILD );
}
}
@ -229,7 +152,6 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
// Notification info
PICKED_ITEMS_LIST undoList;
std::set<EDA_ITEM*> savedModules;
bool itemsDeselected = false;
bool selectedModified = false;
@ -246,10 +168,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
std::shared_ptr<CONNECTIVITY_DATA> connectivity = board->GetConnectivity();
// Note:
// frame == nullptr happens in QA tests
// in this case m_isBoardEditor and m_isFootprintEditor are set to false
// But we also test frame == nullptr mainly to make Coverity happy
// Note: frame == nullptr happens in QA tests
std::vector<BOARD_ITEM*> bulkAddedItems;
std::vector<BOARD_ITEM*> bulkRemovedItems;
@ -272,41 +191,6 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( ent.m_item );
wxASSERT( ent.m_item );
// Module items need to be saved in the undo buffer before modification
if( m_isFootprintEditor )
{
// Be sure that we are storing a footprint
if( ent.m_item->Type() != PCB_FOOTPRINT_T )
{
ent.m_item = ent.m_item->GetParent();
wxASSERT( ent.m_item );
}
// We have not saved the footprint yet, so let's create an entry
if( savedModules.count( ent.m_item ) == 0 )
{
if( !ent.m_copy )
{
wxASSERT( changeType != CHT_MODIFY ); // too late to make a copy..
ent.m_copy = makeImage( ent.m_item );
}
wxASSERT( ent.m_item->Type() == PCB_FOOTPRINT_T );
wxASSERT( ent.m_copy->Type() == PCB_FOOTPRINT_T );
if( !( aCommitFlags & SKIP_UNDO ) && frame )
{
ITEM_PICKER itemWrapper( nullptr, ent.m_item, UNDO_REDO::CHANGED );
itemWrapper.SetLink( ent.m_copy );
undoList.PushItem( itemWrapper );
frame->SaveCopyInUndoList( undoList, UNDO_REDO::CHANGED );
}
savedModules.insert( ent.m_item );
}
}
wxCHECK2( boardItem, continue );
if( m_isBoardEditor )
@ -354,43 +238,25 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
if( boardItem->IsSelected() )
selectedModified = true;
// If we're the footprint editor, the boardItem will always be the containing footprint
if( m_isFootprintEditor && boardItem->Type() == PCB_FOOTPRINT_T )
{
static_cast<FOOTPRINT*>( boardItem )->RunOnChildren(
[&selectedModified]( BOARD_ITEM* aItem )
{
if( aItem->HasFlag( IS_MODIFIED_CHILD ) )
selectedModified = true;
} );
}
switch( changeType )
{
case CHT_ADD:
{
if( selTool && selTool->GetEnteredGroup() && !boardItem->GetParentGroup()
&& PCB_GROUP::IsGroupableType( boardItem->Type() ) )
{
selTool->GetEnteredGroup()->AddItem( boardItem );
}
if( m_isFootprintEditor )
if( !( aCommitFlags & SKIP_UNDO ) )
undoList.PushItem( ITEM_PICKER( nullptr, boardItem, UNDO_REDO::NEWITEM ) );
if( !( changeFlags & CHT_DONE ) )
{
// footprints inside footprints are not supported yet
wxASSERT( boardItem->Type() != PCB_FOOTPRINT_T );
boardItem->SetParent( board->Footprints().front() );
if( !( changeFlags & CHT_DONE ) )
board->Footprints().front()->Add( boardItem );
}
else if( !boardItem->GetParentFootprint() )
{
if( !( aCommitFlags & SKIP_UNDO ) )
undoList.PushItem( ITEM_PICKER( nullptr, boardItem, UNDO_REDO::NEWITEM ) );
if( !( changeFlags & CHT_DONE ) )
if( FOOTPRINT* parentFP = boardItem->GetParentFootprint() )
{
parentFP->Add( boardItem );
}
else
{
board->Add( boardItem, ADD_MODE::BULK_INSERT ); // handles connectivity
bulkAddedItems.push_back( boardItem );
@ -404,14 +270,13 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
view->Add( boardItem );
break;
}
case CHT_REMOVE:
{
FOOTPRINT* parentFP = boardItem->GetParentFootprint();
PCB_GROUP* parentGroup = boardItem->GetParentGroup();
if( !m_isFootprintEditor && !( aCommitFlags & SKIP_UNDO ) )
if( !( aCommitFlags & SKIP_UNDO ) )
undoList.PushItem( ITEM_PICKER( nullptr, boardItem, UNDO_REDO::DELETED ) );
if( boardItem->IsSelected() )
@ -425,6 +290,9 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
if( parentGroup && !( parentGroup->GetFlags() & STRUCT_DELETED ) )
parentGroup->RemoveItem( boardItem );
if( parentFP && !( parentFP->GetFlags() & STRUCT_DELETED ) )
ent.m_parent = parentFP->m_Uuid;
if( autofillZones )
dirtyIntersectingZones( boardItem, changeType );
@ -447,6 +315,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
case PCB_TARGET_T: // a target (graphic item)
case PCB_MARKER_T: // a marker used to show something
case PCB_ZONE_T:
case PCB_FOOTPRINT_T:
if( view )
view->Remove( boardItem );
@ -465,27 +334,6 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
break;
case PCB_FOOTPRINT_T:
{
// No support for nested footprints (yet)
wxASSERT( !m_isFootprintEditor );
FOOTPRINT* footprint = static_cast<FOOTPRINT*>( boardItem );
if( view )
view->Remove( footprint );
footprint->ClearFlags();
if( !( changeFlags & CHT_DONE ) )
{
board->Remove( footprint, REMOVE_MODE::BULK ); // handles connectivity
bulkRemovedItems.push_back( footprint );
}
}
break;
case PCB_GROUP_T:
if( view )
view->Remove( boardItem );
@ -523,7 +371,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
{
BOARD_ITEM* boardItemCopy = dynamic_cast<BOARD_ITEM*>( ent.m_copy );
if( !m_isFootprintEditor && !( aCommitFlags & SKIP_UNDO ) )
if( !( aCommitFlags & SKIP_UNDO ) )
{
ITEM_PICKER itemWrapper( nullptr, boardItem, UNDO_REDO::CHANGED );
wxASSERT( boardItemCopy );
@ -539,26 +387,15 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
connectivity->Update( boardItem );
}
if( autofillZones )
if( m_isBoardEditor && autofillZones )
{
dirtyIntersectingZones( boardItemCopy, changeType ); // before
dirtyIntersectingZones( boardItem, changeType ); // after
}
if( view )
{
view->Update( boardItem );
if( m_isFootprintEditor )
{
static_cast<FOOTPRINT*>( boardItem )->RunOnChildren(
[&]( BOARD_ITEM* aChild )
{
view->Update( aChild );
} );
}
}
itemsChanged.push_back( boardItem );
// if no undo entry is needed, the copy would create a memory leak
@ -574,15 +411,6 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
}
boardItem->ClearEditFlags();
if( m_isFootprintEditor && boardItem->Type() == PCB_FOOTPRINT_T )
{
static_cast<FOOTPRINT*>( boardItem )->RunOnChildren(
[&]( BOARD_ITEM* aChild )
{
aChild->ClearEditFlags();
} );
}
}
if( bulkAddedItems.size() > 0 )
@ -658,12 +486,15 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
}
}
if( m_isBoardEditor && !( aCommitFlags & SKIP_UNDO ) && frame )
if( frame )
{
if( aCommitFlags & APPEND_UNDO )
frame->AppendCopyToUndoList( undoList, UNDO_REDO::UNSPECIFIED );
else
frame->SaveCopyInUndoList( undoList, UNDO_REDO::UNSPECIFIED );
if( !( aCommitFlags & SKIP_UNDO ) )
{
if( aCommitFlags & APPEND_UNDO )
frame->AppendCopyToUndoList( undoList, UNDO_REDO::UNSPECIFIED );
else
frame->SaveCopyInUndoList( undoList, UNDO_REDO::UNSPECIFIED );
}
}
m_toolMgr->PostEvent( { TC_MESSAGE, TA_MODEL_CHANGE, AS_GLOBAL } );
@ -742,8 +573,17 @@ void BOARD_COMMIT::Revert()
view->Remove( boardItem );
connectivity->Remove( boardItem );
board->Remove( boardItem, REMOVE_MODE::BULK );
bulkRemovedItems.push_back( boardItem );
if( FOOTPRINT* parentFP = boardItem->GetParentFootprint() )
{
parentFP->Remove( boardItem );
}
else
{
board->Remove( boardItem, REMOVE_MODE::BULK );
bulkRemovedItems.push_back( boardItem );
}
break;
case CHT_REMOVE:
@ -752,8 +592,17 @@ void BOARD_COMMIT::Revert()
view->Add( boardItem );
connectivity->Add( boardItem );
board->Add( boardItem, ADD_MODE::INSERT );
bulkAddedItems.push_back( boardItem );
if( FOOTPRINT* parentFP = dynamic_cast<FOOTPRINT*>( board->GetItem( ent.m_parent ) ) )
{
parentFP->Add( boardItem, ADD_MODE::INSERT );
}
else
{
board->Add( boardItem, ADD_MODE::INSERT );
bulkAddedItems.push_back( boardItem );
}
break;
case CHT_MODIFY:
@ -801,7 +650,7 @@ void BOARD_COMMIT::Revert()
if( itemsChanged.size() > 0 )
board->OnItemsChanged( itemsChanged );
if ( !m_isFootprintEditor )
if( m_isBoardEditor )
{
connectivity->RecalculateRatsnest();
board->UpdateRatsnestExclusions();

View File

@ -49,7 +49,7 @@ public:
BOARD_COMMIT( EDA_DRAW_FRAME* aFrame );
BOARD_COMMIT( TOOL_BASE *aTool );
virtual ~BOARD_COMMIT();
virtual ~BOARD_COMMIT() {}
BOARD* GetBoard() const;
@ -74,7 +74,6 @@ private:
private:
TOOL_MANAGER* m_toolMgr;
bool m_isFootprintEditor;
bool m_isBoardEditor;
};

View File

@ -1046,7 +1046,7 @@ int BOARD_EDITOR_CONTROL::PlaceFootprint( const TOOL_EVENT& aEvent )
if( reselect && fp )
m_toolMgr->RunAction<EDA_ITEM*>( PCB_ACTIONS::selectItem, fp );
if( evt->IsCancelInteractive() )
if( evt->IsCancelInteractive() || ( fp && evt->IsAction( &ACTIONS::undo ) ) )
{
if( fp )
{
@ -1156,7 +1156,8 @@ int BOARD_EDITOR_CONTROL::PlaceFootprint( const TOOL_EVENT& aEvent )
// Calling 'Properties' action clears the selection, so we need to restore it
reselect = true;
}
else if( fp && ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
else if( fp && ( ZONE_FILLER_TOOL::IsZoneFillAction( evt )
|| evt->IsAction( &ACTIONS::redo ) ) )
{
wxBell();
}
@ -1227,7 +1228,6 @@ int BOARD_EDITOR_CONTROL::modifyLockSelected( MODIFY_MODE aMode )
for( EDA_ITEM* item : selection )
{
BOARD_ITEM* board_item = dynamic_cast<BOARD_ITEM*>( item );
wxCHECK2( board_item, continue );
commit.Modify( board_item );
@ -1369,7 +1369,7 @@ int BOARD_EDITOR_CONTROL::ZoneMerge( const TOOL_EVENT& aEvent )
{
if( mergeZones( m_frame, commit, toMerge, merged ) )
{
commit.Push( wxT( "Merge zones" ) );
commit.Push( wxT( "Merge Zones" ) );
for( EDA_ITEM* item : merged )
m_toolMgr->RunAction( PCB_ACTIONS::selectItem, item );
@ -1425,7 +1425,7 @@ int BOARD_EDITOR_CONTROL::ZoneDuplicate( const TOOL_EVENT& aEvent )
newZone->Move( VECTOR2I( pcbIUScale.IU_PER_MM, pcbIUScale.IU_PER_MM ) );
commit.Add( newZone.release() );
commit.Push( _( "Duplicate zone" ) );
commit.Push( _( "Duplicate Zone" ) );
return 0;
}
@ -1434,7 +1434,6 @@ int BOARD_EDITOR_CONTROL::ZoneDuplicate( const TOOL_EVENT& aEvent )
int BOARD_EDITOR_CONTROL::CrossProbeToSch( const TOOL_EVENT& aEvent )
{
doCrossProbePcbToSch( aEvent, false );
return 0;
}
@ -1442,7 +1441,6 @@ int BOARD_EDITOR_CONTROL::CrossProbeToSch( const TOOL_EVENT& aEvent )
int BOARD_EDITOR_CONTROL::ExplicitCrossProbeToSch( const TOOL_EVENT& aEvent )
{
doCrossProbePcbToSch( aEvent, true );
return 0;
}
@ -1618,20 +1616,17 @@ void BOARD_EDITOR_CONTROL::setTransitions()
Go( &BOARD_EDITOR_CONTROL::BoardSetup, PCB_ACTIONS::boardSetup.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::ImportNetlist, PCB_ACTIONS::importNetlist.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::ImportSpecctraSession,
PCB_ACTIONS::importSpecctraSession.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::ImportSpecctraSession, PCB_ACTIONS::importSpecctraSession.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::ExportSpecctraDSN, PCB_ACTIONS::exportSpecctraDSN.MakeEvent() );
if( ADVANCED_CFG::GetCfg().m_ShowPcbnewExportNetlist && m_frame &&
m_frame->GetExportNetlistAction() )
Go( &BOARD_EDITOR_CONTROL::ExportNetlist, m_frame->GetExportNetlistAction()->MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::GenerateDrillFiles,
PCB_ACTIONS::generateDrillFiles.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::GenerateDrillFiles, PCB_ACTIONS::generateDrillFiles.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::GenerateFabFiles, PCB_ACTIONS::generateGerbers.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::GeneratePosFile, PCB_ACTIONS::generatePosFile.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::GenerateFabFiles,
PCB_ACTIONS::generateReportFile.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::GenerateFabFiles, PCB_ACTIONS::generateReportFile.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::GenerateFabFiles, PCB_ACTIONS::generateD356File.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::GenerateFabFiles, PCB_ACTIONS::generateBOM.MakeEvent() );
@ -1666,10 +1661,8 @@ void BOARD_EDITOR_CONTROL::setTransitions()
Go( &BOARD_EDITOR_CONTROL::AssignNetclass, PCB_ACTIONS::assignNetClass.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::UpdatePCBFromSchematic,
ACTIONS::updatePcbFromSchematic.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::UpdateSchematicFromPCB,
ACTIONS::updateSchematicFromPcb.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::UpdatePCBFromSchematic, ACTIONS::updatePcbFromSchematic.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::UpdateSchematicFromPCB, ACTIONS::updateSchematicFromPcb.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::ShowEeschema, PCB_ACTIONS::showEeschema.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::ToggleLayersManager, PCB_ACTIONS::showLayersManager.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::ToggleProperties, ACTIONS::showProperties.MakeEvent() );

View File

@ -475,9 +475,19 @@ int CONVERT_TOOL::CreatePolys( const TOOL_EVENT& aEvent )
}
if( aEvent.IsAction( &PCB_ACTIONS::convertToPoly ) )
commit.Push( _( "Convert shapes to polygon" ) );
{
if( m_userSettings.m_DeleteOriginals )
commit.Push( _( "Convert to Polygon" ) );
else
commit.Push( _( "Create Polygon" ) );
}
else
commit.Push( _( "Convert shapes to zone" ) );
{
if( m_userSettings.m_DeleteOriginals )
commit.Push( _( "Convert to Zone" ) );
else
commit.Push( _( "Create Zone" ) );
}
return 0;
}
@ -1018,7 +1028,7 @@ int CONVERT_TOOL::CreateLines( const TOOL_EVENT& aEvent )
}
}
commit.Push( _( "Convert polygons to lines" ) );
commit.Push( _( "Create Lines" ) );
return 0;
}
@ -1105,7 +1115,7 @@ int CONVERT_TOOL::SegmentToArc( const TOOL_EVENT& aEvent )
commit.Add( arc );
}
commit.Push( _( "Create arc from line segment" ) );
commit.Push( _( "Create Arc" ) );
return 0;
}

View File

@ -344,7 +344,7 @@ int DRAWING_TOOL::DrawLine( const TOOL_EVENT& aEvent )
if( line )
{
commit.Add( line );
commit.Push( _( "Draw a line segment" ) );
commit.Push( _( "Draw Line" ) );
startingPoint = VECTOR2D( line->GetEnd() );
committedLines.push( line );
}
@ -408,7 +408,7 @@ int DRAWING_TOOL::DrawRectangle( const TOOL_EVENT& aEvent )
{
rect->NormalizeRect();
commit.Add( rect );
commit.Push( isTextBox ? _( "Draw a text box" ) : _( "Draw a rectangle" ) );
commit.Push( isTextBox ? _( "Draw Text Box" ) : _( "Draw Rectangle" ) );
m_toolMgr->RunAction<EDA_ITEM*>( PCB_ACTIONS::selectItem, rect );
}
@ -456,7 +456,7 @@ int DRAWING_TOOL::DrawCircle( const TOOL_EVENT& aEvent )
if( circle )
{
commit.Add( circle );
commit.Push( _( "Draw a circle" ) );
commit.Push( _( "Draw Circle" ) );
m_toolMgr->RunAction<EDA_ITEM*>( PCB_ACTIONS::selectItem, circle );
}
@ -503,7 +503,7 @@ int DRAWING_TOOL::DrawArc( const TOOL_EVENT& aEvent )
if( arc )
{
commit.Add( arc );
commit.Push( _( "Draw an arc" ) );
commit.Push( _( "Draw Arc" ) );
m_toolMgr->RunAction<EDA_ITEM*>( PCB_ACTIONS::selectItem, arc );
}
@ -601,7 +601,7 @@ int DRAWING_TOOL::PlaceImage( const TOOL_EVENT& aEvent )
COORDS_PADDING );
m_controls->ForceCursorPosition( true, cursorPos );
if( evt->IsCancelInteractive() || evt->IsAction( &ACTIONS::undo ) )
if( evt->IsCancelInteractive() || ( image && evt->IsAction( &ACTIONS::undo ) ) )
{
if( image )
{
@ -703,7 +703,7 @@ int DRAWING_TOOL::PlaceImage( const TOOL_EVENT& aEvent )
else
{
commit.Add( image );
commit.Push( _( "Place an image" ) );
commit.Push( _( "Place Image" ) );
m_toolMgr->RunAction<EDA_ITEM*>( PCB_ACTIONS::selectItem, image );
@ -727,7 +727,8 @@ int DRAWING_TOOL::PlaceImage( const TOOL_EVENT& aEvent )
m_menu.ShowContextMenu( selectionTool->GetSelection() );
}
else if( image && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
else if( image && ( evt->IsAction( &ACTIONS::refreshPreview )
|| evt->IsMotion() ) )
{
image->SetPosition( cursorPos );
m_view->ClearPreview();
@ -738,11 +739,8 @@ int DRAWING_TOOL::PlaceImage( const TOOL_EVENT& aEvent )
{
cleanup();
}
else if( image && ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
{
wxBell();
}
else if( evt->IsAction( &ACTIONS::redo ) )
else if( image && ( ZONE_FILLER_TOOL::IsZoneFillAction( evt )
|| evt->IsAction( &ACTIONS::redo ) ) )
{
wxBell();
}
@ -837,7 +835,7 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
COORDS_PADDING );
m_controls->ForceCursorPosition( true, cursorPos );
if( evt->IsCancelInteractive() || evt->IsAction( &ACTIONS::undo ) )
if( evt->IsCancelInteractive() || ( text && evt->IsAction( &ACTIONS::undo ) ) )
{
if( text )
{
@ -891,15 +889,10 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
textAttrs.m_Halign = GR_TEXT_H_ALIGN_LEFT;
textAttrs.m_Valign = GR_TEXT_V_ALIGN_BOTTOM;
// Init the new item attributes
if( m_isFootprintEditor )
{
text = new PCB_TEXT( static_cast<FOOTPRINT*>( m_frame->GetModel() ) );
}
else
{
text = new PCB_TEXT( m_frame->GetModel() );
}
text->SetLayer( layer );
text->SetAttributes( textAttrs );
@ -948,7 +941,7 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear );
commit.Add( text );
commit.Push( _( "Place a text" ) );
commit.Push( _( "Place Text" ) );
m_toolMgr->RunAction<EDA_ITEM*>( PCB_ACTIONS::selectItem, text );
@ -977,32 +970,23 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
m_controls->CaptureCursor( text != nullptr );
m_controls->SetAutoPan( text != nullptr );
}
else if( text && ( evt->IsMotion() || evt->IsAction( &PCB_ACTIONS::refreshPreview ) ) )
else if( text && ( evt->IsMotion()
|| evt->IsAction( &PCB_ACTIONS::refreshPreview ) ) )
{
text->SetPosition( cursorPos );
selection().SetReferencePoint( cursorPos );
m_view->Update( &selection() );
}
else if( text && ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
else if( text && ( ZONE_FILLER_TOOL::IsZoneFillAction( evt )
|| evt->IsAction( &ACTIONS::redo ) ) )
{
wxBell();
}
else if( evt->IsAction( &PCB_ACTIONS::properties ) )
else if( text && evt->IsAction( &PCB_ACTIONS::properties ) )
{
if( text )
{
frame()->OnEditItemRequest( text );
m_view->Update( &selection() );
frame()->SetMsgPanel( text );
}
else
{
evt->SetPassEvent();
}
}
else if( evt->IsAction( &ACTIONS::redo ) )
{
wxBell();
frame()->OnEditItemRequest( text );
m_view->Update( &selection() );
frame()->SetMsgPanel( text );
}
else
{
@ -1124,7 +1108,7 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
m_controls->ForceCursorPosition( true, cursorPos );
if( evt->IsCancelInteractive() || evt->IsAction( &ACTIONS::undo ) )
if( evt->IsCancelInteractive() || ( dimension && evt->IsAction( &ACTIONS::undo ) ) )
{
m_controls->SetAutoPan( false );
@ -1283,7 +1267,7 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
preview.Remove( dimension );
commit.Add( dimension );
commit.Push( _( "Draw a dimension" ) );
commit.Push( _( "Draw Dimension" ) );
// Run the edit immediately to set the leader text
if( t == PCB_DIM_LEADER_T )
@ -1443,11 +1427,8 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
wxBell();
}
}
else if( dimension && ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
{
wxBell();
}
else if( evt->IsAction( &ACTIONS::redo ) )
else if( dimension && ( ZONE_FILLER_TOOL::IsZoneFillAction( evt )
|| evt->IsAction( &ACTIONS::redo ) ) )
{
wxBell();
}
@ -1525,7 +1506,6 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent )
for( std::unique_ptr<EDA_ITEM>& ptr : list )
{
BOARD_ITEM* item = dynamic_cast<BOARD_ITEM*>( ptr.get() );
wxCHECK2( item, continue );
newItems.push_back( item );
@ -1545,7 +1525,7 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent )
for( BOARD_ITEM* item : newItems )
commit.Add( item );
commit.Push( _( "Place a DXF_SVG drawing" ) );
commit.Push( _( "Import Graphic" ) );
return 0;
}
@ -1632,7 +1612,7 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent )
for( BOARD_ITEM* item : newItems )
commit.Add( item );
commit.Push( _( "Place a DXF_SVG drawing" ) );
commit.Push( _( "Import Graphic" ) );
break; // This is a one-shot command, not a tool
}
else if( ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
@ -1713,7 +1693,7 @@ int DRAWING_TOOL::SetAnchor( const TOOL_EVENT& aEvent )
VECTOR2I moveVector = footprint->GetPosition() - cursorPos;
footprint->MoveAnchorPosition( moveVector );
commit.Push( _( "Move the footprint reference anchor" ) );
commit.Push( _( "Move Footprint Anchor" ) );
// Usually, we do not need to change twice the anchor position,
// so deselect the active tool
@ -1807,12 +1787,12 @@ bool DRAWING_TOOL::drawShape( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
}
// geometric construction manager
KIGFX::PREVIEW::TWO_POINT_GEOMETRY_MANAGER twoPointManager;
KIGFX::PREVIEW::TWO_POINT_GEOMETRY_MANAGER twoPointMgr;
// drawing assistant overlay
// TODO: workaround because EDA_SHAPE_TYPE_T is not visible from commons.
KIGFX::PREVIEW::GEOM_SHAPE geomShape( static_cast<KIGFX::PREVIEW::GEOM_SHAPE>( shape ) );
KIGFX::PREVIEW::TWO_POINT_ASSISTANT twoPointAsst( twoPointManager, pcbIUScale, userUnits, geomShape );
KIGFX::PREVIEW::TWO_POINT_ASSISTANT twoPointAsst( twoPointMgr, pcbIUScale, userUnits, geomShape );
// Add a VIEW_GROUP that serves as a preview for the new item
PCB_SELECTION preview;
@ -1976,8 +1956,8 @@ bool DRAWING_TOOL::drawShape( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
grid.SetSkipPoint( cursorPos );
twoPointManager.SetOrigin( cursorPos );
twoPointManager.SetEnd( cursorPos );
twoPointMgr.SetOrigin( cursorPos );
twoPointMgr.SetEnd( cursorPos );
if( !isLocalOriginSet )
m_frame->GetScreen()->m_LocalOrigin = cursorPos;
@ -1993,35 +1973,28 @@ bool DRAWING_TOOL::drawShape( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
m_frame->GetCanvas()->Refresh();
}
updateSegmentFromGeometryMgr( twoPointManager, graphic );
updateSegmentFromGeometryMgr( twoPointMgr, graphic );
started = true;
}
else if( shape == SHAPE_T::CIRCLE )
{
// No clever logic if drawing a circle
preview.Clear();
twoPointManager.Reset();
break;
}
else
{
PCB_SHAPE* snapItem = dynamic_cast<PCB_SHAPE*>( grid.GetSnapped() );
if( twoPointManager.GetOrigin() == twoPointManager.GetEnd()
|| ( evt->IsDblClick( BUT_LEFT ) && shape == SHAPE_T::SEGMENT )
|| snapItem )
// User has clicked twice in the same spot
// or clicked on the end of an existing segment (closing a path)
if( shape == SHAPE_T::SEGMENT && ( twoPointMgr.GetOrigin() == twoPointMgr.GetEnd()
|| evt->IsDblClick( BUT_LEFT )
|| snapItem ) )
{
// User has clicked twice in the same spot
// or clicked on the end of an existing segment (closing a path)
BOARD_COMMIT commit( m_frame );
// If the user clicks on an existing snap point from a drawsegment
// we finish the segment as they are likely closing a path
if( snapItem && ( shape == SHAPE_T::RECT || graphic->GetLength() > 0.0 ) )
if( snapItem && graphic->GetLength() > 0.0 )
{
commit.Add( graphic );
commit.Push( _( "Draw a line segment" ) );
commit.Push( _( "Draw Line" ) );
m_toolMgr->RunAction<EDA_ITEM*>( PCB_ACTIONS::selectItem, graphic );
}
else
@ -2033,59 +2006,53 @@ bool DRAWING_TOOL::drawShape( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
}
preview.Clear();
twoPointManager.Reset();
twoPointMgr.Reset();
break;
}
twoPointManager.SetEnd( GetClampedCoords( cursorPos ) );
twoPointMgr.SetEnd( GetClampedCoords( cursorPos ) );
}
else if( evt->IsMotion() )
{
VECTOR2I clampedCursorPos = cursorPos;
if( shape == SHAPE_T::CIRCLE || shape == SHAPE_T::ARC )
{
clampedCursorPos = getClampedRadiusEnd( twoPointManager.GetOrigin(), cursorPos );
}
clampedCursorPos = getClampedRadiusEnd( twoPointMgr.GetOrigin(), cursorPos );
else
{
clampedCursorPos = getClampedDifferenceEnd( twoPointManager.GetOrigin(),
cursorPos );
}
clampedCursorPos = getClampedDifferenceEnd( twoPointMgr.GetOrigin(), cursorPos );
// 45 degree lines
if( started && Is45Limited() )
{
const VECTOR2I lineVector( clampedCursorPos
- VECTOR2I( twoPointManager.GetOrigin() ) );
const VECTOR2I lineVector( clampedCursorPos - VECTOR2I( twoPointMgr.GetOrigin() ) );
// get a restricted 45/H/V line from the last fixed point to the cursor
VECTOR2I newEnd = GetVectorSnapped45( lineVector, ( shape == SHAPE_T::RECT ) );
m_controls->ForceCursorPosition( true, VECTOR2I( twoPointManager.GetEnd() ) );
twoPointManager.SetEnd( twoPointManager.GetOrigin() + newEnd );
twoPointManager.SetAngleSnap( true );
m_controls->ForceCursorPosition( true, VECTOR2I( twoPointMgr.GetEnd() ) );
twoPointMgr.SetEnd( twoPointMgr.GetOrigin() + newEnd );
twoPointMgr.SetAngleSnap( true );
}
else
{
twoPointManager.SetEnd( clampedCursorPos );
twoPointManager.SetAngleSnap( false );
twoPointMgr.SetEnd( clampedCursorPos );
twoPointMgr.SetAngleSnap( false );
}
updateSegmentFromGeometryMgr( twoPointManager, graphic );
updateSegmentFromGeometryMgr( twoPointMgr, graphic );
m_view->Update( &preview );
m_view->Update( &twoPointAsst );
}
else if( evt->IsAction( &ACTIONS::undo )
|| evt->IsAction( &PCB_ACTIONS::doDelete )
|| evt->IsAction( &PCB_ACTIONS::deleteLastPoint ) )
else if( started && ( evt->IsAction( &ACTIONS::undo )
|| evt->IsAction( &PCB_ACTIONS::doDelete )
|| evt->IsAction( &PCB_ACTIONS::deleteLastPoint ) ) )
{
if( graphic && !aCommittedGraphics->empty() )
if( aCommittedGraphics && !aCommittedGraphics->empty() )
{
twoPointManager.SetOrigin( aCommittedGraphics->top()->GetStart() );
twoPointManager.SetEnd( aCommittedGraphics->top()->GetEnd() );
twoPointMgr.SetOrigin( aCommittedGraphics->top()->GetStart() );
twoPointMgr.SetEnd( aCommittedGraphics->top()->GetEnd() );
aCommittedGraphics->pop();
getViewControls()->WarpMouseCursor( twoPointManager.GetEnd(), true );
getViewControls()->WarpMouseCursor( twoPointMgr.GetEnd(), true );
if( PICKED_ITEMS_LIST* undo = m_frame->PopCommandFromUndoList() )
{
@ -2094,11 +2061,11 @@ bool DRAWING_TOOL::drawShape( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
delete undo;
}
updateSegmentFromGeometryMgr( twoPointManager, graphic );
updateSegmentFromGeometryMgr( twoPointMgr, graphic );
m_view->Update( &preview );
m_view->Update( &twoPointAsst );
}
else if( graphic )
else
{
cleanup();
}
@ -2110,10 +2077,6 @@ bool DRAWING_TOOL::drawShape( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
m_view->Update( &preview );
frame()->SetMsgPanel( graphic );
}
else if( evt->IsAction( &ACTIONS::redo ) )
{
wxBell();
}
else if( graphic && evt->IsAction( &PCB_ACTIONS::decWidth ) )
{
if( (unsigned) m_stroke.GetWidth() > WIDTH_STEP )
@ -2131,7 +2094,8 @@ bool DRAWING_TOOL::drawShape( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
frame()->SetMsgPanel( graphic );
break;
}
else if( started && ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
else if( started && ( ZONE_FILLER_TOOL::IsZoneFillAction( evt )
|| evt->IsAction( &ACTIONS::redo ) ) )
{
wxBell();
}
@ -2273,7 +2237,7 @@ bool DRAWING_TOOL::drawArc( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
grid.BestSnapAnchor( m_controls->GetMousePosition(), graphic ), COORDS_PADDING );
m_controls->ForceCursorPosition( true, cursorPos );
if( evt->IsCancelInteractive() || evt->IsAction( &ACTIONS::undo ) )
if( evt->IsCancelInteractive() || ( started && evt->IsAction( &ACTIONS::undo ) ) )
{
cleanup();
@ -2406,18 +2370,26 @@ bool DRAWING_TOOL::drawArc( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
else if( evt->IsAction( &PCB_ACTIONS::incWidth ) )
{
m_stroke.SetWidth( m_stroke.GetWidth() + WIDTH_STEP );
graphic->SetStroke( m_stroke );
m_view->Update( &preview );
frame()->SetMsgPanel( graphic );
if( graphic )
{
graphic->SetStroke( m_stroke );
m_view->Update( &preview );
frame()->SetMsgPanel( graphic );
}
}
else if( evt->IsAction( &PCB_ACTIONS::decWidth ) )
{
if( (unsigned) m_stroke.GetWidth() > WIDTH_STEP )
{
m_stroke.SetWidth( m_stroke.GetWidth() - WIDTH_STEP );
graphic->SetStroke( m_stroke );
m_view->Update( &preview );
frame()->SetMsgPanel( graphic );
if( graphic )
{
graphic->SetStroke( m_stroke );
m_view->Update( &preview );
frame()->SetMsgPanel( graphic );
}
}
}
else if( evt->IsAction( &PCB_ACTIONS::arcPosture ) )
@ -2430,11 +2402,8 @@ bool DRAWING_TOOL::drawArc( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
m_view->Update( &arcAsst );
evt->SetPassEvent();
}
else if( started && ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
{
wxBell();
}
else if( evt->IsAction( &ACTIONS::redo ) )
else if( started && ( ZONE_FILLER_TOOL::IsZoneFillAction( evt )
|| evt->IsAction( &ACTIONS::redo ) ) )
{
wxBell();
}
@ -2602,7 +2571,7 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
if( evt->IsCancelInteractive() )
{
if( polyGeomMgr.IsPolygonInProgress() )
if( started )
{
cleanup();
}
@ -2616,7 +2585,7 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
}
else if( evt->IsActivate() )
{
if( polyGeomMgr.IsPolygonInProgress() )
if( started )
cleanup();
if( evt->IsPointEditor() )
@ -2686,9 +2655,9 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
}
}
}
else if( evt->IsAction( &PCB_ACTIONS::deleteLastPoint )
|| evt->IsAction( &ACTIONS::doDelete )
|| evt->IsAction( &ACTIONS::undo ) )
else if( started && ( evt->IsAction( &PCB_ACTIONS::deleteLastPoint )
|| evt->IsAction( &ACTIONS::doDelete )
|| evt->IsAction( &ACTIONS::undo ) ) )
{
if( std::optional<VECTOR2I> last = polyGeomMgr.DeleteLastCorner() )
{
@ -2697,21 +2666,22 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
m_controls->ForceCursorPosition( true, cursorPos );
polyGeomMgr.SetCursorPosition( cursorPos );
}
else if( polyGeomMgr.IsPolygonInProgress() )
else
{
cleanup();
}
}
else if( polyGeomMgr.IsPolygonInProgress()
&& ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) )
else if( started && ( evt->IsMotion()
|| evt->IsDrag( BUT_LEFT ) ) )
{
polyGeomMgr.SetCursorPosition( cursorPos );
}
else if( started && ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
else if( started && ( ZONE_FILLER_TOOL::IsZoneFillAction( evt )
|| evt->IsAction( &ACTIONS::redo ) ) )
{
wxBell();
}
else if( started&& evt->IsAction( &PCB_ACTIONS::properties ) )
else if( started && evt->IsAction( &PCB_ACTIONS::properties ) )
{
frame()->OnEditItemRequest( zoneTool.GetZone() );
zoneTool.OnGeometryChange( polyGeomMgr );
@ -2725,10 +2695,6 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
// m_view->Update( &zoneAsst );
evt->SetPassEvent();
}*/
else if( evt->IsAction( &ACTIONS::redo ) )
{
wxBell();
}
else
{
evt->SetPassEvent();

View File

@ -1209,8 +1209,7 @@ int EDIT_TOOL::ModifyLines( const TOOL_EVENT& aEvent )
if( !m_isFootprintEditor )
{
// If the item was "conjured up" it will be added later separately
if( std::find( lines_to_add.begin(), lines_to_add.end(), &aItem )
== lines_to_add.end() )
if( !alg::contains( lines_to_add, &aItem ) )
{
commit.Modify( &aItem );
items_to_select_on_success.push_back( &aItem );
@ -1270,17 +1269,11 @@ int EDIT_TOOL::ModifyLines( const TOOL_EVENT& aEvent )
{
// Didn't construct any mofication routine - could be an error or cancellation
if( !error_message.empty() )
{
frame()->ShowInfoBarMsg( error_message );
}
return 0;
}
// Only modify one parent in FP editor
if( m_isFootprintEditor )
commit.Modify( selection.Front() );
// Apply the tool to every line pair
alg::for_all_pairs( selection.begin(), selection.end(),
[&]( EDA_ITEM* a, EDA_ITEM* b )
@ -1478,7 +1471,7 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
{
for( EDA_ITEM* item : selection )
{
if( !item->IsNew() && !item->IsMoving() && ( !IsFootprintEditor() || commit->Empty() ) )
if( !item->IsNew() && !item->IsMoving() )
{
commit->Modify( item );
@ -1653,7 +1646,7 @@ int EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
if( !item->IsType( MirrorableItems ) )
continue;
if( !item->IsNew() && !item->IsMoving() && ( !IsFootprintEditor() || commit->Empty() ) )
if( !item->IsNew() && !item->IsMoving() )
commit->Modify( item );
// modify each object as necessary
@ -1765,8 +1758,7 @@ int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent )
{
if( BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( item ) )
{
if( !boardItem->IsNew() && !boardItem->IsMoving()
&& ( !IsFootprintEditor() || commit->Empty() ) )
if( !boardItem->IsNew() && !boardItem->IsMoving() )
{
commit->Modify( boardItem );
@ -1816,13 +1808,11 @@ void EDIT_TOOL::DeleteItems( const PCB_SELECTION& aItems, bool aIsCut )
for( EDA_ITEM* item : aItems )
{
BOARD_ITEM* board_item = dynamic_cast<BOARD_ITEM*>( item );
wxCHECK2( board_item, continue );
FOOTPRINT* parentFP = board_item->GetParentFootprint();
PCB_GROUP* parentGroup = board_item->GetParentGroup();
if( parentGroup )
if( PCB_GROUP* parentGroup = board_item->GetParentGroup() )
{
commit.Modify( parentGroup );
parentGroup->RemoveItem( board_item );
@ -2097,17 +2087,13 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent )
if( !frame()->GetPcbNewSettings()->m_Display.m_DisplayInvertYAxis )
rotation = -rotation;
// When editing footprints, all items have the same parent
if( IsFootprintEditor() )
commit.Modify( selection.Front() );
for( EDA_ITEM* item : selection )
{
BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( item );
wxCHECK2( boardItem, continue );
if( !boardItem->IsNew() && !IsFootprintEditor() )
if( !boardItem->IsNew() )
{
commit.Modify( boardItem );

View File

@ -87,7 +87,7 @@ int EDIT_TOOL::Swap( const TOOL_EVENT& aEvent )
// Save items, so changes can be undone
for( EDA_ITEM* item : selection )
{
if( !item->IsNew() && !item->IsMoving() && ( !IsFootprintEditor() || commit->Empty() ) )
if( !item->IsNew() && !item->IsMoving() )
{
commit->Modify( item );
@ -369,10 +369,7 @@ bool EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, BOARD_COMMIT* aCommit
for( EDA_ITEM* item : selection )
{
BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( item );
FOOTPRINT* footprint = dynamic_cast<FOOTPRINT*>( item );
if( boardItem )
if( BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( item ) )
{
if( !is_hover )
orig_items.push_back( boardItem );
@ -380,7 +377,7 @@ bool EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, BOARD_COMMIT* aCommit
sel_items.push_back( boardItem );
}
if( footprint )
if( FOOTPRINT* footprint = dynamic_cast<FOOTPRINT*>( item ) )
{
for( PAD* pad : footprint->Pads() )
sel_items.push_back( pad );
@ -569,8 +566,7 @@ bool EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, BOARD_COMMIT* aCommit
if( item->GetParent() && item->GetParent()->IsSelected() )
continue;
if( !item->IsNew() && !item->IsMoving()
&& ( !IsFootprintEditor() || aCommit->Empty() ) )
if( !item->IsNew() && !item->IsMoving() )
{
aCommit->Modify( item );
item->SetFlags( IS_MOVING );

View File

@ -532,10 +532,7 @@ int FOOTPRINT_EDITOR_CONTROL::ImportFootprint( const TOOL_EVENT& aEvent )
int FOOTPRINT_EDITOR_CONTROL::ExportFootprint( const TOOL_EVENT& aEvent )
{
LIB_ID fpID = m_frame->GetTreeFPID();
FOOTPRINT* fp = m_frame->GetBoard()->GetFirstFootprint();
if( fp )
if( FOOTPRINT* fp = m_frame->GetBoard()->GetFirstFootprint() )
m_frame->ExportFootprint( fp );
return 0;
@ -604,13 +601,12 @@ int FOOTPRINT_EDITOR_CONTROL::ToggleProperties( const TOOL_EVENT& aEvent )
int FOOTPRINT_EDITOR_CONTROL::Properties( const TOOL_EVENT& aEvent )
{
FOOTPRINT* footprint = m_frame->GetBoard()->GetFirstFootprint();
if( footprint )
if( FOOTPRINT* footprint = m_frame->GetBoard()->GetFirstFootprint() )
{
getEditFrame<FOOTPRINT_EDIT_FRAME>()->OnEditItemRequest( footprint );
m_frame->GetCanvas()->Refresh();
}
return 0;
}
@ -637,7 +633,6 @@ int FOOTPRINT_EDITOR_CONTROL::CheckFootprint( const TOOL_EVENT& aEvent )
if( !m_checkerDialog )
{
m_checkerDialog = new DIALOG_FOOTPRINT_CHECKER( m_frame );
m_checkerDialog->Show( true );
}
else // The dialog is just not visible (because the user has double clicked on an error item)

View File

@ -168,7 +168,7 @@ int GLOBAL_EDIT_TOOL::SwapLayers( const TOOL_EVENT& aEvent )
if( hasChanges )
{
frame()->OnModify();
m_commit->Push( wxT( "Layers moved" ) );
m_commit->Push( wxT( "Swap Layers" ) );
frame()->GetCanvas()->Refresh();
}

View File

@ -254,47 +254,32 @@ int GROUP_TOOL::Group( const TOOL_EVENT& aEvent )
if( m_isFootprintEditor )
{
FOOTPRINT* parentFootprint = board->GetFirstFootprint();
group = new PCB_GROUP( board->GetFirstFootprint() );
board->GetFirstFootprint()->Add( group );
}
else
{
group = new PCB_GROUP( board );
board->Add( group );
}
m_frame->SaveCopyInUndoList( parentFootprint, UNDO_REDO::CHANGED );
PICKED_ITEMS_LIST undoList;
undoList.PushItem( ITEM_PICKER( nullptr, group, UNDO_REDO::NEWITEM ) );
group = new PCB_GROUP( parentFootprint );
parentFootprint->Add( group );
for( EDA_ITEM* eda_item : selection )
for( EDA_ITEM* eda_item : selection )
{
if( BOARD_ITEM* item = dynamic_cast<BOARD_ITEM*>( eda_item ) )
{
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( eda_item );
if( item->IsLocked() )
lockGroup = true;
group->AddItem( item );
}
}
else
{
PICKED_ITEMS_LIST undoList;
group = new PCB_GROUP( board );
board->Add( group );
undoList.PushItem( ITEM_PICKER( nullptr, group, UNDO_REDO::NEWITEM ) );
for( EDA_ITEM* eda_item : selection )
{
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( eda_item );
if( item->IsLocked() )
lockGroup = true;
group->AddItem( static_cast<BOARD_ITEM*>( item ) );
undoList.PushItem( ITEM_PICKER( nullptr, item, UNDO_REDO::REGROUP ) );
}
m_frame->SaveCopyInUndoList( undoList, UNDO_REDO::REGROUP );
}
m_frame->SaveCopyInUndoList( undoList, UNDO_REDO::REGROUP );
if( lockGroup )
group->SetLocked( true );
@ -326,33 +311,23 @@ int GROUP_TOOL::Ungroup( const TOOL_EVENT& aEvent )
if( group )
{
if( m_isFootprintEditor )
PICKED_ITEMS_LIST undoList;
for( BOARD_ITEM* member : group->GetItems() )
{
FOOTPRINT* parentFootprint = board->GetFirstFootprint();
m_frame->SaveCopyInUndoList( parentFootprint, UNDO_REDO::CHANGED );
group->RemoveAll();
parentFootprint->Remove( group );
undoList.PushItem( ITEM_PICKER( nullptr, member, UNDO_REDO::UNGROUP ) );
members.push_back( member );
}
group->RemoveAll();
if( m_isFootprintEditor )
board->GetFirstFootprint()->Remove( group );
else
{
PICKED_ITEMS_LIST undoList;
for( BOARD_ITEM* member : group->GetItems() )
{
undoList.PushItem( ITEM_PICKER( nullptr, member, UNDO_REDO::UNGROUP ) );
members.push_back( member );
}
group->RemoveAll();
board->Remove( group );
undoList.PushItem( ITEM_PICKER( nullptr, group, UNDO_REDO::DELETED ) );
m_frame->SaveCopyInUndoList( undoList, UNDO_REDO::UNGROUP );
}
undoList.PushItem( ITEM_PICKER( nullptr, group, UNDO_REDO::DELETED ) );
m_frame->SaveCopyInUndoList( undoList, UNDO_REDO::UNGROUP );
group->SetSelected();
}
}

View File

@ -194,7 +194,6 @@ int PCB_CONTROL::ViaDisplayMode( const TOOL_EVENT& aEvent )
}
canvas()->Refresh();
return 0;
}
@ -301,7 +300,6 @@ int PCB_CONTROL::HighContrastMode( const TOOL_EVENT& aEvent )
: HIGH_CONTRAST_MODE::NORMAL;
m_frame->SetDisplayOptions( opts );
return 0;
}
@ -320,7 +318,6 @@ int PCB_CONTROL::HighContrastModeCycle( const TOOL_EVENT& aEvent )
m_frame->SetDisplayOptions( opts );
m_toolMgr->PostEvent( EVENTS::ContrastModeChangedByKeyEvent );
return 0;
}
@ -343,8 +340,10 @@ int PCB_CONTROL::ContrastModeFeedback( const TOOL_EVENT& aEvent )
HOTKEY_CYCLE_POPUP* popup = m_frame->GetHotkeyPopup();
if( popup )
{
popup->Popup( _( "Inactive Layer Display" ), labels,
static_cast<int>( opts.m_ContrastModeDisplay ) );
}
return 0;
}
@ -362,7 +361,6 @@ int PCB_CONTROL::NetColorModeCycle( const TOOL_EVENT& aEvent )
}
m_frame->SetDisplayOptions( opts );
return 0;
}

View File

@ -166,7 +166,6 @@ size_t ALIGN_DISTRIBUTE_TOOL::GetSelections( std::vector<std::pair<BOARD_ITEM*,
for( EDA_ITEM* item : selection )
{
BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( item );
wxCHECK2( boardItem, continue );
// We do not lock items in the footprint editor
@ -175,13 +174,9 @@ size_t ALIGN_DISTRIBUTE_TOOL::GetSelections( std::vector<std::pair<BOARD_ITEM*,
// Locking a pad but not the footprint means that we align the footprint using
// the pad position. So we test for footprint locking here
if( boardItem->Type() == PCB_PAD_T && !boardItem->GetParent()->IsLocked() )
{
itemsToAlign.push_back( boardItem );
}
else
{
lockedItems.push_back( boardItem );
}
}
else
itemsToAlign.push_back( boardItem );
@ -202,9 +197,9 @@ int ALIGN_DISTRIBUTE_TOOL::AlignTop( const TOOL_EVENT& aEvent )
std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
if( !GetSelections( itemsToAlign, locked_items,
[]( const std::pair<BOARD_ITEM*, BOX2I> left, const std::pair<BOARD_ITEM*, BOX2I> right)
[]( const std::pair<BOARD_ITEM*, BOX2I>& lhs, const std::pair<BOARD_ITEM*, BOX2I>& rhs )
{
return ( left.second.GetTop() < right.second.GetTop() );
return ( lhs.second.GetTop() < rhs.second.GetTop() );
} ) )
{
return 0;
@ -235,8 +230,7 @@ int ALIGN_DISTRIBUTE_TOOL::AlignTop( const TOOL_EVENT& aEvent )
item->Move( VECTOR2I( 0, difference ) );
}
commit.Push( _( "Align to top" ) );
commit.Push( _( "Align to Top" ) );
return 0;
}
@ -247,9 +241,9 @@ int ALIGN_DISTRIBUTE_TOOL::AlignBottom( const TOOL_EVENT& aEvent )
std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
if( !GetSelections( itemsToAlign, locked_items,
[]( const std::pair<BOARD_ITEM*, BOX2I> left, const std::pair<BOARD_ITEM*, BOX2I> right)
[]( const std::pair<BOARD_ITEM*, BOX2I>& lhs, const std::pair<BOARD_ITEM*, BOX2I>& rhs)
{
return ( left.second.GetBottom() > right.second.GetBottom() );
return ( lhs.second.GetBottom() > rhs.second.GetBottom() );
} ) )
{
return 0;
@ -280,8 +274,7 @@ int ALIGN_DISTRIBUTE_TOOL::AlignBottom( const TOOL_EVENT& aEvent )
item->Move( VECTOR2I( 0, difference ) );
}
commit.Push( _( "Align to bottom" ) );
commit.Push( _( "Align to Bottom" ) );
return 0;
}
@ -291,13 +284,9 @@ int ALIGN_DISTRIBUTE_TOOL::AlignLeft( const TOOL_EVENT& aEvent )
// Because this tool uses bounding boxes and they aren't mirrored even when
// the view is mirrored, we need to call the other one if mirrored.
if( getView()->IsMirroredX() )
{
return doAlignRight();
}
else
{
return doAlignLeft();
}
}
@ -307,9 +296,9 @@ int ALIGN_DISTRIBUTE_TOOL::doAlignLeft()
std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
if( !GetSelections( itemsToAlign, locked_items,
[]( const std::pair<BOARD_ITEM*, BOX2I> left, const std::pair<BOARD_ITEM*, BOX2I> right)
[]( const std::pair<BOARD_ITEM*, BOX2I>& lhs, const std::pair<BOARD_ITEM*, BOX2I>& rhs )
{
return ( left.second.GetLeft() < right.second.GetLeft() );
return ( lhs.second.GetLeft() < rhs.second.GetLeft() );
} ) )
{
return 0;
@ -340,8 +329,7 @@ int ALIGN_DISTRIBUTE_TOOL::doAlignLeft()
item->Move( VECTOR2I( difference, 0 ) );
}
commit.Push( _( "Align to left" ) );
commit.Push( _( "Align to Left" ) );
return 0;
}
@ -351,13 +339,9 @@ int ALIGN_DISTRIBUTE_TOOL::AlignRight( const TOOL_EVENT& aEvent )
// Because this tool uses bounding boxes and they aren't mirrored even when
// the view is mirrored, we need to call the other one if mirrored.
if( getView()->IsMirroredX() )
{
return doAlignLeft();
}
else
{
return doAlignRight();
}
}
@ -367,9 +351,9 @@ int ALIGN_DISTRIBUTE_TOOL::doAlignRight()
std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
if( !GetSelections( itemsToAlign, locked_items,
[]( const std::pair<BOARD_ITEM*, BOX2I> left, const std::pair<BOARD_ITEM*, BOX2I> right)
[]( const std::pair<BOARD_ITEM*, BOX2I>& lhs, const std::pair<BOARD_ITEM*, BOX2I>& rhs )
{
return ( left.second.GetRight() > right.second.GetRight() );
return ( lhs.second.GetRight() > rhs.second.GetRight() );
} ) )
{
return 0;
@ -400,8 +384,7 @@ int ALIGN_DISTRIBUTE_TOOL::doAlignRight()
item->Move( VECTOR2I( difference, 0 ) );
}
commit.Push( _( "Align to right" ) );
commit.Push( _( "Align to Right" ) );
return 0;
}
@ -412,9 +395,9 @@ int ALIGN_DISTRIBUTE_TOOL::AlignCenterX( const TOOL_EVENT& aEvent )
std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
if( !GetSelections( itemsToAlign, locked_items,
[]( const std::pair<BOARD_ITEM*, BOX2I> left, const std::pair<BOARD_ITEM*, BOX2I> right)
[]( const std::pair<BOARD_ITEM*, BOX2I>& lhs, const std::pair<BOARD_ITEM*, BOX2I>& rhs )
{
return ( left.second.Centre().x < right.second.Centre().x );
return ( lhs.second.Centre().x < rhs.second.Centre().x );
} ) )
{
return 0;
@ -445,8 +428,7 @@ int ALIGN_DISTRIBUTE_TOOL::AlignCenterX( const TOOL_EVENT& aEvent )
item->Move( VECTOR2I( difference, 0 ) );
}
commit.Push( _( "Align to middle" ) );
commit.Push( _( "Align to Middle" ) );
return 0;
}
@ -457,9 +439,9 @@ int ALIGN_DISTRIBUTE_TOOL::AlignCenterY( const TOOL_EVENT& aEvent )
std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
if( !GetSelections( itemsToAlign, locked_items,
[]( const std::pair<BOARD_ITEM*, BOX2I> left, const std::pair<BOARD_ITEM*, BOX2I> right)
[]( const std::pair<BOARD_ITEM*, BOX2I>& lhs, const std::pair<BOARD_ITEM*, BOX2I>& rhs )
{
return ( left.second.Centre().y < right.second.Centre().y );
return ( lhs.second.Centre().y < rhs.second.Centre().y );
} ) )
{
return 0;
@ -490,8 +472,7 @@ int ALIGN_DISTRIBUTE_TOOL::AlignCenterY( const TOOL_EVENT& aEvent )
item->Move( VECTOR2I( 0, difference ) );
}
commit.Push( _( "Align to center" ) );
commit.Push( _( "Align to Center" ) );
return 0;
}
@ -520,10 +501,9 @@ int ALIGN_DISTRIBUTE_TOOL::DistributeHorizontally( const TOOL_EVENT& aEvent )
// find the last item by reverse sorting
std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
[] ( const std::pair<BOARD_ITEM*, BOX2I> left,
const std::pair<BOARD_ITEM*, BOX2I> right)
[]( const std::pair<BOARD_ITEM*, BOX2I>& lhs, const std::pair<BOARD_ITEM*, BOX2I>& rhs )
{
return ( left.second.GetRight() > right.second.GetRight() );
return ( lhs.second.GetRight() > rhs.second.GetRight() );
} );
BOARD_ITEM* lastItem = itemsToDistribute.begin()->first;
@ -531,10 +511,9 @@ int ALIGN_DISTRIBUTE_TOOL::DistributeHorizontally( const TOOL_EVENT& aEvent )
// sort to get starting order
std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
[] ( const std::pair<BOARD_ITEM*, BOX2I> left,
const std::pair<BOARD_ITEM*, BOX2I> right)
[]( const std::pair<BOARD_ITEM*, BOX2I>& lhs, const std::pair<BOARD_ITEM*, BOX2I>& rhs )
{
return ( left.second.GetX() < right.second.GetX() );
return ( lhs.second.GetX() < rhs.second.GetX() );
} );
const int minX = itemsToDistribute.begin()->second.GetX();
@ -555,8 +534,7 @@ int ALIGN_DISTRIBUTE_TOOL::DistributeHorizontally( const TOOL_EVENT& aEvent )
doDistributeGapsHorizontally( itemsToDistribute, commit, lastItem, totalGap );
}
commit.Push( _( "Distribute horizontally" ) );
commit.Push( _( "Distribute Horizontally" ) );
return 0;
}
@ -596,13 +574,12 @@ void ALIGN_DISTRIBUTE_TOOL::doDistributeCentersHorizontally( std::vector<std::pa
BOARD_COMMIT& aCommit ) const
{
std::sort( aItems.begin(), aItems.end(),
[] ( const std::pair<BOARD_ITEM*, BOX2I> left, const std::pair<BOARD_ITEM*, BOX2I> right)
[]( const std::pair<BOARD_ITEM*, BOX2I>& lhs, const std::pair<BOARD_ITEM*, BOX2I>& rhs )
{
return ( left.second.Centre().x < right.second.Centre().x );
return ( lhs.second.Centre().x < rhs.second.Centre().x );
} );
const int totalGap = ( aItems.end() - 1 )->second.Centre().x
- aItems.begin()->second.Centre().x;
const int totalGap = ( aItems.end()-1 )->second.Centre().x - aItems.begin()->second.Centre().x;
const int itemGap = totalGap / ( aItems.size() - 1 );
int targetX = aItems.begin()->second.Centre().x;
@ -649,20 +626,20 @@ int ALIGN_DISTRIBUTE_TOOL::DistributeVertically( const TOOL_EVENT& aEvent )
// find the last item by reverse sorting
std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
[] ( const std::pair<BOARD_ITEM*, BOX2I> left, const std::pair<BOARD_ITEM*, BOX2I> right)
{
return ( left.second.GetBottom() > right.second.GetBottom() );
} );
[]( const std::pair<BOARD_ITEM*, BOX2I>& lhs, const std::pair<BOARD_ITEM*, BOX2I>& rhs )
{
return ( lhs.second.GetBottom() > rhs.second.GetBottom() );
} );
BOARD_ITEM* lastItem = itemsToDistribute.begin()->first;
const int maxBottom = itemsToDistribute.begin()->second.GetBottom();
// sort to get starting order
std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
[] ( const std::pair<BOARD_ITEM*, BOX2I> left, const std::pair<BOARD_ITEM*, BOX2I> right)
{
return ( left.second.Centre().y < right.second.Centre().y );
} );
[]( const std::pair<BOARD_ITEM*, BOX2I>& lhs, const std::pair<BOARD_ITEM*, BOX2I>& rhs )
{
return ( lhs.second.Centre().y < rhs.second.Centre().y );
} );
int minY = itemsToDistribute.begin()->second.GetY();
int totalGap = maxBottom - minY;
@ -682,8 +659,7 @@ int ALIGN_DISTRIBUTE_TOOL::DistributeVertically( const TOOL_EVENT& aEvent )
doDistributeGapsVertically( itemsToDistribute, commit, lastItem, totalGap );
}
commit.Push( _( "Distribute vertically" ) );
commit.Push( _( "Distribute Vertically" ) );
return 0;
}
@ -723,9 +699,9 @@ void ALIGN_DISTRIBUTE_TOOL::doDistributeCentersVertically( std::vector<std::pair
BOARD_COMMIT& aCommit ) const
{
std::sort( aItems.begin(), aItems.end(),
[] ( const std::pair<BOARD_ITEM*, BOX2I> left, const std::pair<BOARD_ITEM*, BOX2I> right)
[] ( const std::pair<BOARD_ITEM*, BOX2I>& lhs, const std::pair<BOARD_ITEM*, BOX2I>& rhs)
{
return ( left.second.Centre().y < right.second.Centre().y );
return ( lhs.second.Centre().y < rhs.second.Centre().y );
} );
const int totalGap = ( aItems.end() - 1 )->second.Centre().y

View File

@ -203,7 +203,7 @@ void ZONE_CREATE_HELPER::performZoneCutout( ZONE& aZone, const ZONE& aCutout )
// TODO Refill zones when KiCad supports auto re-fill
commit.Push( _( "Add a zone cutout" ) );
commit.Push( _( "Add Zone Cutout" ) );
// Select the new zone and set it as the source for the next cutout
if( newZones.empty() )
@ -215,7 +215,6 @@ void ZONE_CREATE_HELPER::performZoneCutout( ZONE& aZone, const ZONE& aCutout )
m_params.m_sourceZone = newZones[0];
toolMgr->RunAction<EDA_ITEM*>( PCB_ACTIONS::selectItem, newZones[0] );
}
}
@ -238,17 +237,16 @@ void ZONE_CREATE_HELPER::commitZone( std::unique_ptr<ZONE> aZone )
commit.Add( aZone.get() );
commit.Push( _( "Add a zone" ) );
m_tool.GetManager()->RunAction<EDA_ITEM*>( PCB_ACTIONS::selectItem,
aZone.release() );
m_tool.GetManager()->RunAction<EDA_ITEM*>( PCB_ACTIONS::selectItem, aZone.release() );
break;
}
case ZONE_MODE::GRAPHIC_POLYGON:
{
BOARD_COMMIT commit( &m_tool );
BOARD* board = m_tool.getModel<BOARD>();
PCB_LAYER_ID layer = m_params.m_layer;
PCB_SHAPE* poly = new PCB_SHAPE( m_tool.m_frame->GetModel() );
BOARD_COMMIT commit( &m_tool );
BOARD* board = m_tool.getModel<BOARD>();
PCB_LAYER_ID layer = m_params.m_layer;
PCB_SHAPE* poly = new PCB_SHAPE( m_tool.m_frame->GetModel() );
poly->SetShape( SHAPE_T::POLY );
@ -265,8 +263,7 @@ void ZONE_CREATE_HELPER::commitZone( std::unique_ptr<ZONE> aZone )
commit.Add( poly );
m_tool.GetManager()->RunAction<EDA_ITEM*>( PCB_ACTIONS::selectItem, poly );
commit.Push( _( "Add a graphical polygon" ) );
commit.Push( _( "Add Polygon" ) );
break;
}
}

View File

@ -29,7 +29,6 @@
using namespace std::placeholders;
#include <macros.h>
#include <pcb_edit_frame.h>
#include <board.h>
#include <pcb_track.h>
#include <pcb_group.h>
#include <pcb_target.h>
@ -95,126 +94,14 @@ using namespace std::placeholders;
*/
/**
* Test if aItem exists somewhere in undo/redo lists of items. Used by PutDataInPreviousState
* to be sure an item was not deleted since an undo or redo.
*
* This could be possible:
* - if a call to SaveCopyInUndoList was forgotten in Pcbnew
* - in zones outlines, when a change in one zone merges this zone with an other
* Before using this function to test existence of items, it must be called with aItem = NULL to
* prepare the list.
*
* @param aPcb is the board to test.
* @param aItem is the item to find or NULL to build the list of existing items.
*/
static bool TestForExistingItem( BOARD* aPcb, BOARD_ITEM* aItem )
{
for( PCB_TRACK* item : aPcb->Tracks() )
{
if( aItem == item)
return true;
}
for( FOOTPRINT* item : aPcb->Footprints() )
{
if( aItem == item )
return true;
}
for( BOARD_ITEM* item : aPcb->Drawings() )
{
if( aItem == item )
return true;
}
for( ZONE* item : aPcb->Zones() )
{
if( aItem == item )
return true;
}
for( const NETINFO_ITEM* item : aPcb->GetNetInfo() )
{
if( aItem == item )
return true;
}
for( PCB_GROUP* item : aPcb->Groups() )
{
if( aItem == item )
return true;
}
return false;
}
void PCB_BASE_EDIT_FRAME::saveCopyInUndoList( PICKED_ITEMS_LIST* commandToUndo,
const PICKED_ITEMS_LIST& aItemsList,
UNDO_REDO aCommandType )
{
int preExisting = commandToUndo->GetCount();
// First, filter unnecessary stuff from the list (i.e. for multiple pads / labels modified),
// take the first occurrence of the footprint (we save copies of footprints when one of its
// subitems is changed).
for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
{
ITEM_PICKER curr_picker = aItemsList.GetItemWrapper(ii);
BOARD_ITEM* item = dynamic_cast<BOARD_ITEM*>( aItemsList.GetPickedItem( ii ) );
// For items belonging to footprints, we need to save state of the parent footprint
if( item && item->GetParent() && item->GetParent()->Type() == PCB_FOOTPRINT_T )
{
item = item->GetParent();
// Check if the parent footprint has already been saved in another entry
bool found = false;
for( unsigned j = 0; j < commandToUndo->GetCount(); j++ )
{
if( commandToUndo->GetPickedItem( j ) == item
&& commandToUndo->GetPickedItemStatus( j ) == UNDO_REDO::CHANGED )
{
found = true;
break;
}
}
if( !found )
{
// Create a clean copy of the parent footprint
FOOTPRINT* orig = static_cast<FOOTPRINT*>( item );
FOOTPRINT* clone = new FOOTPRINT( *orig );
clone->SetParent( GetBoard() );
clone->SetParentGroup( nullptr );
// Clear current flags (which can be temporary set by a current edit command)
for( BOARD_ITEM* child : clone->GraphicalItems() )
child->ClearEditFlags();
for( PAD* pad : clone->Pads() )
pad->ClearEditFlags();
clone->Reference().ClearEditFlags();
clone->Value().ClearEditFlags();
ITEM_PICKER picker( nullptr, item, UNDO_REDO::CHANGED );
picker.SetLink( clone );
commandToUndo->PushItem( picker );
}
else
{
continue;
}
}
else
{
// Normal case: all other BOARD_ITEMs, are simply copied to the new list
commandToUndo->PushItem( curr_picker );
}
}
commandToUndo->PushItem( aItemsList.GetItemWrapper(ii) );
for( unsigned ii = preExisting; ii < commandToUndo->GetCount(); ii++ )
{
@ -258,8 +145,7 @@ void PCB_BASE_EDIT_FRAME::saveCopyInUndoList( PICKED_ITEMS_LIST* commandToUndo,
break;
default:
wxFAIL_MSG( wxString::Format( wxT( "SaveCopyInUndoList() error (unknown code %X)" ),
command ) );
wxFAIL_MSG( wxString::Format( wxT( "Unrecognized undo command: %X" ), command ) );
break;
}
}
@ -412,7 +298,7 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
&& status != UNDO_REDO::GRIDORIGIN // origin markers never on board
&& status != UNDO_REDO::PAGESETTINGS ) // nor are page settings proxy items
{
if( !TestForExistingItem( GetBoard(), (BOARD_ITEM*) eda_item ) )
if( GetBoard()->GetItem( eda_item->m_Uuid ) == DELETED_BOARD_ITEM::GetInstance() )
{
// Checking if it ever happens
wxASSERT_MSG( false, wxT( "Item in the undo buffer does not exist" ) );