Upgrade many editing actions to SCHEMATIC_COMMIT.

This commit is contained in:
Jeff Young 2023-06-09 17:24:49 +01:00
parent 73b653c276
commit e698156975
28 changed files with 504 additions and 554 deletions

View File

@ -192,15 +192,15 @@ std::unordered_set<SCH_SYMBOL*> getInferredSymbols( const EE_SELECTION& aSelecti
} }
void SCH_EDIT_FRAME::AnnotateSymbols( ANNOTATE_SCOPE_T aAnnotateScope, void SCH_EDIT_FRAME::AnnotateSymbols( SCHEMATIC_COMMIT* aCommit,
ANNOTATE_SCOPE_T aAnnotateScope,
ANNOTATE_ORDER_T aSortOption, ANNOTATE_ORDER_T aSortOption,
ANNOTATE_ALGO_T aAlgoOption, ANNOTATE_ALGO_T aAlgoOption,
bool aRecursive, bool aRecursive,
int aStartNumber, int aStartNumber,
bool aResetAnnotation, bool aResetAnnotation,
bool aRepairTimestamps, bool aRepairTimestamps,
REPORTER& aReporter, REPORTER& aReporter )
bool appendUndo )
{ {
EE_SELECTION_TOOL* selTool = m_toolManager->GetTool<EE_SELECTION_TOOL>(); EE_SELECTION_TOOL* selTool = m_toolManager->GetTool<EE_SELECTION_TOOL>();
EE_SELECTION& selection = selTool->GetSelection(); EE_SELECTION& selection = selTool->GetSelection();
@ -354,8 +354,7 @@ void SCH_EDIT_FRAME::AnnotateSymbols( ANNOTATE_SCOPE_T aAnnotateScope,
SCH_SYMBOL* symbol = ref.GetSymbol(); SCH_SYMBOL* symbol = ref.GetSymbol();
SCH_SHEET_PATH* sheet = &ref.GetSheetPath(); SCH_SHEET_PATH* sheet = &ref.GetSheetPath();
SaveCopyInUndoList( sheet->LastScreen(), symbol, UNDO_REDO::CHANGED, appendUndo ); aCommit->Modify( symbol, sheet->LastScreen() );
appendUndo = true;
ref.Annotate(); ref.Annotate();
KIID_PATH full_uuid = sheet->Path(); KIID_PATH full_uuid = sheet->Path();

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2004 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr * Copyright (C) 2004 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr
* Copyright (C) 2004-2022 KiCad Developers, see change_log.txt for contributors. * Copyright (C) 2004-2023 KiCad Developers, see change_log.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -31,6 +31,7 @@
#include <sch_no_connect.h> #include <sch_no_connect.h>
#include <sch_screen.h> #include <sch_screen.h>
#include <sch_view.h> #include <sch_view.h>
#include <schematic_commit.h>
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
#include <tools/ee_actions.h> #include <tools/ee_actions.h>
#include <tools/ee_selection_tool.h> #include <tools/ee_selection_tool.h>
@ -49,7 +50,8 @@ void SCH_EDIT_FRAME::TestDanglingEnds()
} }
bool SCH_EDIT_FRAME::TrimWire( const VECTOR2I& aStart, const VECTOR2I& aEnd ) bool SCH_EDIT_FRAME::TrimWire( SCHEMATIC_COMMIT* aCommit, const VECTOR2I& aStart,
const VECTOR2I& aEnd )
{ {
if( aStart == aEnd ) if( aStart == aEnd )
return false; return false;
@ -92,20 +94,20 @@ bool SCH_EDIT_FRAME::TrimWire( const VECTOR2I& aStart, const VECTOR2I& aEnd )
// Step 1: break the segment on one end. // Step 1: break the segment on one end.
// Ensure that *line points to the segment containing aEnd // Ensure that *line points to the segment containing aEnd
SCH_LINE* new_line; SCH_LINE* new_line;
BreakSegment( line, aStart, &new_line ); BreakSegment( aCommit, line, aStart, &new_line, screen );
if( IsPointOnSegment( new_line->GetStartPoint(), new_line->GetEndPoint(), aEnd ) ) if( IsPointOnSegment( new_line->GetStartPoint(), new_line->GetEndPoint(), aEnd ) )
line = new_line; line = new_line;
// Step 2: break the remaining segment. // Step 2: break the remaining segment.
// Ensure that *line _also_ contains aStart. This is our overlapping segment // Ensure that *line _also_ contains aStart. This is our overlapping segment
BreakSegment( line, aEnd, &new_line ); BreakSegment( aCommit, line, aEnd, &new_line, screen );
if( IsPointOnSegment( new_line->GetStartPoint(), new_line->GetEndPoint(), aStart ) ) if( IsPointOnSegment( new_line->GetStartPoint(), new_line->GetEndPoint(), aStart ) )
line = new_line; line = new_line;
SaveCopyInUndoList( screen, line, UNDO_REDO::DELETED, true );
RemoveFromScreen( line, screen ); RemoveFromScreen( line, screen );
aCommit->Removed( line, screen );
return true; return true;
} }
@ -114,11 +116,9 @@ bool SCH_EDIT_FRAME::TrimWire( const VECTOR2I& aStart, const VECTOR2I& aEnd )
} }
bool SCH_EDIT_FRAME::SchematicCleanUp( SCH_SCREEN* aScreen ) void SCH_EDIT_FRAME::SchematicCleanUp( SCHEMATIC_COMMIT* aCommit, SCH_SCREEN* aScreen )
{ {
PICKED_ITEMS_LIST itemList;
EE_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<EE_SELECTION_TOOL>(); EE_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<EE_SELECTION_TOOL>();
std::vector<SCH_ITEM*> deletedItems;
std::vector<SCH_LINE*> lines; std::vector<SCH_LINE*> lines;
std::vector<SCH_JUNCTION*> junctions; std::vector<SCH_JUNCTION*> junctions;
std::vector<SCH_NO_CONNECT*> ncs; std::vector<SCH_NO_CONNECT*> ncs;
@ -134,12 +134,16 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( SCH_SCREEN* aScreen )
if( !( aItem->GetFlags() & STRUCT_DELETED ) ) if( !( aItem->GetFlags() & STRUCT_DELETED ) )
{ {
aItem->SetFlags( STRUCT_DELETED ); aItem->SetFlags( STRUCT_DELETED );
itemList.PushItem( ITEM_PICKER( aScreen, aItem, UNDO_REDO::DELETED ) );
deletedItems.push_back( aItem ); if( aItem->IsSelected() )
selectionTool->RemoveItemFromSel( aItem, true /*quiet mode*/ );
RemoveFromScreen( aItem, aScreen );
aCommit->Removed( aItem, aScreen );
} }
}; };
BreakSegmentsOnJunctions( aScreen ); BreakSegmentsOnJunctions( aCommit, aScreen );
for( SCH_ITEM* item : aScreen->Items().OfType( SCH_JUNCTION_T ) ) for( SCH_ITEM* item : aScreen->Items().OfType( SCH_JUNCTION_T ) )
{ {
@ -150,9 +154,7 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( SCH_SCREEN* aScreen )
} }
for( SCH_ITEM* item : aScreen->Items().OfType( SCH_NO_CONNECT_T ) ) for( SCH_ITEM* item : aScreen->Items().OfType( SCH_NO_CONNECT_T ) )
{
ncs.push_back( static_cast<SCH_NO_CONNECT*>( item ) ); ncs.push_back( static_cast<SCH_NO_CONNECT*>( item ) );
}
alg::for_all_pairs( junctions.begin(), junctions.end(), alg::for_all_pairs( junctions.begin(), junctions.end(),
[&]( SCH_JUNCTION* aFirst, SCH_JUNCTION* aSecond ) [&]( SCH_JUNCTION* aFirst, SCH_JUNCTION* aSecond )
@ -237,9 +239,9 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( SCH_SCREEN* aScreen )
{ {
remove_item( firstLine ); remove_item( firstLine );
remove_item( secondLine ); remove_item( secondLine );
itemList.PushItem( ITEM_PICKER( aScreen, mergedLine, UNDO_REDO::NEWITEM ) );
AddToScreen( mergedLine, aScreen ); AddToScreen( mergedLine, aScreen );
aCommit->Added( mergedLine, aScreen );
if( firstLine->IsSelected() || secondLine->IsSelected() ) if( firstLine->IsSelected() || secondLine->IsSelected() )
selectionTool->AddItemToSel( mergedLine, true /*quiet mode*/ ); selectionTool->AddItemToSel( mergedLine, true /*quiet mode*/ );
@ -249,55 +251,38 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( SCH_SCREEN* aScreen )
} }
} }
} }
for( SCH_ITEM* item : deletedItems )
{
if( item->IsSelected() )
selectionTool->RemoveItemFromSel( item, true /*quiet mode*/ );
RemoveFromScreen( item, aScreen );
}
if( itemList.GetCount() )
SaveCopyInUndoList( itemList, UNDO_REDO::DELETED, true );
return itemList.GetCount() > 0;
} }
void SCH_EDIT_FRAME::BreakSegment( SCH_LINE* aSegment, const VECTOR2I& aPoint, void SCH_EDIT_FRAME::BreakSegment( SCHEMATIC_COMMIT* aCommit, SCH_LINE* aSegment,
SCH_LINE** aNewSegment, SCH_SCREEN* aScreen ) const VECTOR2I& aPoint, SCH_LINE** aNewSegment,
SCH_SCREEN* aScreen )
{ {
if( aScreen == nullptr )
aScreen = GetScreen();
// Save the copy of aSegment before breaking it // Save the copy of aSegment before breaking it
SaveCopyInUndoList( aScreen, aSegment, UNDO_REDO::CHANGED, true ); aCommit->Modify( aSegment, aScreen );
SCH_LINE* newSegment = aSegment->BreakAt( aPoint ); SCH_LINE* newSegment = aSegment->BreakAt( aPoint );
aSegment->SetFlags( IS_CHANGED | IS_BROKEN ); aSegment->SetFlags( IS_CHANGED | IS_BROKEN );
newSegment->SetFlags( IS_NEW | IS_BROKEN ); newSegment->SetFlags( IS_NEW | IS_BROKEN );
AddToScreen( newSegment, aScreen ); AddToScreen( newSegment, aScreen );
aCommit->Added( newSegment, aScreen );
SaveCopyInUndoList( aScreen, newSegment, UNDO_REDO::NEWITEM, true );
UpdateItem( aSegment, false, true ); UpdateItem( aSegment, false, true );
if( aNewSegment ) *aNewSegment = newSegment;
*aNewSegment = newSegment;
} }
bool SCH_EDIT_FRAME::BreakSegments( const VECTOR2I& aPoint, SCH_SCREEN* aScreen ) bool SCH_EDIT_FRAME::BreakSegments( SCHEMATIC_COMMIT* aCommit, const VECTOR2I& aPoint,
SCH_SCREEN* aScreen )
{ {
if( aScreen == nullptr ) bool brokenSegments = false;
aScreen = GetScreen(); SCH_LINE* new_line;
bool brokenSegments = false;
for( SCH_LINE* wire : aScreen->GetBusesAndWires( aPoint, true ) ) for( SCH_LINE* wire : aScreen->GetBusesAndWires( aPoint, true ) )
{ {
BreakSegment( wire, aPoint, nullptr, aScreen ); BreakSegment( aCommit, wire, aPoint, &new_line, aScreen );
brokenSegments = true; brokenSegments = true;
} }
@ -305,11 +290,8 @@ bool SCH_EDIT_FRAME::BreakSegments( const VECTOR2I& aPoint, SCH_SCREEN* aScreen
} }
bool SCH_EDIT_FRAME::BreakSegmentsOnJunctions( SCH_SCREEN* aScreen ) bool SCH_EDIT_FRAME::BreakSegmentsOnJunctions( SCHEMATIC_COMMIT* aCommit, SCH_SCREEN* aScreen )
{ {
if( aScreen == nullptr )
aScreen = GetScreen();
bool brokenSegments = false; bool brokenSegments = false;
std::set<VECTOR2I> point_set; std::set<VECTOR2I> point_set;
@ -326,7 +308,7 @@ bool SCH_EDIT_FRAME::BreakSegmentsOnJunctions( SCH_SCREEN* aScreen )
for( const VECTOR2I& pt : point_set ) for( const VECTOR2I& pt : point_set )
{ {
BreakSegments( pt, aScreen ); BreakSegments( aCommit, pt, aScreen );
brokenSegments = true; brokenSegments = true;
} }
@ -334,21 +316,15 @@ bool SCH_EDIT_FRAME::BreakSegmentsOnJunctions( SCH_SCREEN* aScreen )
} }
void SCH_EDIT_FRAME::DeleteJunction( SCH_ITEM* aJunction, bool aAppend ) void SCH_EDIT_FRAME::DeleteJunction( SCHEMATIC_COMMIT* aCommit, SCH_ITEM* aJunction )
{ {
SCH_SCREEN* screen = GetScreen(); SCH_SCREEN* screen = GetScreen();
PICKED_ITEMS_LIST undoList; PICKED_ITEMS_LIST undoList;
EE_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<EE_SELECTION_TOOL>(); EE_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<EE_SELECTION_TOOL>();
auto remove_item = aJunction->SetFlags( STRUCT_DELETED );
[&]( SCH_ITEM* aItem ) -> void
{
aItem->SetFlags( STRUCT_DELETED );
undoList.PushItem( ITEM_PICKER( screen, aItem, UNDO_REDO::DELETED ) );
};
remove_item( aJunction );
RemoveFromScreen( aJunction, screen ); RemoveFromScreen( aJunction, screen );
aCommit->Removed( aJunction, screen );
/// Note that std::list or similar is required here as we may insert values in the /// Note that std::list or similar is required here as we may insert values in the
/// loop below. This will invalidate iterators in a std::vector or std::deque /// loop below. This will invalidate iterators in a std::vector or std::deque
@ -380,27 +356,25 @@ void SCH_EDIT_FRAME::DeleteJunction( SCH_ITEM* aJunction, bool aAppend )
if( firstLine->IsEndPoint( secondLine->GetStartPoint() ) if( firstLine->IsEndPoint( secondLine->GetStartPoint() )
&& firstLine->IsEndPoint( secondLine->GetEndPoint() ) ) && firstLine->IsEndPoint( secondLine->GetEndPoint() ) )
{ {
remove_item( firstLine ); firstLine->SetFlags( STRUCT_DELETED );
return; return;
} }
// Try to merge the remaining lines // Try to merge the remaining lines
if( SCH_LINE* line = secondLine->MergeOverlap( screen, firstLine, false ) ) if( SCH_LINE* new_line = secondLine->MergeOverlap( screen, firstLine, false ) )
{ {
remove_item( firstLine ); firstLine->SetFlags( STRUCT_DELETED );
remove_item( secondLine ); secondLine->SetFlags( STRUCT_DELETED );
undoList.PushItem( ITEM_PICKER( screen, line, UNDO_REDO::NEWITEM ) ); AddToScreen( new_line, screen );
AddToScreen( line, screen ); aCommit->Added( new_line, screen );
if( line->IsSelected() ) if( new_line->IsSelected() )
selectionTool->AddItemToSel( line, true /*quiet mode*/ ); selectionTool->AddItemToSel( new_line, true /*quiet mode*/ );
lines.push_back( line ); lines.push_back( new_line );
} }
} ); } );
SaveCopyInUndoList( undoList, UNDO_REDO::DELETED, aAppend );
for( SCH_LINE* line : lines ) for( SCH_LINE* line : lines )
{ {
if( line->GetEditFlags() & STRUCT_DELETED ) if( line->GetEditFlags() & STRUCT_DELETED )
@ -409,32 +383,21 @@ void SCH_EDIT_FRAME::DeleteJunction( SCH_ITEM* aJunction, bool aAppend )
selectionTool->RemoveItemFromSel( line, true /*quiet mode*/ ); selectionTool->RemoveItemFromSel( line, true /*quiet mode*/ );
RemoveFromScreen( line, screen ); RemoveFromScreen( line, screen );
aCommit->Removed( line, screen );
} }
} }
} }
SCH_JUNCTION* SCH_EDIT_FRAME::AddJunction( SCH_SCREEN* aScreen, const VECTOR2I& aPos, SCH_JUNCTION* SCH_EDIT_FRAME::AddJunction( SCHEMATIC_COMMIT* aCommit, SCH_SCREEN* aScreen,
bool aUndoAppend, bool aFinal ) const VECTOR2I& aPos )
{ {
SCH_JUNCTION* junction = new SCH_JUNCTION( aPos ); SCH_JUNCTION* junction = new SCH_JUNCTION( aPos );
AddToScreen( junction, aScreen ); AddToScreen( junction, aScreen );
SaveCopyInUndoList( aScreen, junction, UNDO_REDO::NEWITEM, aUndoAppend ); aCommit->Added( junction, aScreen );
BreakSegments( aPos );
if( aFinal ) BreakSegments( aCommit, aPos, aScreen );
{
m_toolManager->PostEvent( EVENTS::SelectedItemsModified );
TestDanglingEnds();
OnModify();
KIGFX::SCH_VIEW* view = GetCanvas()->GetView();
view->ClearPreview();
view->ShowPreview( false );
view->ClearHiddenFlags();
}
return junction; return junction;
} }

View File

@ -907,7 +907,7 @@ void SCH_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
} }
if( ADVANCED_CFG::GetCfg().m_IncrementalConnectivity ) if( ADVANCED_CFG::GetCfg().m_IncrementalConnectivity )
RecalculateConnections( GLOBAL_CLEANUP ); RecalculateConnections( nullptr, GLOBAL_CLEANUP );
NETLIST_EXPORTER_KICAD exporter( &Schematic() ); NETLIST_EXPORTER_KICAD exporter( &Schematic() );
STRING_FORMATTER formatter; STRING_FORMATTER formatter;

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 1992-2017 jean-pierre Charras jp.charras at wanadoo.fr * Copyright (C) 1992-2017 jean-pierre Charras jp.charras at wanadoo.fr
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -24,14 +24,13 @@
#include <sch_edit_frame.h> #include <sch_edit_frame.h>
#include <base_units.h>
#include <bitmaps.h> #include <bitmaps.h>
#include <confirm.h>
#include <dialog_annotate_base.h> #include <dialog_annotate_base.h>
#include <eeschema_settings.h> #include <eeschema_settings.h>
#include <kiface_base.h> #include <kiface_base.h>
#include <widgets/wx_html_report_panel.h> #include <widgets/wx_html_report_panel.h>
#include <schematic.h> #include <schematic.h>
#include <schematic_commit.h>
// A window name for the annotate dialog to retrieve is if not destroyed // A window name for the annotate dialog to retrieve is if not destroyed
#define DLG_WINDOW_NAME "DialogAnnotateWindowName" #define DLG_WINDOW_NAME "DialogAnnotateWindowName"
@ -215,19 +214,21 @@ void DIALOG_ANNOTATE::OnClose( wxCloseEvent& event )
void DIALOG_ANNOTATE::OnApplyClick( wxCommandEvent& event ) void DIALOG_ANNOTATE::OnApplyClick( wxCommandEvent& event )
{ {
SCHEMATIC_COMMIT commit( m_Parent );
m_MessageWindow->Clear(); m_MessageWindow->Clear();
REPORTER& reporter = m_MessageWindow->Reporter(); REPORTER& reporter = m_MessageWindow->Reporter();
m_MessageWindow->SetLazyUpdate( true ); // Don't update after each message m_MessageWindow->SetLazyUpdate( true ); // Don't update after each message
m_Parent->AnnotateSymbols( GetScope(), GetSortOrder(), GetAnnotateAlgo(), GetRecursive(), m_Parent->AnnotateSymbols( &commit, GetScope(), GetSortOrder(), GetAnnotateAlgo(),
GetStartNumber(), GetResetItems(), true, reporter ); GetRecursive(), GetStartNumber(), GetResetItems(), true, reporter );
commit.Push( _( "Annotate" ) );
m_MessageWindow->Flush( true ); // Now update to show all messages m_MessageWindow->Flush( true ); // Now update to show all messages
m_Parent->GetCanvas()->Refresh(); m_Parent->GetCanvas()->Refresh();
m_btnClear->Enable(); m_btnClear->Enable();
m_sdbSizer1Cancel->SetDefault(); m_sdbSizer1Cancel->SetDefault();
// Don't close dialog if there are things the user needs to address // Don't close dialog if there are things the user needs to address

View File

@ -495,9 +495,9 @@ void DIALOG_ERC::testErc()
// If we are using the new connectivity, make sure that we do a full-rebuild // If we are using the new connectivity, make sure that we do a full-rebuild
if( ADVANCED_CFG::GetCfg().m_IncrementalConnectivity ) if( ADVANCED_CFG::GetCfg().m_IncrementalConnectivity )
m_parent->RecalculateConnections( GLOBAL_CLEANUP ); m_parent->RecalculateConnections( nullptr, GLOBAL_CLEANUP );
else else
m_parent->RecalculateConnections( NO_CLEANUP ); m_parent->RecalculateConnections( nullptr, NO_CLEANUP );
sch->ConnectionGraph()->RunERC(); sch->ConnectionGraph()->RunERC();

View File

@ -21,7 +21,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include <connection_graph.h>
#include <dialog_global_edit_text_and_graphics_base.h> #include <dialog_global_edit_text_and_graphics_base.h>
#include <string_utils.h> #include <string_utils.h>
#include <sch_symbol.h> #include <sch_symbol.h>
@ -33,7 +32,7 @@
#include <sch_sheet.h> #include <sch_sheet.h>
#include <sch_sheet_pin.h> #include <sch_sheet_pin.h>
#include <schematic.h> #include <schematic.h>
#include <advanced_config.h> #include <schematic_commit.h>
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
#include <tools/ee_selection_tool.h> #include <tools/ee_selection_tool.h>
#include <tools/sch_edit_tool.h> #include <tools/sch_edit_tool.h>

View File

@ -36,7 +36,7 @@ DIALOG_SHAPE_PROPERTIES::DIALOG_SHAPE_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_S
m_shape( aShape ), m_shape( aShape ),
m_borderWidth( aParent, m_borderWidthLabel, m_borderWidthCtrl, m_borderWidthUnits, true ) m_borderWidth( aParent, m_borderWidthLabel, m_borderWidthCtrl, m_borderWidthUnits, true )
{ {
SetTitle( wxString::Format( GetTitle(), aShape->ShowShape() ) ); SetTitle( wxString::Format( GetTitle(), aShape->EDA_SHAPE::GetFriendlyName() ) );
m_helpLabel1->SetFont( KIUI::GetInfoFont( this ).Italic() ); m_helpLabel1->SetFont( KIUI::GetInfoFont( this ).Italic() );
m_helpLabel2->SetFont( KIUI::GetInfoFont( this ).Italic() ); m_helpLabel2->SetFont( KIUI::GetInfoFont( this ).Italic() );
@ -165,7 +165,10 @@ bool DIALOG_SHAPE_PROPERTIES::TransferDataFromWindow()
m_shape->SetFillColor( m_fillColorSwatch->GetSwatchColor() ); m_shape->SetFillColor( m_fillColorSwatch->GetSwatchColor() );
if( !commit.Empty() ) if( !commit.Empty() )
commit.Push( wxString::Format( _( "Edit %s" ), m_shape->ShowShape() ), SKIP_CONNECTIVITY ); {
commit.Push( wxString::Format( _( "Edit %s" ), m_shape->EDA_SHAPE::GetFriendlyName() ),
SKIP_CONNECTIVITY );
}
return true; return true;
} }

View File

@ -807,14 +807,12 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataFromWindow()
{ {
SCH_SCREEN* screen = sheet.LastScreen(); SCH_SCREEN* screen = sheet.LastScreen();
std::vector<SCH_SYMBOL*> otherUnits; std::vector<SCH_SYMBOL*> otherUnits;
constexpr bool appendUndo = true;
CollectOtherUnits( ref, unit, libId, sheet, &otherUnits ); CollectOtherUnits( ref, unit, libId, sheet, &otherUnits );
for( SCH_SYMBOL* otherUnit : otherUnits ) for( SCH_SYMBOL* otherUnit : otherUnits )
{ {
GetParent()->SaveCopyInUndoList( screen, otherUnit, UNDO_REDO::CHANGED, commit.Modify( otherUnit, screen );
appendUndo );
otherUnit->SetValueFieldText( m_fields->at( VALUE_FIELD ).GetText() ); otherUnit->SetValueFieldText( m_fields->at( VALUE_FIELD ).GetText() );
otherUnit->SetFootprintFieldText( m_fields->at( FOOTPRINT_FIELD ).GetText() ); otherUnit->SetFootprintFieldText( m_fields->at( FOOTPRINT_FIELD ).GetText() );

View File

@ -487,7 +487,7 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
OnModify(); OnModify();
} }
RecalculateConnections( GLOBAL_CLEANUP ); RecalculateConnections( nullptr, GLOBAL_CLEANUP );
ClearUndoRedoList(); ClearUndoRedoList();
} }
@ -1258,7 +1258,7 @@ bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
GetScreen()->SetFileName( newfilename.GetFullPath() ); GetScreen()->SetFileName( newfilename.GetFullPath() );
GetScreen()->SetContentModified(); GetScreen()->SetContentModified();
RecalculateConnections( GLOBAL_CLEANUP ); RecalculateConnections( nullptr, GLOBAL_CLEANUP );
// Only perform the dangling end test on root sheet. // Only perform the dangling end test on root sheet.
GetScreen()->TestDanglingEnds(); GetScreen()->TestDanglingEnds();

View File

@ -32,36 +32,12 @@
#include <wildcards_and_files_ext.h> #include <wildcards_and_files_ext.h>
#include <sch_edit_frame.h> #include <sch_edit_frame.h>
#include <symbol_lib_table.h>
#include <symbol_library.h> #include <symbol_library.h>
#include <sch_symbol.h> #include <sch_symbol.h>
#include <sch_sheet.h> #include <sch_sheet.h>
#include <schematic.h> #include <schematic.h>
bool SCH_EDIT_FRAME::CreateArchiveLibraryCacheFile( bool aUseCurrentSheetFilename )
{
wxFileName fn;
if( aUseCurrentSheetFilename )
fn = GetScreen()->GetFileName();
else
fn = Schematic().RootScreen()->GetFileName();
fn.SetName( fn.GetName() + wxS( "-cache" ) );
fn.SetExt( LegacySymbolLibFileExtension );
bool success = CreateArchiveLibrary( fn.GetFullPath() );
// Update the schematic symbol library links.
// because the lib cache has changed
SCH_SCREENS schematic( Schematic().Root() );
schematic.UpdateSymbolLinks();
return success;
}
bool SCH_EDIT_FRAME::CreateArchiveLibrary( const wxString& aFileName ) bool SCH_EDIT_FRAME::CreateArchiveLibrary( const wxString& aFileName )
{ {
wxString tmp; wxString tmp;

View File

@ -55,7 +55,7 @@ bool SCH_EDIT_FRAME::WriteNetListFile( int aFormat, const wxString& aFullFileNam
// If we are using the new connectivity, make sure that we do a full-rebuild // If we are using the new connectivity, make sure that we do a full-rebuild
if( ADVANCED_CFG::GetCfg().m_IncrementalConnectivity ) if( ADVANCED_CFG::GetCfg().m_IncrementalConnectivity )
RecalculateConnections( GLOBAL_CLEANUP ); RecalculateConnections( nullptr, GLOBAL_CLEANUP );
bool res = true; bool res = true;
bool executeCommandLine = false; bool executeCommandLine = false;

View File

@ -53,6 +53,7 @@
#include <sch_sheet.h> #include <sch_sheet.h>
#include <sch_marker.h> #include <sch_marker.h>
#include <schematic.h> #include <schematic.h>
#include <schematic_commit.h>
#include <settings/settings_manager.h> #include <settings/settings_manager.h>
#include <advanced_config.h> #include <advanced_config.h>
#include <sim/simulator_frame.h> #include <sim/simulator_frame.h>
@ -1083,7 +1084,7 @@ void SCH_EDIT_FRAME::OnModify()
GetScreen()->SetContentModified(); GetScreen()->SetContentModified();
m_autoSaveRequired = true; m_autoSaveRequired = true;
RecalculateConnections( NO_CLEANUP ); RecalculateConnections( nullptr, NO_CLEANUP );
GetCanvas()->Refresh(); GetCanvas()->Refresh();
UpdateHierarchyNavigator(); UpdateHierarchyNavigator();
@ -1588,8 +1589,8 @@ void SCH_EDIT_FRAME::AutoRotateItem( SCH_SCREEN* aScreen, SCH_ITEM* aItem )
} }
void SCH_EDIT_FRAME::AddItemToScreenAndUndoList( SCH_SCREEN* aScreen, SCH_ITEM* aItem, void SCH_EDIT_FRAME::AddItemToCommitAndScreen( SCHEMATIC_COMMIT* aCommit, SCH_SCREEN* aScreen,
bool aUndoAppend ) SCH_ITEM* aItem )
{ {
wxCHECK_RET( aItem != nullptr, wxT( "Cannot add null item to list." ) ); wxCHECK_RET( aItem != nullptr, wxT( "Cannot add null item to list." ) );
@ -1622,8 +1623,7 @@ void SCH_EDIT_FRAME::AddItemToScreenAndUndoList( SCH_SCREEN* aScreen, SCH_ITEM*
if( aItem->Type() == SCH_SHEET_PIN_T ) if( aItem->Type() == SCH_SHEET_PIN_T )
{ {
// Sheet pins are owned by their parent sheet. // Sheet pins are owned by their parent sheet.
SaveCopyInUndoList( aScreen, undoItem, UNDO_REDO::CHANGED, aUndoAppend ); aCommit->Modify( undoItem, aScreen );
parentSheet->AddPin( (SCH_SHEET_PIN*) aItem ); parentSheet->AddPin( (SCH_SHEET_PIN*) aItem );
} }
else if( aItem->Type() == SCH_FIELD_T ) else if( aItem->Type() == SCH_FIELD_T )
@ -1638,12 +1638,12 @@ void SCH_EDIT_FRAME::AddItemToScreenAndUndoList( SCH_SCREEN* aScreen, SCH_ITEM*
AddToScreen( aItem, aScreen ); AddToScreen( aItem, aScreen );
SaveCopyForRepeatItem( aItem ); SaveCopyForRepeatItem( aItem );
SaveCopyInUndoList( aScreen, undoItem, UNDO_REDO::NEWITEM, aUndoAppend ); aCommit->Modify( undoItem, aScreen );
} }
// Update connectivity info for new item // Update connectivity info for new item
if( !aItem->IsMoving() && aItem->IsConnectable() ) if( !aItem->IsMoving() && aItem->IsConnectable() )
RecalculateConnections( LOCAL_CLEANUP ); RecalculateConnections( aCommit, LOCAL_CLEANUP );
} }
aItem->ClearFlags( IS_NEW ); aItem->ClearFlags( IS_NEW );
@ -1656,22 +1656,21 @@ void SCH_EDIT_FRAME::AddItemToScreenAndUndoList( SCH_SCREEN* aScreen, SCH_ITEM*
std::vector<VECTOR2I> pts = aItem->GetConnectionPoints(); std::vector<VECTOR2I> pts = aItem->GetConnectionPoints();
bool connected = true; bool connected = true;
for( auto i = pts.begin(); i != pts.end(); i++ ) for( auto i = pts.begin(); i != pts.end(); i++ )
{ {
for( auto j = i + 1; j != pts.end(); j++ ) for( auto j = i + 1; j != pts.end(); j++ )
TrimWire( *i, *j ); TrimWire( aCommit, *i, *j );
if( aScreen->IsExplicitJunctionNeeded( *i ) ) if( aScreen->IsExplicitJunctionNeeded( *i ) )
{ {
AddJunction( aScreen, *i, true, false ); AddJunction( aCommit, aScreen, *i );
connected = true; connected = true;
} }
} }
if( connected ) if( connected )
{
AutoRotateItem( aScreen, aItem ); AutoRotateItem( aScreen, aItem );
}
TestDanglingEnds(); TestDanglingEnds();
@ -1737,11 +1736,16 @@ void SCH_EDIT_FRAME::initScreenZoom()
} }
void SCH_EDIT_FRAME::RecalculateConnections( SCH_CLEANUP_FLAGS aCleanupFlags ) void SCH_EDIT_FRAME::RecalculateConnections( SCHEMATIC_COMMIT* aCommit,
SCH_CLEANUP_FLAGS aCleanupFlags )
{ {
wxString highlightedConn = GetHighlightedConnection(); wxString highlightedConn = GetHighlightedConnection();
SCHEMATIC_SETTINGS& settings = Schematic().Settings(); SCHEMATIC_SETTINGS& settings = Schematic().Settings();
SCH_SHEET_LIST list = Schematic().GetSheets(); SCH_SHEET_LIST list = Schematic().GetSheets();
SCHEMATIC_COMMIT localInstance( m_toolManager );
if( !aCommit )
aCommit = &localInstance;
#ifdef PROFILE #ifdef PROFILE
PROF_TIMER timer; PROF_TIMER timer;
@ -1750,12 +1754,12 @@ void SCH_EDIT_FRAME::RecalculateConnections( SCH_CLEANUP_FLAGS aCleanupFlags )
// Ensure schematic graph is accurate // Ensure schematic graph is accurate
if( aCleanupFlags == LOCAL_CLEANUP ) if( aCleanupFlags == LOCAL_CLEANUP )
{ {
SchematicCleanUp( GetScreen() ); SchematicCleanUp( aCommit, GetScreen() );
} }
else if( aCleanupFlags == GLOBAL_CLEANUP ) else if( aCleanupFlags == GLOBAL_CLEANUP )
{ {
for( const SCH_SHEET_PATH& sheet : list ) for( const SCH_SHEET_PATH& sheet : list )
SchematicCleanUp( sheet.LastScreen() ); SchematicCleanUp( aCommit, sheet.LastScreen() );
} }
#ifdef PROFILE #ifdef PROFILE
@ -1909,6 +1913,9 @@ void SCH_EDIT_FRAME::RecalculateConnections( SCH_CLEANUP_FLAGS aCleanupFlags )
m_highlightedConnChanged = false; m_highlightedConnChanged = false;
} }
if( !localInstance.Empty() )
localInstance.Push( _( "Schematic Cleanup" ) );
} }

View File

@ -55,10 +55,10 @@ class SCH_SYMBOL;
class SCH_FIELD; class SCH_FIELD;
class SCH_JUNCTION; class SCH_JUNCTION;
class SCHEMATIC; class SCHEMATIC;
class SCHEMATIC_COMMIT;
class DIALOG_BOOK_REPORTER; class DIALOG_BOOK_REPORTER;
class DIALOG_ERC; class DIALOG_ERC;
class DIALOG_SCH_FIND; class DIALOG_SCH_FIND;
class wxFindReplaceData;
class RESCUER; class RESCUER;
class HIERARCHY_PANE; class HIERARCHY_PANE;
@ -248,10 +248,9 @@ public:
void AutoRotateItem( SCH_SCREEN* aScreen, SCH_ITEM* aItem ); void AutoRotateItem( SCH_SCREEN* aScreen, SCH_ITEM* aItem );
/** /**
* Add an item to the schematic and adds the changes to the undo/redo container. * Add an item to the schematic and adds the changes to the commit.
* @param aUndoAppend True if the action should be appended to the current undo record.
*/ */
void AddItemToScreenAndUndoList( SCH_SCREEN* aScreen, SCH_ITEM* aItem, bool aUndoAppend ); void AddItemToCommitAndScreen( SCHEMATIC_COMMIT* aCommit, SCH_SCREEN* aScreen, SCH_ITEM* aItem );
/** /**
* Run the Find or Find & Replace dialog. * Run the Find or Find & Replace dialog.
@ -279,39 +278,33 @@ public:
/** /**
* Break a single segment into two at the specified point. * Break a single segment into two at the specified point.
* * @param aCommit Transaction container used to record changes for undo/redo
* @note This always appends to the existing undo state.
*
* @param aSegment Line segment to break * @param aSegment Line segment to break
* @param aPoint Point at which to break the segment * @param aPoint Point at which to break the segment
* @param aNewSegment Pointer to the newly created segment (if given and created) * @param aNewSegment Pointer to the newly created segment (if created)
* @param aScreen is the screen to examine, or nullptr to examine the current screen. * @param aScreen is the screen to examine
*/ */
void BreakSegment( SCH_LINE* aSegment, const VECTOR2I& aPoint, void BreakSegment( SCHEMATIC_COMMIT* aCommit, SCH_LINE* aSegment, const VECTOR2I& aPoint,
SCH_LINE** aNewSegment = nullptr, SCH_SCREEN* aScreen = nullptr ); SCH_LINE** aNewSegment, SCH_SCREEN* aScreen );
/** /**
* Check every wire and bus for a intersection at \a aPoint and break into two segments * Check every wire and bus for a intersection at \a aPoint and break into two segments
* at \a aPoint if an intersection is found. * at \a aPoint if an intersection is found.
* * @param aCommit Transaction container used to record changes for undo/redo
* @note This always appends to the existing undo state.
*
* @param aPoint Test this point for an intersection. * @param aPoint Test this point for an intersection.
* @param aScreen is the screen to examine, or nullptr to examine the current screen. * @param aScreen is the screen to examine.
* @return True if any wires or buses were broken. * @return True if any wires or buses were broken.
*/ */
bool BreakSegments( const VECTOR2I& aPoint, SCH_SCREEN* aScreen = nullptr ); bool BreakSegments( SCHEMATIC_COMMIT* aCommit, const VECTOR2I& aPoint, SCH_SCREEN* aScreen );
/** /**
* Test all junctions and bus entries in the schematic for intersections with wires and * Test all junctions and bus entries in the schematic for intersections with wires and
* buses and breaks any intersections into multiple segments. * buses and breaks any intersections into multiple segments.
* * @param aCommit Transaction container used to record changes for undo/redo
* @note This always appends to the existing undo state. * @param aScreen is the screen to examine.
*
* @param aScreen is the screen to examine, or nullptr to examine the current screen
* @return True if any wires or buses were broken. * @return True if any wires or buses were broken.
*/ */
bool BreakSegmentsOnJunctions( SCH_SCREEN* aScreen = nullptr ); bool BreakSegmentsOnJunctions( SCHEMATIC_COMMIT* aCommit, SCH_SCREEN* aScreen );
/** /**
* Test all of the connectable objects in the schematic for unused connection points. * Test all of the connectable objects in the schematic for unused connection points.
@ -396,7 +389,7 @@ public:
* Annotate the symbols in the schematic that are not currently annotated. Multi-unit symbols * Annotate the symbols in the schematic that are not currently annotated. Multi-unit symbols
* are annotated together. E.g. if two symbols were R8A and R8B, they may become R3A and * are annotated together. E.g. if two symbols were R8A and R8B, they may become R3A and
* R3B, but not R3A and R3C or R3C and R4D. * R3B, but not R3A and R3C or R3C and R4D.
* * @param aCommit Transaction container used to record changes for undo/redo
* @param aAnnotateScope See #ANNOTATE_SCOPE_T * @param aAnnotateScope See #ANNOTATE_SCOPE_T
* @param aSortOption Define the annotation order. See #ANNOTATE_ORDER_T. * @param aSortOption Define the annotation order. See #ANNOTATE_ORDER_T.
* @param aAlgoOption Define the annotation style. See #ANNOTATE_ALGO_T. * @param aAlgoOption Define the annotation style. See #ANNOTATE_ALGO_T.
@ -410,17 +403,14 @@ public:
* used to handle annotation in complex hierarchies. * used to handle annotation in complex hierarchies.
* @param aReporter A sink for error messages. Use NULL_REPORTER if you don't need errors. * @param aReporter A sink for error messages. Use NULL_REPORTER if you don't need errors.
* *
* @param appendUndo True if the annotation operation should be added to an existing undo,
* false if it should be separately undo-able.
*
* When the sheet number is used in annotation, each sheet annotation starts from sheet * When the sheet number is used in annotation, each sheet annotation starts from sheet
* number * 100. In other words the first sheet uses 100 to 199, the second sheet uses * number * 100. In other words the first sheet uses 100 to 199, the second sheet uses
* 200 to 299, and so on. * 200 to 299, and so on.
*/ */
void AnnotateSymbols( ANNOTATE_SCOPE_T aAnnotateScope, ANNOTATE_ORDER_T aSortOption, void AnnotateSymbols( SCHEMATIC_COMMIT* aCommit, ANNOTATE_SCOPE_T aAnnotateScope,
ANNOTATE_ALGO_T aAlgoOption, bool aRecursive, int aStartNumber, ANNOTATE_ORDER_T aSortOption, ANNOTATE_ALGO_T aAlgoOption,
bool aResetAnnotation, bool aRepairTimestamps, REPORTER& aReporter, bool aRecursive, int aStartNumber, bool aResetAnnotation,
bool appendUndo = false ); bool aRepairTimestamps, REPORTER& aReporter );
/** /**
* Check for annotation errors. * Check for annotation errors.
@ -532,31 +522,26 @@ public:
*/ */
bool AskToSaveChanges(); bool AskToSaveChanges();
SCH_JUNCTION* AddJunction( SCH_SCREEN* aScreen, const VECTOR2I& aPos, bool aAppendToUndo, SCH_JUNCTION* AddJunction( SCHEMATIC_COMMIT* aCommit, SCH_SCREEN* aScreen,
bool aFinal = true ); const VECTOR2I& aPos );
/** /**
* Perform routine schematic cleaning including breaking wire and buses and deleting * Perform routine schematic cleaning including breaking wire and buses and deleting
* identical objects superimposed on top of each other. * identical objects superimposed on top of each other.
* * @param aCommit Transaction container used to record changes for undo/redo
* @note This always appends to the existing undo state.
*
* @param aScreen is the screen to examine, or nullptr to examine the current screen * @param aScreen is the screen to examine, or nullptr to examine the current screen
* @return True if any schematic clean up was performed.
*/ */
bool SchematicCleanUp( SCH_SCREEN* aScreen = nullptr ); void SchematicCleanUp( SCHEMATIC_COMMIT* aCommit, SCH_SCREEN* aScreen = nullptr );
/** /**
* If any single wire passes through _both points_, remove the portion between the two points, * If any single wire passes through _both points_, remove the portion between the two points,
* potentially splitting the wire into two. * potentially splitting the wire into two.
* * @param aCommit Transaction container used to record changes for undo/redo
* @note This always appends to the existing undo state.
*
* @param aStart The starting point for trimmming * @param aStart The starting point for trimmming
* @param aEnd The ending point for trimming * @param aEnd The ending point for trimming
* @return True if any wires were changed by this operation * @return True if any wires were changed by this operation
*/ */
bool TrimWire( const VECTOR2I& aStart, const VECTOR2I& aEnd ); bool TrimWire( SCHEMATIC_COMMIT* aCommit, const VECTOR2I& aStart, const VECTOR2I& aEnd );
void OnOpenPcbnew( wxCommandEvent& event ); void OnOpenPcbnew( wxCommandEvent& event );
void OnOpenCvpcb( wxCommandEvent& event ); void OnOpenCvpcb( wxCommandEvent& event );
@ -568,7 +553,6 @@ public:
* *
* @param aSheet is the #SCH_SHEET object to test. * @param aSheet is the #SCH_SHEET object to test.
* @param aHierarchy is the #SCH_SHEET_PATH where \a aSheet is going to reside. * @param aHierarchy is the #SCH_SHEET_PATH where \a aSheet is going to reside.
*
* @return true if \a aSheet will cause a recursion error in \a aHierarchy. * @return true if \a aSheet will cause a recursion error in \a aHierarchy.
*/ */
bool CheckSheetForRecursion( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy ); bool CheckSheetForRecursion( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy );
@ -670,9 +654,8 @@ public:
* Removes a given junction and heals any wire segments under the junction * Removes a given junction and heals any wire segments under the junction
* *
* @param aItem The junction to delete * @param aItem The junction to delete
* @param aAppend True if we are updating an ongoing commit
*/ */
void DeleteJunction( SCH_ITEM* aItem, bool aAppend = false ); void DeleteJunction( SCHEMATIC_COMMIT* aCommit, SCH_ITEM* aItem );
void ConvertPart( SCH_SYMBOL* aSymbol ); void ConvertPart( SCH_SYMBOL* aSymbol );
@ -680,11 +663,6 @@ public:
/* Undo - redo */ /* Undo - redo */
/**
* Create a new, blank stack for future Undo commands to be pushed to
*/
void StartNewUndo();
/** /**
* Create a copy of the current schematic item, and put it in the undo list. * Create a copy of the current schematic item, and put it in the undo list.
* *
@ -758,17 +736,6 @@ public:
*/ */
void RollbackSchematicFromUndo(); void RollbackSchematicFromUndo();
/**
* Create a symbol library file with the name of the root document plus the '-cache' suffix,
*
* This file will contain all symbols used in the current schematic.
*
* @param aUseCurrentSheetFilename set to false to use the root sheet filename
* (default) or true to use the currently opened sheet.
* @return true if the file was written successfully.
*/
bool CreateArchiveLibraryCacheFile( bool aUseCurrentSheetFilename = false );
/** /**
* Create a library \a aFileName that contains all symbols used in the current schematic. * Create a library \a aFileName that contains all symbols used in the current schematic.
* *
@ -809,7 +776,7 @@ public:
/** /**
* Generate the connection data for the entire schematic hierarchy. * Generate the connection data for the entire schematic hierarchy.
*/ */
void RecalculateConnections( SCH_CLEANUP_FLAGS aCleanupFlags ); void RecalculateConnections( SCHEMATIC_COMMIT* aCommit, SCH_CLEANUP_FLAGS aCleanupFlags );
/** /**
* Called after the preferences dialog is run. * Called after the preferences dialog is run.

View File

@ -26,13 +26,9 @@
#include <tools/ee_tool_base.h> #include <tools/ee_tool_base.h>
#include <lib_item.h> #include <lib_item.h>
#include <lib_pin.h>
#include <lib_shape.h>
#include <lib_symbol.h> #include <lib_symbol.h>
#include <lib_text.h>
#include <sch_screen.h> #include <sch_screen.h>
#include <sch_sheet_path.h>
#include <schematic.h> #include <schematic.h>
#include <view/view.h> #include <view/view.h>
@ -75,19 +71,33 @@ COMMIT& SCHEMATIC_COMMIT::Stage( EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_
// If aItem belongs a symbol, the full symbol will be saved because undo/redo does // If aItem belongs a symbol, the full symbol will be saved because undo/redo does
// not handle "sub items" modifications. // not handle "sub items" modifications.
if( aItem->GetParent() && aItem->GetParent()->IsType( { SCH_SYMBOL_T, LIB_SYMBOL_T } ) ) if( aItem->GetParent() && aItem->GetParent()->IsType( { SCH_SYMBOL_T, LIB_SYMBOL_T,
SCH_SHEET_T } ) )
{ {
aItem->SetFlags( IS_MODIFIED_CHILD ); aItem->SetFlags( IS_MODIFIED_CHILD );
aItem = aItem->GetParent(); aItem = aItem->GetParent();
aChangeType = CHT_MODIFY;
} }
// IS_SELECTED flag should not be set on undo items which were added for
// a drag operation.
if( aItem->IsSelected() && aItem->HasFlag( SELECTED_BY_DRAG ) )
{
aItem->ClearSelected();
COMMIT::Stage( aItem, aChangeType, aScreen );
aItem->SetSelected();
}
else
{
COMMIT::Stage( aItem, aChangeType, aScreen );
}
return COMMIT::Stage( aItem, aChangeType, aScreen ); return *this;
} }
COMMIT& SCHEMATIC_COMMIT::Stage( std::vector<EDA_ITEM*> &container, CHANGE_TYPE aChangeType, COMMIT& SCHEMATIC_COMMIT::Stage( std::vector<EDA_ITEM*> &container, CHANGE_TYPE aChangeType,
BASE_SCREEN *aScreen ) BASE_SCREEN *aScreen )
{ {
for( EDA_ITEM* item : container ) for( EDA_ITEM* item : container )
Stage( item, aChangeType, aScreen ); Stage( item, aChangeType, aScreen );
@ -97,7 +107,7 @@ COMMIT& SCHEMATIC_COMMIT::Stage( std::vector<EDA_ITEM*> &container, CHANGE_TYPE
COMMIT& SCHEMATIC_COMMIT::Stage( const PICKED_ITEMS_LIST &aItems, UNDO_REDO aModFlag, COMMIT& SCHEMATIC_COMMIT::Stage( const PICKED_ITEMS_LIST &aItems, UNDO_REDO aModFlag,
BASE_SCREEN *aScreen ) BASE_SCREEN *aScreen )
{ {
return COMMIT::Stage( aItems, aModFlag, aScreen ); return COMMIT::Stage( aItems, aModFlag, aScreen );
} }
@ -274,17 +284,17 @@ void SCHEMATIC_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
{ {
case CHT_ADD: case CHT_ADD:
{ {
if( !schItem->GetParent() ) if( !( aCommitFlags & SKIP_UNDO ) )
undoList.PushItem( ITEM_PICKER( screen, schItem, UNDO_REDO::NEWITEM ) );
if( !( changeFlags & CHT_DONE ) )
{ {
if( !( aCommitFlags & SKIP_UNDO ) ) if( !schItem->GetParent() )
undoList.PushItem( ITEM_PICKER( screen, schItem, UNDO_REDO::NEWITEM ) );
if( !( changeFlags & CHT_DONE ) )
frame->GetScreen()->Append( schItem ); frame->GetScreen()->Append( schItem );
}
if( view ) if( view )
view->Add( schItem ); view->Add( schItem );
}
bulkAddedItems.push_back( schItem ); bulkAddedItems.push_back( schItem );
@ -310,14 +320,16 @@ void SCHEMATIC_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
break; break;
} }
if( view ) if( !( changeFlags & CHT_DONE ) )
view->Remove( schItem ); {
frame->GetScreen()->Remove( schItem );
if( view )
view->Remove( schItem );
}
bulkRemovedItems.push_back( schItem ); bulkRemovedItems.push_back( schItem );
if( !( changeFlags & CHT_DONE ) )
frame->GetScreen()->Remove( schItem );
break; break;
} }
@ -406,8 +418,10 @@ EDA_ITEM* SCHEMATIC_COMMIT::parentObject( EDA_ITEM* aItem ) const
EDA_ITEM* SCHEMATIC_COMMIT::makeImage( EDA_ITEM* aItem ) const EDA_ITEM* SCHEMATIC_COMMIT::makeImage( EDA_ITEM* aItem ) const
{ {
if( m_isLibEditor ) if( m_isLibEditor )
return new LIB_SYMBOL( {
*static_cast<SYMBOL_EDIT_FRAME*>( m_toolMgr->GetToolHolder() )->GetCurSymbol() ); SYMBOL_EDIT_FRAME* frame = static_cast<SYMBOL_EDIT_FRAME*>( m_toolMgr->GetToolHolder() );
return new LIB_SYMBOL( *frame->GetCurSymbol() );
}
return aItem->Clone(); return aItem->Clone();
} }
@ -431,8 +445,8 @@ void SCHEMATIC_COMMIT::revertLibEdit()
void SCHEMATIC_COMMIT::Revert() void SCHEMATIC_COMMIT::Revert()
{ {
PICKED_ITEMS_LIST undoList; PICKED_ITEMS_LIST undoList;
KIGFX::VIEW* view = m_toolMgr->GetView(); KIGFX::VIEW* view = m_toolMgr->GetView();
if( m_changes.empty() ) if( m_changes.empty() )
return; return;
@ -443,10 +457,11 @@ void SCHEMATIC_COMMIT::Revert()
return; return;
} }
SCHEMATIC& schematic = static_cast<SCH_EDIT_FRAME*>( m_toolMgr->GetToolHolder() )->Schematic(); SCH_EDIT_FRAME* frame = static_cast<SCH_EDIT_FRAME*>( m_toolMgr->GetToolHolder() );
SCHEMATIC& schematic = frame->Schematic();
std::vector<SCH_ITEM*> bulkAddedItems; std::vector<SCH_ITEM*> bulkAddedItems;
std::vector<SCH_ITEM*> bulkRemovedItems; std::vector<SCH_ITEM*> bulkRemovedItems;
std::vector<SCH_ITEM*> itemsChanged; std::vector<SCH_ITEM*> itemsChanged;
for( auto it = m_changes.rbegin(); it != m_changes.rend(); ++it ) for( auto it = m_changes.rbegin(); it != m_changes.rend(); ++it )
@ -470,6 +485,8 @@ void SCHEMATIC_COMMIT::Revert()
break; break;
case CHT_REMOVE: case CHT_REMOVE:
item->SetConnectivityDirty();
if( !( changeFlags & CHT_DONE ) ) if( !( changeFlags & CHT_DONE ) )
break; break;
@ -482,6 +499,7 @@ void SCHEMATIC_COMMIT::Revert()
{ {
view->Remove( item ); view->Remove( item );
item->SwapData( copy ); item->SwapData( copy );
item->SetConnectivityDirty();
// Special cases for items which have instance data // Special cases for items which have instance data
if( item->GetParent() && item->GetParent()->Type() == SCH_SYMBOL_T if( item->GetParent() && item->GetParent()->Type() == SCH_SYMBOL_T
@ -521,6 +539,8 @@ void SCHEMATIC_COMMIT::Revert()
EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>(); EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
selTool->RebuildSelection(); selTool->RebuildSelection();
frame->RecalculateConnections( nullptr, NO_CLEANUP );
clear(); clear();
} }

View File

@ -96,13 +96,6 @@
* swapped data is data modified by editing, so not all values are swapped * swapped data is data modified by editing, so not all values are swapped
*/ */
void SCH_EDIT_FRAME::StartNewUndo()
{
PICKED_ITEMS_LIST* blank = new PICKED_ITEMS_LIST();
PushCommandToUndoList( blank );
}
void SCH_EDIT_FRAME::SaveCopyInUndoList( SCH_SCREEN* aScreen, SCH_ITEM* aItem, void SCH_EDIT_FRAME::SaveCopyInUndoList( SCH_SCREEN* aScreen, SCH_ITEM* aItem,
UNDO_REDO aCommandType, bool aAppend, UNDO_REDO aCommandType, bool aAppend,
bool aDirtyConnectivity ) bool aDirtyConnectivity )
@ -221,7 +214,9 @@ void SCH_EDIT_FRAME::SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList,
{ {
if( !sch_item->IsConnectivityDirty() && sch_item->Connection() if( !sch_item->IsConnectivityDirty() && sch_item->Connection()
&& ( sch_item->Connection()->Name() == m_highlightedConn ) ) && ( sch_item->Connection()->Name() == m_highlightedConn ) )
{
m_highlightedConnChanged = true; m_highlightedConnChanged = true;
}
sch_item->SetConnectivityDirty(); sch_item->SetConnectivityDirty();
} }

View File

@ -994,7 +994,7 @@ bool SIMULATOR_FRAME::LoadSimulator()
// If we are using the new connectivity, make sure that we do a full-rebuild // If we are using the new connectivity, make sure that we do a full-rebuild
if( ADVANCED_CFG::GetCfg().m_IncrementalConnectivity ) if( ADVANCED_CFG::GetCfg().m_IncrementalConnectivity )
m_schematicFrame->RecalculateConnections( GLOBAL_CLEANUP ); m_schematicFrame->RecalculateConnections( nullptr, GLOBAL_CLEANUP );
if( !m_simulator->Attach( m_circuitModel, reporter ) ) if( !m_simulator->Attach( m_circuitModel, reporter ) )
{ {

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2019 Alexander Shuklin <Jasuramme@gmail.com> * Copyright (C) 2019 Alexander Shuklin <Jasuramme@gmail.com>
* Copyright (C) 2004-2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2004-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -33,6 +33,7 @@
#include <sch_sheet_path.h> #include <sch_sheet_path.h>
#include <sch_label.h> #include <sch_label.h>
#include <schematic.h> #include <schematic.h>
#include <schematic_commit.h>
#include <string_utils.h> #include <string_utils.h>
#include <kiface_base.h> #include <kiface_base.h>
#include <wildcards_and_files_ext.h> #include <wildcards_and_files_ext.h>
@ -53,8 +54,7 @@ BACK_ANNOTATE::BACK_ANNOTATE( SCH_EDIT_FRAME* aFrame, REPORTER& aReporter, bool
m_processAttributes( aProcessAttributes ), m_processAttributes( aProcessAttributes ),
m_dryRun( aDryRun ), m_dryRun( aDryRun ),
m_frame( aFrame ), m_frame( aFrame ),
m_changesCount( 0 ), m_changesCount( 0 )
m_appendUndo( false )
{ {
} }
@ -67,7 +67,6 @@ BACK_ANNOTATE::~BACK_ANNOTATE()
bool BACK_ANNOTATE::BackAnnotateSymbols( const std::string& aNetlist ) bool BACK_ANNOTATE::BackAnnotateSymbols( const std::string& aNetlist )
{ {
m_changesCount = 0; m_changesCount = 0;
m_appendUndo = false;
if( !m_matchByReference && !m_processValues && !m_processFootprints && !m_processReferences if( !m_matchByReference && !m_processValues && !m_processFootprints && !m_processReferences
&& !m_processNetNames && !m_processAttributes ) && !m_processNetNames && !m_processAttributes )
@ -226,8 +225,8 @@ void BACK_ANNOTATE::getPcbModulesFromString( const std::string& aPayload )
else else
{ {
// Add footprint to the map // Add footprint to the map
auto data = auto data = std::make_shared<PCB_FP_DATA>( ref, footprint, value, dnp, exBOM,
std::make_shared<PCB_FP_DATA>( ref, footprint, value, dnp, exBOM, pinNetMap ); pinNetMap );
m_pcbFootprints.insert( nearestItem, std::make_pair( path, data ) ); m_pcbFootprints.insert( nearestItem, std::make_pair( path, data ) );
} }
} }
@ -336,7 +335,8 @@ void BACK_ANNOTATE::checkForUnusedSymbols()
void BACK_ANNOTATE::applyChangelist() void BACK_ANNOTATE::applyChangelist()
{ {
wxString msg; SCHEMATIC_COMMIT commit( m_frame );
wxString msg;
// Apply changes from change list // Apply changes from change list
for( CHANGELIST_ITEM& item : m_changelist ) for( CHANGELIST_ITEM& item : m_changelist )
@ -365,8 +365,7 @@ void BACK_ANNOTATE::applyChangelist()
if( !m_dryRun ) if( !m_dryRun )
{ {
m_frame->SaveCopyInUndoList( screen, symbol, UNDO_REDO::CHANGED, m_appendUndo ); commit.Modify( symbol, screen );
m_appendUndo = true;
symbol->SetRef( &ref.GetSheetPath(), fpData.m_ref ); symbol->SetRef( &ref.GetSheetPath(), fpData.m_ref );
} }
@ -383,8 +382,7 @@ void BACK_ANNOTATE::applyChangelist()
if( !m_dryRun ) if( !m_dryRun )
{ {
m_frame->SaveCopyInUndoList( screen, symbol, UNDO_REDO::CHANGED, m_appendUndo ); commit.Modify( symbol, screen );
m_appendUndo = true;
symbol->SetFootprintFieldText( fpData.m_footprint ); symbol->SetFootprintFieldText( fpData.m_footprint );
} }
@ -401,8 +399,7 @@ void BACK_ANNOTATE::applyChangelist()
if( !m_dryRun ) if( !m_dryRun )
{ {
m_frame->SaveCopyInUndoList( screen, symbol, UNDO_REDO::CHANGED, m_appendUndo ); commit.Modify( symbol, screen );
m_appendUndo = true;
symbol->SetValueFieldText( fpData.m_value ); symbol->SetValueFieldText( fpData.m_value );
} }
@ -417,8 +414,7 @@ void BACK_ANNOTATE::applyChangelist()
if( !m_dryRun ) if( !m_dryRun )
{ {
m_frame->SaveCopyInUndoList( screen, symbol, UNDO_REDO::CHANGED, m_appendUndo ); commit.Modify( symbol, screen );
m_appendUndo = true;
symbol->SetDNP( fpData.m_DNP ); symbol->SetDNP( fpData.m_DNP );
} }
@ -434,8 +430,7 @@ void BACK_ANNOTATE::applyChangelist()
if( !m_dryRun ) if( !m_dryRun )
{ {
m_frame->SaveCopyInUndoList( screen, symbol, UNDO_REDO::CHANGED, m_appendUndo ); commit.Modify( symbol, screen );
m_appendUndo = true;
symbol->SetIncludeInBom( !fpData.m_excludeFromBOM ); symbol->SetIncludeInBom( !fpData.m_excludeFromBOM );
} }
@ -464,19 +459,21 @@ void BACK_ANNOTATE::applyChangelist()
if( connection && connection->Name( true ) != shortNetName ) if( connection && connection->Name( true ) != shortNetName )
{ {
processNetNameChange( ref.GetRef(), pin, connection, processNetNameChange( &commit, ref.GetRef(), pin, connection,
connection->Name( true ), shortNetName ); connection->Name( true ), shortNetName );
} }
} }
} }
// JEY TODO: back-annotate netclass changes? // TODO: back-annotate netclass changes?
} }
if( !m_dryRun ) if( !m_dryRun )
{ {
m_frame->RecalculateConnections( NO_CLEANUP ); m_frame->RecalculateConnections( &commit, NO_CLEANUP );
m_frame->UpdateNetHighlightStatus(); m_frame->UpdateNetHighlightStatus();
commit.Push( _( "Update Schematic from PCB" ) );
} }
} }
@ -560,8 +557,8 @@ void addConnections( SCH_ITEM* aItem, const SCH_SHEET_PATH& aSheetPath,
} }
void BACK_ANNOTATE::processNetNameChange( const wxString& aRef, SCH_PIN* aPin, void BACK_ANNOTATE::processNetNameChange( SCHEMATIC_COMMIT* aCommit, const wxString& aRef,
const SCH_CONNECTION* aConnection, SCH_PIN* aPin, const SCH_CONNECTION* aConnection,
const wxString& aOldName, const wxString& aNewName ) const wxString& aOldName, const wxString& aNewName )
{ {
wxString msg; wxString msg;
@ -603,10 +600,7 @@ void BACK_ANNOTATE::processNetNameChange( const wxString& aRef, SCH_PIN* aPin,
if( !m_dryRun ) if( !m_dryRun )
{ {
SCH_SCREEN* screen = aConnection->Sheet().LastScreen(); aCommit->Modify( driver, aConnection->Sheet().LastScreen() );
m_frame->SaveCopyInUndoList( screen, driver, UNDO_REDO::CHANGED, m_appendUndo );
m_appendUndo = true;
static_cast<SCH_LABEL_BASE*>( driver )->SetText( aNewName ); static_cast<SCH_LABEL_BASE*>( driver )->SetText( aNewName );
} }
@ -644,8 +638,7 @@ void BACK_ANNOTATE::processNetNameChange( const wxString& aRef, SCH_PIN* aPin,
label->SetFlags( IS_NEW ); label->SetFlags( IS_NEW );
SCH_SCREEN* screen = aConnection->Sheet().LastScreen(); SCH_SCREEN* screen = aConnection->Sheet().LastScreen();
m_frame->AddItemToScreenAndUndoList( screen, label, m_appendUndo ); m_frame->AddItemToCommitAndScreen( aCommit, screen, label );
m_appendUndo = true;
} }
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION ); m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2019 Alexander Shuklin <Jasuramme@gmail.com> * Copyright (C) 2019 Alexander Shuklin <Jasuramme@gmail.com>
* Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -37,7 +37,7 @@
class REPORTER; class REPORTER;
class SCH_SHEET_LIST; class SCH_SHEET_LIST;
class SCH_EDIT_FRAME; class SCH_EDIT_FRAME;
class SCHEMATIC_COMMIT;
/** /**
* Back annotation algorithm class used to receive, check, and apply a \ref NETLIST from * Back annotation algorithm class used to receive, check, and apply a \ref NETLIST from
@ -62,7 +62,7 @@ public:
{ {
PCB_FP_DATA( const wxString& aRef, const wxString& aFootprint, const wxString& aValue, PCB_FP_DATA( const wxString& aRef, const wxString& aFootprint, const wxString& aValue,
bool aDNP, bool aExcludeFromBOM, bool aDNP, bool aExcludeFromBOM,
const std::map<wxString, wxString> aPinMap ) : const std::map<wxString, wxString>& aPinMap ) :
m_ref( aRef ), m_ref( aRef ),
m_footprint( aFootprint ), m_footprint( aFootprint ),
m_value( aValue ), m_value( aValue ),
@ -71,11 +71,11 @@ public:
m_pinMap( aPinMap ) m_pinMap( aPinMap )
{} {}
wxString m_ref; wxString m_ref;
wxString m_footprint; wxString m_footprint;
wxString m_value; wxString m_value;
bool m_DNP; bool m_DNP;
bool m_excludeFromBOM; bool m_excludeFromBOM;
std::map<wxString, wxString> m_pinMap; std::map<wxString, wxString> m_pinMap;
}; };
@ -131,7 +131,7 @@ private:
*/ */
void applyChangelist(); void applyChangelist();
void processNetNameChange( const wxString& aRef, SCH_PIN* aPin, void processNetNameChange( SCHEMATIC_COMMIT* aCommit, const wxString& aRef, SCH_PIN* aPin,
const SCH_CONNECTION* aConnection, const wxString& aOldName, const SCH_CONNECTION* aConnection, const wxString& aOldName,
const wxString& aNewName ); const wxString& aNewName );
@ -152,7 +152,6 @@ private:
SCH_EDIT_FRAME* m_frame; SCH_EDIT_FRAME* m_frame;
int m_changesCount; // Number of user-level changes int m_changesCount; // Number of user-level changes
bool m_appendUndo;
}; };
#endif #endif

View File

@ -34,9 +34,7 @@
#include <tools/ee_selection_tool.h> #include <tools/ee_selection_tool.h>
#include <sch_edit_frame.h> #include <sch_edit_frame.h>
#include <sch_view.h> #include <sch_view.h>
#include <schematic_commit.h>
#include <symbol_edit_frame.h> #include <symbol_edit_frame.h>
#include <undo_redo_container.h>
class EE_SELECTION; class EE_SELECTION;
@ -92,9 +90,6 @@ public:
m_isSymbolEditor = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_frame ) != nullptr; m_isSymbolEditor = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_frame ) != nullptr;
} }
if( aReason != RUN )
m_commit = std::make_unique<SCHEMATIC_COMMIT>( m_toolMgr );
m_view = static_cast<KIGFX::SCH_VIEW*>( getView() ); m_view = static_cast<KIGFX::SCH_VIEW*>( getView() );
} }
@ -201,8 +196,6 @@ protected:
KIGFX::SCH_VIEW* m_view; KIGFX::SCH_VIEW* m_view;
EE_SELECTION_TOOL* m_selectionTool; EE_SELECTION_TOOL* m_selectionTool;
bool m_isSymbolEditor; bool m_isSymbolEditor;
std::unique_ptr<SCHEMATIC_COMMIT> m_commit;
}; };

View File

@ -47,6 +47,7 @@
#include <sch_sheet_pin.h> #include <sch_sheet_pin.h>
#include <sch_bitmap.h> #include <sch_bitmap.h>
#include <schematic.h> #include <schematic.h>
#include <schematic_commit.h>
#include <symbol_library_common.h> #include <symbol_library_common.h>
#include <eeschema_settings.h> #include <eeschema_settings.h>
#include <dialogs/dialog_label_properties.h> #include <dialogs/dialog_label_properties.h>
@ -110,6 +111,7 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
std::vector<PICKED_SYMBOL>* historyList = nullptr; std::vector<PICKED_SYMBOL>* historyList = nullptr;
bool ignorePrimePosition = false; bool ignorePrimePosition = false;
COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings(); COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
SCHEMATIC_COMMIT commit( m_toolMgr );
EE_GRID_HELPER grid( m_toolMgr ); EE_GRID_HELPER grid( m_toolMgr );
if( m_inPlaceSymbol ) if( m_inPlaceSymbol )
@ -147,7 +149,7 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
m_frame->PushTool( aEvent ); m_frame->PushTool( aEvent );
auto addSymbol = auto addSymbol =
[&]( SCH_SYMBOL* aSymbol ) [this]( SCHEMATIC_COMMIT* aCommit, SCH_SYMBOL* aSymbol )
{ {
m_frame->SaveCopyForRepeatItem( aSymbol ); m_frame->SaveCopyForRepeatItem( aSymbol );
@ -156,9 +158,9 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
aSymbol->SetParent( m_frame->GetScreen() ); aSymbol->SetParent( m_frame->GetScreen() );
aSymbol->SetFlags( IS_NEW | IS_MOVING ); aSymbol->SetFlags( IS_NEW | IS_MOVING );
m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), aSymbol, false ); m_frame->AddItemToCommitAndScreen( aCommit, m_frame->GetScreen(), aSymbol );
// Set IS_MOVING again, as AddItemToScreenAndUndoList() will have cleared it. // Set IS_MOVING again, as AddItemToCommitAndScreen() will have cleared it.
aSymbol->SetFlags( IS_MOVING ); aSymbol->SetFlags( IS_MOVING );
m_toolMgr->RunAction( ACTIONS::refreshPreview ); m_toolMgr->RunAction( ACTIONS::refreshPreview );
}; };
@ -222,7 +224,7 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
// Prime the pump // Prime the pump
if( symbol ) if( symbol )
{ {
addSymbol( symbol ); addSymbol( &commit, symbol );
annotate(); annotate();
getViewControls()->WarpMouseCursor( getViewControls()->GetMousePosition( false ) ); getViewControls()->WarpMouseCursor( getViewControls()->GetMousePosition( false ) );
} }
@ -323,7 +325,7 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
symbol = new SCH_SYMBOL( *libSymbol, &m_frame->GetCurrentSheet(), sel, cursorPos, symbol = new SCH_SYMBOL( *libSymbol, &m_frame->GetCurrentSheet(), sel, cursorPos,
&m_frame->Schematic() ); &m_frame->Schematic() );
addSymbol( symbol ); addSymbol( &commit, symbol );
annotate(); annotate();
// Update the list of references for the next symbol placement. // Update the list of references for the next symbol placement.
@ -348,10 +350,10 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
m_frame->GetScreen()->Update( symbol ); m_frame->GetScreen()->Update( symbol );
SCH_LINE_WIRE_BUS_TOOL* lwbTool = m_toolMgr->GetTool<SCH_LINE_WIRE_BUS_TOOL>(); SCH_LINE_WIRE_BUS_TOOL* lwbTool = m_toolMgr->GetTool<SCH_LINE_WIRE_BUS_TOOL>();
lwbTool->TrimOverLappingWires( &m_selectionTool->GetSelection() ); lwbTool->TrimOverLappingWires( &commit, &m_selectionTool->GetSelection() );
lwbTool->AddJunctionsIfNeeded( &m_selectionTool->GetSelection() ); lwbTool->AddJunctionsIfNeeded( &commit, &m_selectionTool->GetSelection() );
m_frame->OnModify(); commit.Push( _( "Add Symbol" ) );
SCH_SYMBOL* nextSymbol = nullptr; SCH_SYMBOL* nextSymbol = nullptr;
@ -381,8 +383,8 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
if( new_unit == 1 ) if( new_unit == 1 )
nextSymbol->ClearAnnotation( nullptr, false ); nextSymbol->ClearAnnotation( nullptr, false );
addSymbol( nextSymbol ); addSymbol( &commit, nextSymbol );
symbol = nextSymbol; // annotate() looks at symbol, update it symbol = nextSymbol;
annotate(); annotate();
// Update the list of references for the next symbol placement. // Update the list of references for the next symbol placement.
@ -641,7 +643,10 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
} }
else else
{ {
m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), image, false ); SCHEMATIC_COMMIT commit( m_toolMgr );
m_frame->AddItemToCommitAndScreen( &commit, m_frame->GetScreen(), image );
commit.Push( _( "Add Image" ) );
image = nullptr; image = nullptr;
m_toolMgr->RunAction( ACTIONS::activatePointEditor ); m_toolMgr->RunAction( ACTIONS::activatePointEditor );
@ -700,6 +705,7 @@ int SCH_DRAWING_TOOLS::SingleClickPlace( const TOOL_EVENT& aEvent )
KIGFX::VIEW_CONTROLS* controls = getViewControls(); KIGFX::VIEW_CONTROLS* controls = getViewControls();
SCH_ITEM* previewItem; SCH_ITEM* previewItem;
bool loggedInfoBarError = false; bool loggedInfoBarError = false;
wxString description;
if( m_inSingleClickPlace ) if( m_inSingleClickPlace )
return 0; return 0;
@ -725,16 +731,19 @@ int SCH_DRAWING_TOOLS::SingleClickPlace( const TOOL_EVENT& aEvent )
case SCH_NO_CONNECT_T: case SCH_NO_CONNECT_T:
previewItem = new SCH_NO_CONNECT( cursorPos ); previewItem = new SCH_NO_CONNECT( cursorPos );
previewItem->SetParent( m_frame->GetScreen() ); previewItem->SetParent( m_frame->GetScreen() );
description = _( "Add No Connect Flag" );
break; break;
case SCH_JUNCTION_T: case SCH_JUNCTION_T:
previewItem = new SCH_JUNCTION( cursorPos ); previewItem = new SCH_JUNCTION( cursorPos );
previewItem->SetParent( m_frame->GetScreen() ); previewItem->SetParent( m_frame->GetScreen() );
description = _( "Add Junction" );
break; break;
case SCH_BUS_WIRE_ENTRY_T: case SCH_BUS_WIRE_ENTRY_T:
previewItem = new SCH_BUS_WIRE_ENTRY( cursorPos ); previewItem = new SCH_BUS_WIRE_ENTRY( cursorPos );
previewItem->SetParent( m_frame->GetScreen() ); previewItem->SetParent( m_frame->GetScreen() );
description = _( "Add Wire to Bus Entry" );
break; break;
default: default:
@ -824,14 +833,15 @@ int SCH_DRAWING_TOOLS::SingleClickPlace( const TOOL_EVENT& aEvent )
newItem->SetPosition( cursorPos ); newItem->SetPosition( cursorPos );
newItem->SetFlags( IS_NEW ); newItem->SetFlags( IS_NEW );
m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), newItem, false ); SCHEMATIC_COMMIT commit( m_toolMgr );
m_frame->AddItemToCommitAndScreen( &commit, m_frame->GetScreen(), newItem );
if( type == SCH_JUNCTION_T ) if( type == SCH_JUNCTION_T )
m_frame->TestDanglingEnds(); m_frame->TestDanglingEnds();
else else
m_frame->SchematicCleanUp(); m_frame->SchematicCleanUp( &commit );
m_frame->OnModify(); commit.Push( description );
} }
if( evt->IsDblClick( BUT_LEFT ) || type == SCH_SHEET_PIN_T ) // Finish tool. if( evt->IsDblClick( BUT_LEFT ) || type == SCH_SHEET_PIN_T ) // Finish tool.
@ -890,10 +900,7 @@ int SCH_DRAWING_TOOLS::SingleClickPlace( const TOOL_EVENT& aEvent )
DIALOG_WIRE_BUS_PROPERTIES dlg( m_frame, strokeItems ); DIALOG_WIRE_BUS_PROPERTIES dlg( m_frame, strokeItems );
if( dlg.ShowModal() == wxID_OK ) if( dlg.ShowModal() == wxID_OK )
{
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified ); m_toolMgr->PostEvent( EVENTS::SelectedItemsModified );
m_frame->OnModify();
}
} }
break; break;
@ -905,10 +912,7 @@ int SCH_DRAWING_TOOLS::SingleClickPlace( const TOOL_EVENT& aEvent )
DIALOG_JUNCTION_PROPS dlg( m_frame, junctions ); DIALOG_JUNCTION_PROPS dlg( m_frame, junctions );
if( dlg.ShowModal() == wxID_OK ) if( dlg.ShowModal() == wxID_OK )
{
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified ); m_toolMgr->PostEvent( EVENTS::SelectedItemsModified );
m_frame->OnModify();
}
} }
break; break;
default: default:
@ -1115,6 +1119,7 @@ int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
bool ignorePrimePosition = false; bool ignorePrimePosition = false;
COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings(); COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
SCH_SHEET* sheet = nullptr; SCH_SHEET* sheet = nullptr;
wxString description;
if( m_inTwoClickPlace ) if( m_inTwoClickPlace )
return 0; return 0;
@ -1293,10 +1298,12 @@ int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
if( isText ) if( isText )
{ {
item = createNewText( cursorPos, LAYER_NOTES ); item = createNewText( cursorPos, LAYER_NOTES );
description = _( "Add Text" );
} }
else if( isHierLabel ) else if( isHierLabel )
{ {
item = createNewText( cursorPos, LAYER_HIERLABEL ); item = createNewText( cursorPos, LAYER_HIERLABEL );
description = _( "Add Hierarchical Label" );
} }
else if( isNetLabel || isGlobalLabel ) else if( isNetLabel || isGlobalLabel )
{ {
@ -1356,10 +1363,13 @@ int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
labelItem->SetText( netName ); labelItem->SetText( netName );
item = labelItem; item = labelItem;
} }
description = _( "Add Label" );
} }
else if( isClassLabel ) else if( isClassLabel )
{ {
item = createNewText( cursorPos, LAYER_NETCLASS_REFS ); item = createNewText( cursorPos, LAYER_NETCLASS_REFS );
description = _( "Add Label" );
} }
else if( isSheetPin ) else if( isSheetPin )
{ {
@ -1387,6 +1397,8 @@ int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
break; break;
} }
} }
description = _( "Add Sheet Pin" );
} }
// If we started with a hotkey which has a position then warp back to that. // If we started with a hotkey which has a position then warp back to that.
@ -1426,9 +1438,12 @@ int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
else // ... and second click places: else // ... and second click places:
{ {
item->ClearFlags( IS_MOVING ); item->ClearFlags( IS_MOVING );
m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), item, false );
item = nullptr;
SCHEMATIC_COMMIT commit( m_toolMgr );
m_frame->AddItemToCommitAndScreen( &commit, m_frame->GetScreen(), item );
commit.Push( description );
item = nullptr;
m_view->ClearPreview(); m_view->ClearPreview();
// Exit the tool when this sheet runs out of pins for convenience // Exit the tool when this sheet runs out of pins for convenience
@ -1502,6 +1517,7 @@ int SCH_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
SCH_SHAPE* item = nullptr; SCH_SHAPE* item = nullptr;
bool isTextBox = aEvent.IsAction( &EE_ACTIONS::drawTextBox ); bool isTextBox = aEvent.IsAction( &EE_ACTIONS::drawTextBox );
SHAPE_T type = aEvent.Parameter<SHAPE_T>(); SHAPE_T type = aEvent.Parameter<SHAPE_T>();
wxString description;
if( m_inDrawShape ) if( m_inDrawShape )
return 0; return 0;
@ -1611,6 +1627,7 @@ int SCH_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
textbox->SetParent( schematic ); textbox->SetParent( schematic );
item = textbox; item = textbox;
description = _( "Add Text Box" );
} }
else else
{ {
@ -1619,6 +1636,7 @@ int SCH_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
item->SetStroke( m_lastStroke ); item->SetStroke( m_lastStroke );
item->SetFillColor( m_lastFillColor ); item->SetFillColor( m_lastFillColor );
item->SetParent( schematic ); item->SetParent( schematic );
description = wxString::Format( _( "Add %s" ), item->EDA_SHAPE::GetFriendlyName() );
} }
item->SetFlags( IS_NEW ); item->SetFlags( IS_NEW );
@ -1670,7 +1688,10 @@ int SCH_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
m_lastFillColor = item->GetFillColor(); m_lastFillColor = item->GetFillColor();
} }
m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), item, false ); SCHEMATIC_COMMIT commit( m_toolMgr );
commit.Added( item, m_frame->GetScreen() );
commit.Push( wxString::Format( _( "Draw %s" ), item->GetClass() ) );
m_selectionTool->AddItemToSel( item ); m_selectionTool->AddItemToSel( item );
item = nullptr; item = nullptr;
@ -1859,7 +1880,10 @@ int SCH_DRAWING_TOOLS::DrawSheet( const TOOL_EVENT& aEvent )
{ {
sheet->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false ); sheet->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), sheet, false ); SCHEMATIC_COMMIT commit( m_toolMgr );
m_frame->AddItemToCommitAndScreen( &commit, m_frame->GetScreen(), sheet );
commit.Push( "Draw Sheet" );
m_frame->UpdateHierarchyNavigator(); m_frame->UpdateHierarchyNavigator();
m_selectionTool->AddItemToSel( sheet ); m_selectionTool->AddItemToSel( sheet );
} }

View File

@ -671,10 +671,15 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
if( selection.GetSize() == 0 ) if( selection.GetSize() == 0 )
return 0; return 0;
SCH_ITEM* head = nullptr; SCH_ITEM* head = nullptr;
int principalItemCount = 0; // User-selected items (as opposed to connected wires) int principalItemCount = 0; // User-selected items (as opposed to connected wires)
VECTOR2I rotPoint; VECTOR2I rotPoint;
bool moving = false; bool moving = false;
SCHEMATIC_COMMIT localInstance( m_toolMgr );
SCHEMATIC_COMMIT* commit = aEvent.Parameter<SCHEMATIC_COMMIT*>();
if( !commit )
commit = &localInstance;
for( unsigned ii = 0; ii < selection.GetSize(); ii++ ) for( unsigned ii = 0; ii < selection.GetSize(); ii++ )
{ {
@ -702,7 +707,7 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
rotPoint = m_frame->GetNearestHalfGridPosition( head->GetBoundingBox().GetCenter() ); rotPoint = m_frame->GetNearestHalfGridPosition( head->GetBoundingBox().GetCenter() );
if( !moving ) if( !moving )
saveCopyInUndoList( head, UNDO_REDO::CHANGED ); commit->Modify( head, m_frame->GetScreen() );
switch( head->Type() ) switch( head->Type() )
{ {
@ -830,9 +835,9 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
rotPoint = m_frame->GetNearestHalfGridPosition( selection.GetCenter() ); rotPoint = m_frame->GetNearestHalfGridPosition( selection.GetCenter() );
} }
for( unsigned ii = 0; ii < selection.GetSize(); ii++ ) for( EDA_ITEM* edaItem : selection )
{ {
SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.GetItem( ii ) ); SCH_ITEM* item = static_cast<SCH_ITEM*>( edaItem );
// We've already rotated the user selected item if there was only one. We're just // We've already rotated the user selected item if there was only one. We're just
// here to rotate the ends of wires that were attached to it. // here to rotate the ends of wires that were attached to it.
@ -840,7 +845,7 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
continue; continue;
if( !moving ) if( !moving )
saveCopyInUndoList( item, UNDO_REDO::CHANGED, ii > 0 ); commit->Modify( item, m_frame->GetScreen() );
for( int i = 0; clockwise ? i < 3 : i < 1; ++i ) for( int i = 0; clockwise ? i < 3 : i < 1; ++i )
{ {
@ -916,13 +921,14 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true ); m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
SCH_LINE_WIRE_BUS_TOOL* lwbTool = m_toolMgr->GetTool<SCH_LINE_WIRE_BUS_TOOL>(); SCH_LINE_WIRE_BUS_TOOL* lwbTool = m_toolMgr->GetTool<SCH_LINE_WIRE_BUS_TOOL>();
lwbTool->TrimOverLappingWires( &selectionCopy ); lwbTool->TrimOverLappingWires( commit, &selectionCopy );
lwbTool->AddJunctionsIfNeeded( &selectionCopy ); lwbTool->AddJunctionsIfNeeded( commit, &selectionCopy );
m_frame->SchematicCleanUp(); m_frame->SchematicCleanUp( commit );
m_frame->TestDanglingEnds(); m_frame->TestDanglingEnds();
m_frame->OnModify(); if( !localInstance.Empty() )
localInstance.Push( _( "Rotate" ) );
} }
return 0; return 0;
@ -936,15 +942,20 @@ int SCH_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
if( selection.GetSize() == 0 ) if( selection.GetSize() == 0 )
return 0; return 0;
bool vertical = ( aEvent.Matches( EE_ACTIONS::mirrorV.MakeEvent() ) ); bool vertical = ( aEvent.Matches( EE_ACTIONS::mirrorV.MakeEvent() ) );
SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.Front() ); SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.Front() );
bool connections = false; bool connections = false;
bool moving = item->IsMoving(); bool moving = item->IsMoving();
SCHEMATIC_COMMIT localInstance( m_toolMgr );
SCHEMATIC_COMMIT* commit = aEvent.Parameter<SCHEMATIC_COMMIT*>();
if( !commit )
commit = &localInstance;
if( selection.GetSize() == 1 ) if( selection.GetSize() == 1 )
{ {
if( !moving ) if( !moving )
saveCopyInUndoList( item, UNDO_REDO::CHANGED ); commit->Modify( item, m_frame->GetScreen() );
switch( item->Type() ) switch( item->Type() )
{ {
@ -1040,12 +1051,12 @@ int SCH_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
{ {
VECTOR2I mirrorPoint = m_frame->GetNearestHalfGridPosition( selection.GetCenter() ); VECTOR2I mirrorPoint = m_frame->GetNearestHalfGridPosition( selection.GetCenter() );
for( unsigned ii = 0; ii < selection.GetSize(); ii++ ) for( EDA_ITEM* edaItem : selection )
{ {
item = static_cast<SCH_ITEM*>( selection.GetItem( ii ) ); item = static_cast<SCH_ITEM*>( edaItem );
if( !moving ) if( !moving )
saveCopyInUndoList( item, UNDO_REDO::CHANGED, ii > 0 ); commit->Modify( item, m_frame->GetScreen() );
if( item->Type() == SCH_SHEET_PIN_T ) if( item->Type() == SCH_SHEET_PIN_T )
{ {
@ -1110,14 +1121,15 @@ int SCH_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
if( connections ) if( connections )
{ {
SCH_LINE_WIRE_BUS_TOOL* lwbTool = m_toolMgr->GetTool<SCH_LINE_WIRE_BUS_TOOL>(); SCH_LINE_WIRE_BUS_TOOL* lwbTool = m_toolMgr->GetTool<SCH_LINE_WIRE_BUS_TOOL>();
lwbTool->TrimOverLappingWires( &selectionCopy ); lwbTool->TrimOverLappingWires( commit, &selectionCopy );
lwbTool->AddJunctionsIfNeeded( &selectionCopy ); lwbTool->AddJunctionsIfNeeded( commit, &selectionCopy );
m_frame->SchematicCleanUp(); m_frame->SchematicCleanUp( commit );
m_frame->TestDanglingEnds(); m_frame->TestDanglingEnds();
} }
m_frame->OnModify(); if( !localInstance.Empty() )
localInstance.Push( _( "Mirror" ) );
} }
return 0; return 0;
@ -1235,8 +1247,8 @@ int SCH_EDIT_TOOL::RepeatDrawItem( const TOOL_EVENT& aEvent )
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true ); m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
bool appendUndo = false; SCHEMATIC_COMMIT commit( m_toolMgr );
EE_SELECTION newItems; EE_SELECTION newItems;
for( const std::unique_ptr<SCH_ITEM>& item : sourceItems ) for( const std::unique_ptr<SCH_ITEM>& item : sourceItems )
{ {
@ -1266,8 +1278,7 @@ int SCH_EDIT_TOOL::RepeatDrawItem( const TOOL_EVENT& aEvent )
m_toolMgr->RunAction( EE_ACTIONS::addItemToSel, true, newItem ); m_toolMgr->RunAction( EE_ACTIONS::addItemToSel, true, newItem );
newItem->SetFlags( IS_NEW ); newItem->SetFlags( IS_NEW );
m_frame->AddToScreen( newItem, m_frame->GetScreen() ); m_frame->AddToScreen( newItem, m_frame->GetScreen() );
m_frame->SaveCopyInUndoList( m_frame->GetScreen(), newItem, UNDO_REDO::NEWITEM, appendUndo ); commit.Added( newItem, m_frame->GetScreen() );
appendUndo = true;
if( newItem->Type() == SCH_SYMBOL_T ) if( newItem->Type() == SCH_SYMBOL_T )
{ {
@ -1279,13 +1290,19 @@ int SCH_EDIT_TOOL::RepeatDrawItem( const TOOL_EVENT& aEvent )
{ {
static_cast<SCH_SYMBOL*>( newItem )->ClearAnnotation( nullptr, false ); static_cast<SCH_SYMBOL*>( newItem )->ClearAnnotation( nullptr, false );
NULL_REPORTER reporter; NULL_REPORTER reporter;
m_frame->AnnotateSymbols( ANNOTATE_SELECTION, m_frame->AnnotateSymbols( &commit, ANNOTATE_SELECTION,
(ANNOTATE_ORDER_T) annotate.sort_order, (ANNOTATE_ORDER_T) annotate.sort_order,
(ANNOTATE_ALGO_T) annotate.method, true /* recursive */, (ANNOTATE_ALGO_T) annotate.method, true /* recursive */,
annotateStartNum, false, false, reporter, appendUndo ); annotateStartNum, false, false, reporter );
} }
m_toolMgr->RunAction( EE_ACTIONS::move, true ); m_toolMgr->RunAction( EE_ACTIONS::move, true, &commit );
while( m_toolMgr->GetTool<SCH_MOVE_TOOL>()->IsToolActive() )
{
wxMilliSleep( 50 );
wxYield();
}
} }
newItems.Add( newItem ); newItems.Add( newItem );
@ -1296,15 +1313,17 @@ int SCH_EDIT_TOOL::RepeatDrawItem( const TOOL_EVENT& aEvent )
if( !newItems.Empty() ) if( !newItems.Empty() )
{ {
SCH_LINE_WIRE_BUS_TOOL* lwbTool = m_toolMgr->GetTool<SCH_LINE_WIRE_BUS_TOOL>(); SCH_LINE_WIRE_BUS_TOOL* lwbTool = m_toolMgr->GetTool<SCH_LINE_WIRE_BUS_TOOL>();
lwbTool->TrimOverLappingWires( &newItems ); lwbTool->TrimOverLappingWires( &commit, &newItems );
lwbTool->AddJunctionsIfNeeded( &newItems ); lwbTool->AddJunctionsIfNeeded( &commit, &newItems );
m_frame->SchematicCleanUp(); m_frame->SchematicCleanUp( &commit );
m_frame->TestDanglingEnds(); m_frame->TestDanglingEnds();
} }
m_frame->GetCanvas()->Refresh(); m_frame->GetCanvas()->Refresh();
m_frame->OnModify();
if( !commit.Empty() )
commit.Push( _( "Repeat Item" ) );
if( !newItems.Empty() ) if( !newItems.Empty() )
m_frame->SaveCopyForRepeatItem( static_cast<SCH_ITEM*>( newItems[0] ) ); m_frame->SaveCopyForRepeatItem( static_cast<SCH_ITEM*>( newItems[0] ) );
@ -1343,7 +1362,7 @@ int SCH_EDIT_TOOL::DoDelete( const TOOL_EVENT& aEvent )
{ {
SCH_SCREEN* screen = m_frame->GetScreen(); SCH_SCREEN* screen = m_frame->GetScreen();
std::deque<EDA_ITEM*> items = m_selectionTool->RequestSelection( deletableItems ).GetItems(); std::deque<EDA_ITEM*> items = m_selectionTool->RequestSelection( deletableItems ).GetItems();
bool appendToUndo = false; SCHEMATIC_COMMIT commit( m_toolMgr );
std::vector<VECTOR2I> pts; std::vector<VECTOR2I> pts;
if( items.empty() ) if( items.empty() )
@ -1381,31 +1400,23 @@ int SCH_EDIT_TOOL::DoDelete( const TOOL_EVENT& aEvent )
if( !alg::contains( items, sheet ) ) if( !alg::contains( items, sheet ) )
{ {
pin->SetFlags( STRUCT_DELETED ); pin->SetFlags( STRUCT_DELETED );
saveCopyInUndoList( item, UNDO_REDO::DELETED, appendToUndo );
appendToUndo = true;
updateItem( pin, false ); updateItem( pin, false );
sheet->RemovePin( pin ); sheet->RemovePin( pin );
commit.Removed( pin, m_frame->GetScreen() );
} }
} }
else if( sch_item->Type() == SCH_FIELD_T ) else if( sch_item->Type() == SCH_FIELD_T )
{ {
saveCopyInUndoList( item, UNDO_REDO::CHANGED, appendToUndo ); commit.Modify( item, m_frame->GetScreen() );
static_cast<SCH_FIELD*>( sch_item )->SetVisible( false ); static_cast<SCH_FIELD*>( sch_item )->SetVisible( false );
appendToUndo = true;
updateItem( sch_item, false ); updateItem( sch_item, false );
} }
else else
{ {
sch_item->SetFlags( STRUCT_DELETED ); sch_item->SetFlags( STRUCT_DELETED );
saveCopyInUndoList( item, UNDO_REDO::DELETED, appendToUndo );
appendToUndo = true;
updateItem( sch_item, false ); updateItem( sch_item, false );
m_frame->RemoveFromScreen( sch_item, m_frame->GetScreen() ); m_frame->RemoveFromScreen( sch_item, m_frame->GetScreen() );
commit.Removed( item, m_frame->GetScreen() );
if( sch_item->Type() == SCH_SHEET_T ) if( sch_item->Type() == SCH_SHEET_T )
m_frame->UpdateHierarchyNavigator(); m_frame->UpdateHierarchyNavigator();
@ -1420,13 +1431,13 @@ int SCH_EDIT_TOOL::DoDelete( const TOOL_EVENT& aEvent )
continue; continue;
if( junction->HasFlag( STRUCT_DELETED ) || !screen->IsExplicitJunction( point ) ) if( junction->HasFlag( STRUCT_DELETED ) || !screen->IsExplicitJunction( point ) )
m_frame->DeleteJunction( junction, appendToUndo ); m_frame->DeleteJunction( &commit, junction );
} }
m_frame->TestDanglingEnds(); // m_frame->TestDanglingEnds();
m_frame->GetCanvas()->Refresh(); m_frame->GetCanvas()->Refresh();
m_frame->OnModify(); commit.Push( _( "Delete" ) );
return 0; return 0;
} }
@ -2329,15 +2340,19 @@ int SCH_EDIT_TOOL::ChangeTextType( const TOOL_EVENT& aEvent )
if( selected ) if( selected )
m_toolMgr->RunAction( EE_ACTIONS::removeItemFromSel, true, item ); m_toolMgr->RunAction( EE_ACTIONS::removeItemFromSel, true, item );
SCHEMATIC_COMMIT commit( m_toolMgr );
if( !item->IsNew() ) if( !item->IsNew() )
{ {
saveCopyInUndoList( item, UNDO_REDO::DELETED, i != 0 );
saveCopyInUndoList( newtext, UNDO_REDO::NEWITEM, true );
m_frame->RemoveFromScreen( item, m_frame->GetScreen() ); m_frame->RemoveFromScreen( item, m_frame->GetScreen() );
commit.Removed( item, m_frame->GetScreen() );
m_frame->AddToScreen( newtext, m_frame->GetScreen() ); m_frame->AddToScreen( newtext, m_frame->GetScreen() );
commit.Added( newtext, m_frame->GetScreen() );
} }
commit.Push( _( "Change Item Type" ) );
if( selected ) if( selected )
m_toolMgr->RunAction( EE_ACTIONS::addItemToSel, true, newtext ); m_toolMgr->RunAction( EE_ACTIONS::addItemToSel, true, newtext );
@ -2372,6 +2387,8 @@ int SCH_EDIT_TOOL::BreakWire( const TOOL_EVENT& aEvent )
VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !aEvent.DisableGridSnapping() ); VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !aEvent.DisableGridSnapping() );
EE_SELECTION& selection = m_selectionTool->RequestSelection( { SCH_LINE_T } ); EE_SELECTION& selection = m_selectionTool->RequestSelection( { SCH_LINE_T } );
SCH_SCREEN* screen = m_frame->GetScreen();
SCHEMATIC_COMMIT commit( m_toolMgr );
std::vector<SCH_LINE*> lines; std::vector<SCH_LINE*> lines;
for( EDA_ITEM* item : selection ) for( EDA_ITEM* item : selection )
@ -2384,7 +2401,6 @@ int SCH_EDIT_TOOL::BreakWire( const TOOL_EVENT& aEvent )
} }
m_selectionTool->ClearSelection(); m_selectionTool->ClearSelection();
m_frame->StartNewUndo();
for( SCH_LINE* line : lines ) for( SCH_LINE* line : lines )
{ {
@ -2392,9 +2408,9 @@ int SCH_EDIT_TOOL::BreakWire( const TOOL_EVENT& aEvent )
// We let the user select the break point if they're on a single line // We let the user select the break point if they're on a single line
if( lines.size() == 1 && line->HitTest( cursorPos ) ) if( lines.size() == 1 && line->HitTest( cursorPos ) )
m_frame->BreakSegment( line, cursorPos, &newLine ); m_frame->BreakSegment( &commit, line, cursorPos, &newLine, screen );
else else
m_frame->BreakSegment( line, line->GetMidPoint(), &newLine ); m_frame->BreakSegment( &commit, line, line->GetMidPoint(), &newLine, screen );
// Make sure both endpoints are deselected // Make sure both endpoints are deselected
newLine->ClearFlags(); newLine->ClearFlags();
@ -2417,11 +2433,18 @@ int SCH_EDIT_TOOL::BreakWire( const TOOL_EVENT& aEvent )
if( !lines.empty() ) if( !lines.empty() )
{ {
m_frame->TestDanglingEnds(); m_frame->TestDanglingEnds();
m_frame->OnModify();
m_frame->GetCanvas()->Refresh(); m_frame->GetCanvas()->Refresh();
m_toolMgr->RunAction( EE_ACTIONS::drag, false, true ); m_toolMgr->RunAction( EE_ACTIONS::drag, true, &commit );
while( m_toolMgr->GetTool<SCH_MOVE_TOOL>()->IsToolActive() )
{
wxMilliSleep( 50 );
wxYield();
}
if( !commit.Empty() )
commit.Push( isSlice ? _( "Slice Wire" ) : _( "Break Wire" ) );
} }
return 0; return 0;

View File

@ -31,12 +31,12 @@
#include <dialogs/dialog_plot_schematic.h> #include <dialogs/dialog_plot_schematic.h>
#include <dialogs/dialog_symbol_remap.h> #include <dialogs/dialog_symbol_remap.h>
#include <dialogs/dialog_assign_netclass.h> #include <dialogs/dialog_assign_netclass.h>
#include <dialogs/dialog_update_from_pcb.h>
#include <project_rescue.h> #include <project_rescue.h>
#include <erc.h> #include <erc.h>
#include <invoke_sch_dialog.h> #include <invoke_sch_dialog.h>
#include <string_utils.h> #include <string_utils.h>
#include <kiway.h> #include <kiway.h>
#include <kiway_player.h>
#include <netlist_exporters/netlist_exporter_spice.h> #include <netlist_exporters/netlist_exporter_spice.h>
#include <paths.h> #include <paths.h>
#include <project/project_file.h> #include <project/project_file.h>
@ -52,11 +52,11 @@
#include <sch_sheet_pin.h> #include <sch_sheet_pin.h>
#include <sch_view.h> #include <sch_view.h>
#include <schematic.h> #include <schematic.h>
#include <advanced_config.h> #include <schematic_commit.h>
#include <sim/simulator_frame.h> #include <sim/simulator_frame.h>
#include <sim/spice_generator.h> #include <sim/spice_generator.h>
#include <sim/sim_lib_mgr.h> #include <sim/sim_lib_mgr.h>
#include "symbol_library_manager.h" #include <symbol_library_manager.h>
#include <symbol_viewer_frame.h> #include <symbol_viewer_frame.h>
#include <tool/picker_tool.h> #include <tool/picker_tool.h>
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
@ -64,8 +64,8 @@
#include <tools/ee_selection.h> #include <tools/ee_selection.h>
#include <tools/ee_selection_tool.h> #include <tools/ee_selection_tool.h>
#include <tools/sch_editor_control.h> #include <tools/sch_editor_control.h>
#include <tools/sch_move_tool.h>
#include <drawing_sheet/ds_proxy_undo_item.h> #include <drawing_sheet/ds_proxy_undo_item.h>
#include <dialog_update_from_pcb.h>
#include <eda_list_dialog.h> #include <eda_list_dialog.h>
#include <wildcards_and_files_ext.h> #include <wildcards_and_files_ext.h>
#include <wx_filename.h> #include <wx_filename.h>
@ -247,7 +247,7 @@ bool SCH_EDITOR_CONTROL::rescueProject( RESCUER& aRescuer, bool aRunningOnDemand
SCH_SCREENS schematic( m_frame->Schematic().Root() ); SCH_SCREENS schematic( m_frame->Schematic().Root() );
schematic.UpdateSymbolLinks(); schematic.UpdateSymbolLinks();
m_frame->RecalculateConnections( GLOBAL_CLEANUP ); m_frame->RecalculateConnections( nullptr, GLOBAL_CLEANUP );
} }
m_frame->ClearUndoRedoList(); m_frame->ClearUndoRedoList();
@ -780,9 +780,7 @@ static bool highlightNet( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition )
if( item ) if( item )
{ {
if( item->IsConnectivityDirty() ) if( item->IsConnectivityDirty() )
{ editFrame->RecalculateConnections( nullptr, NO_CLEANUP );
editFrame->RecalculateConnections( NO_CLEANUP );
}
if( item->Type() == SCH_FIELD_T ) if( item->Type() == SCH_FIELD_T )
symbol = dynamic_cast<SCH_SYMBOL*>( item->GetParent() ); symbol = dynamic_cast<SCH_SYMBOL*>( item->GetParent() );
@ -1529,18 +1527,19 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
// SCH_SEXP_PLUGIN added the items to the paste screen, but not to the view or anything // SCH_SEXP_PLUGIN added the items to the paste screen, but not to the view or anything
// else. Pull them back out to start with. // else. Pull them back out to start with.
EDA_ITEMS loadedItems; SCHEMATIC_COMMIT commit( m_toolMgr );
bool sheetsPasted = false; EDA_ITEMS loadedItems;
SCH_SHEET_LIST hierarchy = m_frame->Schematic().GetSheets(); bool sheetsPasted = false;
SCH_SHEET_PATH& pasteRoot = m_frame->GetCurrentSheet(); SCH_SHEET_LIST hierarchy = m_frame->Schematic().GetSheets();
wxFileName destFn = pasteRoot.Last()->GetFileName(); SCH_SHEET_PATH& pasteRoot = m_frame->GetCurrentSheet();
wxFileName destFn = pasteRoot.Last()->GetFileName();
if( destFn.IsRelative() ) if( destFn.IsRelative() )
destFn.MakeAbsolute( m_frame->Prj().GetProjectPath() ); destFn.MakeAbsolute( m_frame->Prj().GetProjectPath() );
// List of paths in the hierarchy that refer to the destination sheet of the paste // List of paths in the hierarchy that refer to the destination sheet of the paste
SCH_SHEET_LIST pasteInstances = hierarchy.FindAllSheetsForScreen( pasteRoot.LastScreen() ); SCH_SHEET_LIST sheetPathsForScreen = hierarchy.FindAllSheetsForScreen( pasteRoot.LastScreen() );
pasteInstances.SortByPageNumbers(); sheetPathsForScreen.SortByPageNumbers();
// Build a list of screens from the current design (to avoid loading sheets that already exist) // Build a list of screens from the current design (to avoid loading sheets that already exist)
std::map<wxString, SCH_SCREEN*> loadedScreens; std::map<wxString, SCH_SCREEN*> loadedScreens;
@ -1594,9 +1593,8 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
// Remove the references from our temporary screen to prevent freeing on the DTOR // Remove the references from our temporary screen to prevent freeing on the DTOR
tempScreen->Clear( false ); tempScreen->Clear( false );
for( unsigned i = 0; i < loadedItems.size(); ++i ) for( EDA_ITEM* item : loadedItems )
{ {
EDA_ITEM* item = loadedItems[i];
KIID_PATH clipPath( wxT( "/" ) ); // clipboard is at root KIID_PATH clipPath( wxT( "/" ) ); // clipboard is at root
if( item->Type() == SCH_SYMBOL_T ) if( item->Type() == SCH_SYMBOL_T )
@ -1629,8 +1627,8 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
symbol->SetLibSymbol( libSymbol ); symbol->SetLibSymbol( libSymbol );
} }
for( SCH_SHEET_PATH& instance : pasteInstances ) for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
updatePastedSymbol( symbol, tempScreen, instance, clipPath, forceKeepAnnotations ); updatePastedSymbol( symbol, tempScreen, sheetPath, clipPath, forceKeepAnnotations );
// Assign a new KIID // Assign a new KIID
const_cast<KIID&>( item->m_Uuid ) = KIID(); const_cast<KIID&>( item->m_Uuid ) = KIID();
@ -1639,14 +1637,14 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
for( SCH_PIN* pin : symbol->GetPins() ) for( SCH_PIN* pin : symbol->GetPins() )
const_cast<KIID&>( pin->m_Uuid ) = KIID(); const_cast<KIID&>( pin->m_Uuid ) = KIID();
for( SCH_SHEET_PATH& instance : pasteInstances ) for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
{ {
// Ignore symbols from a non-existant library. // Ignore symbols from a non-existant library.
if( libSymbol ) if( libSymbol )
{ {
SCH_REFERENCE schReference( symbol, libSymbol, instance ); SCH_REFERENCE schReference( symbol, libSymbol, sheetPath );
schReference.SetSheetNumber( instance.GetVirtualPageNumber() ); schReference.SetSheetNumber( sheetPath.GetVirtualPageNumber() );
pastedSymbols[instance].AddItem( schReference ); pastedSymbols[sheetPath].AddItem( schReference );
} }
} }
} }
@ -1724,14 +1722,14 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
// Once we have our new KIID we can update all pasted instances. This will either // Once we have our new KIID we can update all pasted instances. This will either
// reset the annotations or copy "kept" annotations from the supplementary clipboard. // reset the annotations or copy "kept" annotations from the supplementary clipboard.
for( SCH_SHEET_PATH& instance : pasteInstances ) for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
{ {
SCH_SHEET_PATH sheetPath = updatePastedSheet( instance, clipPath, sheet, SCH_SHEET_PATH subPath = updatePastedSheet( sheetPath, clipPath, sheet,
( forceKeepAnnotations && annotate.automatic ), ( forceKeepAnnotations && annotate.automatic ),
&pastedSheets[instance], &pastedSheets[sheetPath],
&pastedSymbols[instance] ); &pastedSymbols[sheetPath] );
sheetPath.GetSymbols( pastedSymbols[instance] ); subPath.GetSymbols( pastedSymbols[sheetPath] );
} }
} }
else else
@ -1754,7 +1752,7 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
item->SetFlags( STARTPOINT | ENDPOINT ); item->SetFlags( STARTPOINT | ENDPOINT );
item->SetFlags( IS_NEW | IS_PASTED | IS_MOVING ); item->SetFlags( IS_NEW | IS_PASTED | IS_MOVING );
m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), (SCH_ITEM*) item, i > 0 ); m_frame->AddItemToCommitAndScreen( &commit, m_frame->GetScreen(), (SCH_ITEM*) item );
// Reset flags for subsequent move operation // Reset flags for subsequent move operation
item->SetFlags( IS_NEW | IS_PASTED | IS_MOVING ); item->SetFlags( IS_NEW | IS_PASTED | IS_MOVING );
@ -1764,16 +1762,16 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
getView()->Hide( item, true ); getView()->Hide( item, true );
} }
pasteInstances.SortByPageNumbers(); sheetPathsForScreen.SortByPageNumbers();
if( sheetsPasted ) if( sheetsPasted )
{ {
// Update page numbers: Find next free numeric page number // Update page numbers: Find next free numeric page number
for( SCH_SHEET_PATH& instance : pasteInstances ) for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
{ {
pastedSheets[instance].SortByPageNumbers(); pastedSheets[sheetPath].SortByPageNumbers();
for( SCH_SHEET_PATH& pastedSheet : pastedSheets[instance] ) for( SCH_SHEET_PATH& pastedSheet : pastedSheets[sheetPath] )
{ {
int page = 1; int page = 1;
wxString pageNum = wxString::Format( "%d", page ); wxString pageNum = wxString::Format( "%d", page );
@ -1797,7 +1795,7 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
std::map<SCH_SHEET_PATH, SCH_REFERENCE_LIST> annotatedSymbols; std::map<SCH_SHEET_PATH, SCH_REFERENCE_LIST> annotatedSymbols;
// Update the list of symbol instances that satisfy the annotation criteria. // Update the list of symbol instances that satisfy the annotation criteria.
for( const SCH_SHEET_PATH& sheetPath : pasteInstances ) for( const SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
{ {
for( size_t i = 0; i < pastedSymbols[sheetPath].GetCount(); i++ ) for( size_t i = 0; i < pastedSymbols[sheetPath].GetCount(); i++ )
{ {
@ -1812,24 +1810,27 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
if( !annotatedSymbols.empty() ) if( !annotatedSymbols.empty() )
{ {
for( SCH_SHEET_PATH& instance : pasteInstances ) for( SCH_SHEET_PATH& path : sheetPathsForScreen )
{ {
annotatedSymbols[instance].SortByReferenceOnly(); annotatedSymbols[path].SortByReferenceOnly();
if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS ) if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS )
annotatedSymbols[instance].ReannotateDuplicates( existingRefs ); {
annotatedSymbols[path].ReannotateDuplicates( existingRefs );
}
else else
annotatedSymbols[instance].ReannotateByOptions( (ANNOTATE_ORDER_T) annotate.sort_order, {
(ANNOTATE_ALGO_T) annotate.method, annotatedSymbols[path].ReannotateByOptions( (ANNOTATE_ORDER_T) annotate.sort_order,
annotateStartNum, existingRefs, (ANNOTATE_ALGO_T) annotate.method,
false, annotateStartNum, existingRefs, false,
&hierarchy ); &hierarchy );
}
annotatedSymbols[instance].UpdateAnnotation(); annotatedSymbols[path].UpdateAnnotation();
// Update existing refs for next iteration // Update existing refs for next iteration
for( size_t i = 0; i < annotatedSymbols[instance].GetCount(); i++ ) for( size_t i = 0; i < annotatedSymbols[path].GetCount(); i++ )
existingRefs.AddItem( annotatedSymbols[instance][i] ); existingRefs.AddItem( annotatedSymbols[path][i] );
} }
} }
@ -1935,7 +1936,16 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
selection.SetReferencePoint( item->GetPosition() ); selection.SetReferencePoint( item->GetPosition() );
} }
m_toolMgr->RunAction( EE_ACTIONS::move, false ); m_toolMgr->RunAction( EE_ACTIONS::move, true, &commit );
while( m_toolMgr->GetTool<SCH_MOVE_TOOL>()->IsToolActive() )
{
wxMilliSleep( 50 );
wxYield();
}
if( !commit.Empty() )
commit.Push( _( "Paste" ) );
} }
return 0; return 0;
@ -2071,7 +2081,7 @@ int SCH_EDITOR_CONTROL::GenerateBOM( const TOOL_EVENT& aEvent )
int SCH_EDITOR_CONTROL::DrawSheetOnClipboard( const TOOL_EVENT& aEvent ) int SCH_EDITOR_CONTROL::DrawSheetOnClipboard( const TOOL_EVENT& aEvent )
{ {
m_frame->RecalculateConnections( LOCAL_CLEANUP ); m_frame->RecalculateConnections( nullptr, LOCAL_CLEANUP );
m_frame->DrawCurrentSheetToClipboard(); m_frame->DrawCurrentSheetToClipboard();
return 0; return 0;
} }

View File

@ -35,9 +35,6 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <eda_item.h>
#include <bitmaps.h>
#include <core/typeinfo.h>
#include <layer_ids.h> #include <layer_ids.h>
#include <math/vector2d.h> #include <math/vector2d.h>
#include <advanced_config.h> #include <advanced_config.h>
@ -47,18 +44,16 @@
#include <tool/selection_conditions.h> #include <tool/selection_conditions.h>
#include <tool/tool_event.h> #include <tool/tool_event.h>
#include <trigo.h> #include <trigo.h>
#include <undo_redo_container.h>
#include <connection_graph.h>
#include <eeschema_id.h> #include <eeschema_id.h>
#include <sch_bus_entry.h> #include <sch_bus_entry.h>
#include <sch_connection.h> #include <sch_connection.h>
#include <sch_edit_frame.h> #include <sch_edit_frame.h>
#include <sch_item.h>
#include <sch_line.h> #include <sch_line.h>
#include <sch_screen.h> #include <sch_screen.h>
#include <sch_sheet.h> #include <sch_sheet.h>
#include <sch_sheet_pin.h> #include <sch_sheet_pin.h>
#include <schematic.h> #include <schematic.h>
#include <schematic_commit.h>
#include <ee_actions.h> #include <ee_actions.h>
#include <ee_grid_helper.h> #include <ee_grid_helper.h>
#include <ee_selection.h> #include <ee_selection.h>
@ -819,8 +814,10 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const TOOL_EVENT& aTool, int aType,
if( evt->IsDblClick( BUT_LEFT ) && segment ) if( evt->IsDblClick( BUT_LEFT ) && segment )
{ {
if( twoSegments && m_wires.size() >= 2 ) if( twoSegments && m_wires.size() >= 2 )
{
computeBreakPoint( { m_wires[m_wires.size() - 2], segment }, cursorPos, computeBreakPoint( { m_wires[m_wires.size() - 2], segment }, cursorPos,
currentMode, posture ); currentMode, posture );
}
finishSegments(); finishSegments();
segment = nullptr; segment = nullptr;
@ -1123,8 +1120,8 @@ void SCH_LINE_WIRE_BUS_TOOL::finishSegments()
// freed selected items. // freed selected items.
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true ); m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
SCH_SCREEN* screen = m_frame->GetScreen(); SCH_SCREEN* screen = m_frame->GetScreen();
PICKED_ITEMS_LIST itemList; SCHEMATIC_COMMIT commit( m_toolMgr );
// Remove segments backtracking over others // Remove segments backtracking over others
simplifyWireList(); simplifyWireList();
@ -1149,17 +1146,17 @@ void SCH_LINE_WIRE_BUS_TOOL::finishSegments()
new_ends.push_back( pt ); new_ends.push_back( pt );
} }
itemList.PushItem( ITEM_PICKER( screen, wire, UNDO_REDO::NEWITEM ) ); commit.Added( wire, screen );
} }
if( m_busUnfold.in_progress && m_busUnfold.label_placed ) if( m_busUnfold.in_progress && m_busUnfold.label_placed )
{ {
wxASSERT( m_busUnfold.entry && m_busUnfold.label ); wxASSERT( m_busUnfold.entry && m_busUnfold.label );
itemList.PushItem( ITEM_PICKER( screen, m_busUnfold.entry, UNDO_REDO::NEWITEM ) ); commit.Added( m_busUnfold.entry, screen );
m_frame->SaveCopyForRepeatItem( m_busUnfold.entry ); m_frame->SaveCopyForRepeatItem( m_busUnfold.entry );
itemList.PushItem( ITEM_PICKER( screen, m_busUnfold.label, UNDO_REDO::NEWITEM ) ); commit.Added( m_busUnfold.label, screen );
m_frame->AddCopyForRepeatItem( m_busUnfold.label ); m_frame->AddCopyForRepeatItem( m_busUnfold.label );
m_busUnfold.label->ClearEditFlags(); m_busUnfold.label->ClearEditFlags();
} }
@ -1189,10 +1186,8 @@ void SCH_LINE_WIRE_BUS_TOOL::finishSegments()
getViewControls()->CaptureCursor( false ); getViewControls()->CaptureCursor( false );
getViewControls()->SetAutoPan( false ); getViewControls()->SetAutoPan( false );
m_frame->SaveCopyInUndoList( itemList, UNDO_REDO::NEWITEM, false );
// Correct and remove segments that need to be merged. // Correct and remove segments that need to be merged.
m_frame->SchematicCleanUp(); m_frame->SchematicCleanUp( &commit );
std::vector<SCH_ITEM*> symbols; std::vector<SCH_ITEM*> symbols;
@ -1209,14 +1204,14 @@ void SCH_LINE_WIRE_BUS_TOOL::finishSegments()
for( auto pt = pts.begin(); pt != pts.end(); pt++ ) for( auto pt = pts.begin(); pt != pts.end(); pt++ )
{ {
for( auto secondPt = pt + 1; secondPt != pts.end(); secondPt++ ) for( auto secondPt = pt + 1; secondPt != pts.end(); secondPt++ )
m_frame->TrimWire( *pt, *secondPt ); m_frame->TrimWire( &commit, *pt, *secondPt );
} }
} }
for( const VECTOR2I& pt : new_ends ) for( const VECTOR2I& pt : new_ends )
{ {
if( m_frame->GetScreen()->IsExplicitJunctionNeeded( pt ) ) if( m_frame->GetScreen()->IsExplicitJunctionNeeded( pt ) )
m_frame->AddJunction( m_frame->GetScreen(), pt, true, false ); m_frame->AddJunction( &commit, m_frame->GetScreen(), pt );
} }
if( m_busUnfold.in_progress ) if( m_busUnfold.in_progress )
@ -1226,13 +1221,14 @@ void SCH_LINE_WIRE_BUS_TOOL::finishSegments()
item->ClearEditFlags(); item->ClearEditFlags();
m_frame->TestDanglingEnds(); m_frame->TestDanglingEnds();
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified ); commit.Push( _( "Draw Wires" ) );
m_frame->OnModify(); m_toolMgr->PostEvent( EVENTS::SelectedItemsModified );
} }
int SCH_LINE_WIRE_BUS_TOOL::TrimOverLappingWires( EE_SELECTION* aSelection ) int SCH_LINE_WIRE_BUS_TOOL::TrimOverLappingWires( SCHEMATIC_COMMIT* aCommit,
EE_SELECTION* aSelection )
{ {
SCHEMATIC* sch = getModel<SCHEMATIC>(); SCHEMATIC* sch = getModel<SCHEMATIC>();
SCH_SCREEN* screen = sch->CurrentSheet().LastScreen(); SCH_SCREEN* screen = sch->CurrentSheet().LastScreen();
@ -1258,7 +1254,7 @@ int SCH_LINE_WIRE_BUS_TOOL::TrimOverLappingWires( EE_SELECTION* aSelection )
{ {
std::vector<VECTOR2I> conn_pts; std::vector<VECTOR2I> conn_pts;
for( VECTOR2I pt : pts ) for( const VECTOR2I& pt : pts )
{ {
if( IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), pt ) ) if( IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), pt ) )
conn_pts.push_back( pt ); conn_pts.push_back( pt );
@ -1268,7 +1264,7 @@ int SCH_LINE_WIRE_BUS_TOOL::TrimOverLappingWires( EE_SELECTION* aSelection )
} }
if( conn_pts.size() == 2 ) if( conn_pts.size() == 2 )
m_frame->TrimWire( conn_pts[0], conn_pts[1] ); m_frame->TrimWire( aCommit, conn_pts[0], conn_pts[1] );
} }
} }
@ -1276,12 +1272,13 @@ int SCH_LINE_WIRE_BUS_TOOL::TrimOverLappingWires( EE_SELECTION* aSelection )
} }
int SCH_LINE_WIRE_BUS_TOOL::AddJunctionsIfNeeded( EE_SELECTION* aSelection ) int SCH_LINE_WIRE_BUS_TOOL::AddJunctionsIfNeeded( SCHEMATIC_COMMIT* aCommit,
EE_SELECTION* aSelection )
{ {
SCH_SCREEN* screen = m_frame->GetScreen(); SCH_SCREEN* screen = m_frame->GetScreen();
for( const VECTOR2I& point : screen->GetNeededJunctions( aSelection->Items() ) ) for( const VECTOR2I& point : screen->GetNeededJunctions( aSelection->Items() ) )
m_frame->AddJunction( m_frame->GetScreen(), point, true, false ); m_frame->AddJunction( aCommit, m_frame->GetScreen(), point );
return 0; return 0;
} }

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2019 CERN * Copyright (C) 2019 CERN
* Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -92,17 +92,20 @@ public:
/** /**
* Handle the addition of junctions to a selection of objects * Handle the addition of junctions to a selection of objects
*/ */
int AddJunctionsIfNeeded( EE_SELECTION* aSelection ); int AddJunctionsIfNeeded( SCHEMATIC_COMMIT* aCommit, EE_SELECTION* aSelection );
/** /**
* Logic to remove wires when overlapping correct items * Logic to remove wires when overlapping correct items
*/ */
int TrimOverLappingWires( EE_SELECTION* aSelection ); int TrimOverLappingWires( SCHEMATIC_COMMIT* aCommit, EE_SELECTION* aSelection );
private: private:
int doDrawSegments( const TOOL_EVENT& aTool, int aType, bool aQuitOnDraw ); int doDrawSegments( const TOOL_EVENT& aTool, int aType, bool aQuitOnDraw );
SCH_LINE* startSegments( int aType, const VECTOR2D& aPos, SCH_LINE* aSegment = nullptr ); SCH_LINE* startSegments( int aType, const VECTOR2D& aPos, SCH_LINE* aSegment = nullptr );
SCH_LINE* doUnfoldBus( const wxString& aNet, const VECTOR2I& aPos = VECTOR2I( 0, 0 ) ); SCH_LINE* doUnfoldBus( const wxString& aNet, const VECTOR2I& aPos = VECTOR2I( 0, 0 ) );
void finishSegments(); void finishSegments();
/** /**

View File

@ -30,6 +30,7 @@
#include <tools/ee_selection_tool.h> #include <tools/ee_selection_tool.h>
#include <tools/sch_line_wire_bus_tool.h> #include <tools/sch_line_wire_bus_tool.h>
#include <ee_actions.h> #include <ee_actions.h>
#include <schematic_commit.h>
#include <eda_item.h> #include <eda_item.h>
#include <sch_item.h> #include <sch_item.h>
#include <sch_symbol.h> #include <sch_symbol.h>
@ -359,6 +360,11 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
EE_GRID_HELPER grid( m_toolMgr ); EE_GRID_HELPER grid( m_toolMgr );
bool wasDragging = m_moveInProgress && m_isDrag; bool wasDragging = m_moveInProgress && m_isDrag;
bool isSlice = false; bool isSlice = false;
SCHEMATIC_COMMIT localInstance( m_toolMgr );
SCHEMATIC_COMMIT* commit = aEvent.Parameter<SCHEMATIC_COMMIT*>();
if( !commit )
commit = &localInstance;
m_anchorPos.reset(); m_anchorPos.reset();
@ -369,7 +375,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
else if( aEvent.IsAction( &EE_ACTIONS::drag ) ) else if( aEvent.IsAction( &EE_ACTIONS::drag ) )
{ {
m_isDrag = true; m_isDrag = true;
isSlice = aEvent.Parameter<bool>(); isSlice = commit != &localInstance;
} }
else if( aEvent.IsAction( &EE_ACTIONS::moveActivate ) ) else if( aEvent.IsAction( &EE_ACTIONS::moveActivate ) )
{ {
@ -392,7 +398,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
// state. // state.
try try
{ {
m_frame->RollbackSchematicFromUndo(); commit->Revert();
} }
catch( const IO_ERROR& exc ) catch( const IO_ERROR& exc )
{ {
@ -475,7 +481,6 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
if( !m_moveInProgress ) // Prepare to start moving/dragging if( !m_moveInProgress ) // Prepare to start moving/dragging
{ {
SCH_ITEM* sch_item = (SCH_ITEM*) selection.Front(); SCH_ITEM* sch_item = (SCH_ITEM*) selection.Front();
bool appendUndo = ( sch_item && sch_item->IsNew() ) || isSlice;
bool placingNewItems = sch_item && sch_item->IsNew(); bool placingNewItems = sch_item && sch_item->IsNew();
//------------------------------------------------------------------------ //------------------------------------------------------------------------
@ -528,7 +533,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
} }
for( const VECTOR2I& point : connections ) for( const VECTOR2I& point : connections )
getConnectedDragItems( item, point, connectedDragItems, appendUndo ); getConnectedDragItems( commit, item, point, connectedDragItems );
} }
// Go back and get all label connections now that we can test for drag-selected // Go back and get all label connections now that we can test for drag-selected
@ -536,7 +541,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
for( SCH_ITEM* item : stageTwo ) for( SCH_ITEM* item : stageTwo )
{ {
for( const VECTOR2I& point : item->GetConnectionPoints() ) for( const VECTOR2I& point : item->GetConnectionPoints() )
getConnectedDragItems( item, point, connectedDragItems, appendUndo ); getConnectedDragItems( commit, item, point, connectedDragItems );
} }
for( EDA_ITEM* item : connectedDragItems ) for( EDA_ITEM* item : connectedDragItems )
@ -595,17 +600,15 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
if( item->IsNew() ) if( item->IsNew() )
{ {
// Item was added in a previous command (and saved to undo by // Item was added to commit in a previous command
// that command)
} }
else if( item->GetParent() && item->GetParent()->IsSelected() ) else if( item->GetParent() && item->GetParent()->IsSelected() )
{ {
// Item will be (or has been) saved to undo by parent // Item will be (or has been) added to commit by parent
} }
else else
{ {
saveCopyInUndoList( (SCH_ITEM*) item, UNDO_REDO::CHANGED, appendUndo, false ); commit->Modify( (SCH_ITEM*) item, m_frame->GetScreen() );
appendUndo = true;
} }
SCH_ITEM* schItem = (SCH_ITEM*) item; SCH_ITEM* schItem = (SCH_ITEM*) item;
@ -840,11 +843,11 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
} }
else if( evt->IsAction( &EE_ACTIONS::rotateCW ) ) else if( evt->IsAction( &EE_ACTIONS::rotateCW ) )
{ {
m_toolMgr->RunAction( EE_ACTIONS::rotateCW, true ); m_toolMgr->RunAction( EE_ACTIONS::rotateCW, true, &commit );
} }
else if( evt->IsAction( &EE_ACTIONS::rotateCCW ) ) else if( evt->IsAction( &EE_ACTIONS::rotateCCW ) )
{ {
m_toolMgr->RunAction( EE_ACTIONS::rotateCCW, true ); m_toolMgr->RunAction( EE_ACTIONS::rotateCCW, true, &commit );
} }
else if( evt->Action() == TA_CHOICE_MENU_CHOICE ) else if( evt->Action() == TA_CHOICE_MENU_CHOICE )
{ {
@ -903,7 +906,19 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
selectionCopy.Add( line ); selectionCopy.Add( line );
// Save whatever new bend lines and changed lines survived the drag // Save whatever new bend lines and changed lines survived the drag
commitDragLines(); for( SCH_LINE* newLine : m_newDragLines )
{
newLine->ClearEditFlags();
commit->Added( newLine, m_frame->GetScreen() );
}
// These lines have been changed, but aren't selected. We need
// to manually clear these edit flags or they'll stick around.
for( SCH_LINE* oldLine : m_changedDragLines )
oldLine->ClearEditFlags();
m_newDragLines.clear();
m_changedDragLines.clear();
controls->ForceCursorPosition( false ); controls->ForceCursorPosition( false );
controls->ShowCursor( false ); controls->ShowCursor( false );
@ -917,7 +932,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
if( restore_state ) if( restore_state )
{ {
m_selectionTool->RemoveItemsFromSel( &m_dragAdditions, QUIET_MODE ); m_selectionTool->RemoveItemsFromSel( &m_dragAdditions, QUIET_MODE );
m_frame->RollbackSchematicFromUndo(); commit->Revert();
} }
else else
{ {
@ -937,24 +952,26 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
for( const DANGLING_END_ITEM& it : internalPoints ) for( const DANGLING_END_ITEM& it : internalPoints )
{ {
if( m_frame->GetScreen()->IsExplicitJunctionNeeded( it.GetPosition()) ) if( m_frame->GetScreen()->IsExplicitJunctionNeeded( it.GetPosition()) )
m_frame->AddJunction( m_frame->GetScreen(), it.GetPosition(), true, false ); m_frame->AddJunction( commit, m_frame->GetScreen(), it.GetPosition() );
} }
SCH_LINE_WIRE_BUS_TOOL* lwbTool = m_toolMgr->GetTool<SCH_LINE_WIRE_BUS_TOOL>(); SCH_LINE_WIRE_BUS_TOOL* lwbTool = m_toolMgr->GetTool<SCH_LINE_WIRE_BUS_TOOL>();
lwbTool->TrimOverLappingWires( &selectionCopy ); lwbTool->TrimOverLappingWires( commit, &selectionCopy );
lwbTool->AddJunctionsIfNeeded( &selectionCopy ); lwbTool->AddJunctionsIfNeeded( commit, &selectionCopy );
// This needs to run prior to `RecalculateConnections` because we need to identify // This needs to run prior to `RecalculateConnections` because we need to identify
// the lines that are newly dangling // the lines that are newly dangling
if( m_isDrag && !isSlice ) if( m_isDrag && !isSlice )
trimDanglingLines(); trimDanglingLines( commit );
// Auto-rotate any moved labels // Auto-rotate any moved labels
for( EDA_ITEM* item : selection ) for( EDA_ITEM* item : selection )
m_frame->AutoRotateItem( m_frame->GetScreen(), static_cast<SCH_ITEM*>( item ) ); m_frame->AutoRotateItem( m_frame->GetScreen(), static_cast<SCH_ITEM*>( item ) );
m_frame->SchematicCleanUp(); m_frame->SchematicCleanUp( commit );
m_frame->OnModify();
if( commit == &localInstance )
commit->Push( m_isDrag ? _( "Drag" ) : _( "Move" ) );
} }
for( EDA_ITEM* item : m_frame->GetScreen()->Items() ) for( EDA_ITEM* item : m_frame->GetScreen()->Items() )
@ -979,10 +996,10 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
} }
void SCH_MOVE_TOOL::trimDanglingLines() void SCH_MOVE_TOOL::trimDanglingLines( SCHEMATIC_COMMIT* aCommit )
{ {
// Need a local cleanup first to ensure we remove unneeded junctions // Need a local cleanup first to ensure we remove unneeded junctions
m_frame->SchematicCleanUp( m_frame->GetScreen() ); m_frame->SchematicCleanUp( aCommit, m_frame->GetScreen() );
std::set<SCH_ITEM*> danglers; std::set<SCH_ITEM*> danglers;
@ -1006,10 +1023,9 @@ void SCH_MOVE_TOOL::trimDanglingLines()
for( SCH_ITEM* line : danglers ) for( SCH_ITEM* line : danglers )
{ {
line->SetFlags( STRUCT_DELETED ); line->SetFlags( STRUCT_DELETED );
saveCopyInUndoList( line, UNDO_REDO::DELETED, true ); aCommit->Removed( line, m_frame->GetScreen() );
updateItem( line, false ); updateItem( line, false );
m_frame->RemoveFromScreen( line, m_frame->GetScreen() ); m_frame->RemoveFromScreen( line, m_frame->GetScreen() );
} }
} }
@ -1144,8 +1160,8 @@ void SCH_MOVE_TOOL::getConnectedItems( SCH_ITEM* aOriginalItem, const VECTOR2I&
} }
void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aSelectedItem, const VECTOR2I& aPoint, void SCH_MOVE_TOOL::getConnectedDragItems( SCHEMATIC_COMMIT* aCommit, SCH_ITEM* aSelectedItem,
EDA_ITEMS& aList, bool& aAppendUndo ) const VECTOR2I& aPoint, EDA_ITEMS& aList )
{ {
EE_RTREE& items = m_frame->GetScreen()->Items(); EE_RTREE& items = m_frame->GetScreen()->Items();
EE_RTREE::EE_TYPE itemsOverlappingRTree = items.Overlapping( aSelectedItem->GetBoundingBox() ); EE_RTREE::EE_TYPE itemsOverlappingRTree = items.Overlapping( aSelectedItem->GetBoundingBox() );
@ -1153,7 +1169,8 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aSelectedItem, const VECTOR
bool ptHasUnselectedJunction = false; bool ptHasUnselectedJunction = false;
auto makeNewWire = auto makeNewWire =
[&]( SCH_ITEM* fixed, SCH_ITEM* selected, const VECTOR2I& start, const VECTOR2I& end ) [this]( SCHEMATIC_COMMIT* commit, SCH_ITEM* fixed, SCH_ITEM* selected,
const VECTOR2I& start, const VECTOR2I& end )
{ {
SCH_LINE* newWire; SCH_LINE* newWire;
@ -1175,12 +1192,13 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aSelectedItem, const VECTOR
newWire->SetEndPoint( end ); newWire->SetEndPoint( end );
m_frame->AddToScreen( newWire, m_frame->GetScreen() ); m_frame->AddToScreen( newWire, m_frame->GetScreen() );
commit->Added( newWire, m_frame->GetScreen() );
return newWire; return newWire;
}; };
auto makeNewJunction = auto makeNewJunction =
[&]( SCH_LINE* line, const VECTOR2I& pt ) [this]( SCHEMATIC_COMMIT* commit, SCH_LINE* line, const VECTOR2I& pt )
{ {
SCH_JUNCTION* junction = new SCH_JUNCTION( pt ); SCH_JUNCTION* junction = new SCH_JUNCTION( pt );
junction->SetFlags( IS_NEW ); junction->SetFlags( IS_NEW );
@ -1191,6 +1209,7 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aSelectedItem, const VECTOR
junction->SetLayer( LAYER_BUS_JUNCTION ); junction->SetLayer( LAYER_BUS_JUNCTION );
m_frame->AddToScreen( junction, m_frame->GetScreen() ); m_frame->AddToScreen( junction, m_frame->GetScreen() );
commit->Added( junction, m_frame->GetScreen() );
return junction; return junction;
}; };
@ -1282,34 +1301,22 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aSelectedItem, const VECTOR
if( line->HitTest( aPoint, 1 ) && !line->HasFlag( SELECTED ) if( line->HitTest( aPoint, 1 ) && !line->HasFlag( SELECTED )
&& !line->HasFlag( SELECTED_BY_DRAG ) ) && !line->HasFlag( SELECTED_BY_DRAG ) )
{ {
newWire = makeNewWire( line, aSelectedItem, aPoint, aPoint ); newWire = makeNewWire( aCommit, line, aSelectedItem, aPoint, aPoint );
newWire->SetFlags( SELECTED_BY_DRAG | STARTPOINT ); newWire->SetFlags( SELECTED_BY_DRAG | STARTPOINT );
newWire->StoreAngle( ( line->Angle() + ANGLE_90 ).Normalize() ); newWire->StoreAngle( ( line->Angle() + ANGLE_90 ).Normalize() );
aList.push_back( newWire ); aList.push_back( newWire );
saveCopyInUndoList( newWire, UNDO_REDO::NEWITEM, aAppendUndo );
aAppendUndo = true;
if( aPoint != line->GetStartPoint() && aPoint != line->GetEndPoint() ) if( aPoint != line->GetStartPoint() && aPoint != line->GetEndPoint() )
{ {
// Split line in half // Split line in half
if( !line->IsNew() ) if( !line->IsNew() )
{ aCommit->Modify( line, m_frame->GetScreen() );
saveCopyInUndoList( line, UNDO_REDO::CHANGED, aAppendUndo );
aAppendUndo = true;
}
VECTOR2I oldEnd = line->GetEndPoint(); VECTOR2I oldEnd = line->GetEndPoint();
line->SetEndPoint( aPoint ); line->SetEndPoint( aPoint );
SCH_LINE* secondHalf = makeNewWire( line, line, aPoint, oldEnd ); makeNewWire( aCommit, line, line, aPoint, oldEnd );
SCH_JUNCTION* junction = makeNewJunction( line, aPoint ); makeNewJunction( aCommit, line, aPoint );
saveCopyInUndoList( secondHalf, UNDO_REDO::NEWITEM, aAppendUndo );
aAppendUndo = true;
saveCopyInUndoList( junction, UNDO_REDO::NEWITEM, aAppendUndo );
aAppendUndo = true;
} }
else else
{ {
@ -1367,12 +1374,9 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aSelectedItem, const VECTOR
{ {
// Add a new wire between the sheetpin and the selected item so the // Add a new wire between the sheetpin and the selected item so the
// selected item can be dragged. // selected item can be dragged.
newWire = makeNewWire( pin, aSelectedItem, aPoint, aPoint ); newWire = makeNewWire( aCommit, pin, aSelectedItem, aPoint, aPoint );
newWire->SetFlags( SELECTED_BY_DRAG | STARTPOINT ); newWire->SetFlags( SELECTED_BY_DRAG | STARTPOINT );
aList.push_back( newWire ); aList.push_back( newWire );
saveCopyInUndoList( newWire, UNDO_REDO::NEWITEM, aAppendUndo );
aAppendUndo = true;
} }
} }
} }
@ -1385,12 +1389,9 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aSelectedItem, const VECTOR
{ {
// Add a new wire between the symbol or junction and the selected item so // Add a new wire between the symbol or junction and the selected item so
// the selected item can be dragged. // the selected item can be dragged.
newWire = makeNewWire( test, aSelectedItem, aPoint, aPoint ); newWire = makeNewWire( aCommit, test, aSelectedItem, aPoint, aPoint );
newWire->SetFlags( SELECTED_BY_DRAG | STARTPOINT ); newWire->SetFlags( SELECTED_BY_DRAG | STARTPOINT );
aList.push_back( newWire ); aList.push_back( newWire );
saveCopyInUndoList( newWire, UNDO_REDO::NEWITEM, aAppendUndo );
aAppendUndo = true;
} }
break; break;
@ -1451,12 +1452,9 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aSelectedItem, const VECTOR
{ {
// Add a new wire between the label and the selected item so the selected item // Add a new wire between the label and the selected item so the selected item
// can be dragged. // can be dragged.
newWire = makeNewWire( test, aSelectedItem, aPoint, aPoint ); newWire = makeNewWire( aCommit, test, aSelectedItem, aPoint, aPoint );
newWire->SetFlags( SELECTED_BY_DRAG | STARTPOINT ); newWire->SetFlags( SELECTED_BY_DRAG | STARTPOINT );
aList.push_back( newWire ); aList.push_back( newWire );
saveCopyInUndoList( newWire, UNDO_REDO::NEWITEM, aAppendUndo );
aAppendUndo = true;
} }
break; break;
@ -1496,7 +1494,7 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aSelectedItem, const VECTOR
else else
otherEnd = ends[0]; otherEnd = ends[0];
getConnectedDragItems( test, otherEnd, aList, aAppendUndo ); getConnectedDragItems( aCommit, test, otherEnd, aList );
// No need to test the other end of the bus entry // No need to test the other end of the bus entry
break; break;
@ -1594,15 +1592,15 @@ void SCH_MOVE_TOOL::moveItem( EDA_ITEM* aItem, const VECTOR2I& aDelta )
int SCH_MOVE_TOOL::AlignElements( const TOOL_EVENT& aEvent ) int SCH_MOVE_TOOL::AlignElements( const TOOL_EVENT& aEvent )
{ {
EE_GRID_HELPER grid( m_toolMgr); EE_GRID_HELPER grid( m_toolMgr);
EE_SELECTION& selection = m_selectionTool->RequestSelection( EE_COLLECTOR::MovableItems ); EE_SELECTION& selection = m_selectionTool->RequestSelection( EE_COLLECTOR::MovableItems );
bool appendUndo = false; SCHEMATIC_COMMIT commit( m_toolMgr );
auto doMoveItem = auto doMoveItem =
[&]( EDA_ITEM* item, const VECTOR2I& delta ) [&]( EDA_ITEM* item, const VECTOR2I& delta )
{ {
saveCopyInUndoList( item, UNDO_REDO::CHANGED, appendUndo ); commit.Modify( item, m_frame->GetScreen() );
appendUndo = true;
// Ensure only one end is moved when calling moveItem // Ensure only one end is moved when calling moveItem
// i.e. we are in drag mode // i.e. we are in drag mode
bool tmp_isDrag = m_isDrag; bool tmp_isDrag = m_isDrag;
@ -1645,7 +1643,7 @@ int SCH_MOVE_TOOL::AlignElements( const TOOL_EVENT& aEvent )
line->ClearFlags(); line->ClearFlags();
line->SetFlags( SELECTED ); line->SetFlags( SELECTED );
line->SetFlags( flags[ii] ); line->SetFlags( flags[ii] );
getConnectedDragItems( line, pts[ii], drag_items, appendUndo ); getConnectedDragItems( &commit, line, pts[ii], drag_items );
std::set<EDA_ITEM*> unique_items( drag_items.begin(), drag_items.end() ); std::set<EDA_ITEM*> unique_items( drag_items.begin(), drag_items.end() );
VECTOR2I gridpt = grid.AlignGrid( pts[ii] ) - pts[ii]; VECTOR2I gridpt = grid.AlignGrid( pts[ii] ) - pts[ii];
@ -1697,8 +1695,8 @@ int SCH_MOVE_TOOL::AlignElements( const TOOL_EVENT& aEvent )
if( gridpt != VECTOR2I( 0, 0 ) ) if( gridpt != VECTOR2I( 0, 0 ) )
{ {
EDA_ITEMS drag_items; EDA_ITEMS drag_items;
getConnectedDragItems( pin, pin->GetConnectionPoints()[0], drag_items, getConnectedDragItems( &commit, pin, pin->GetConnectionPoints()[0],
appendUndo ); drag_items );
doMoveItem( pin, gridpt ); doMoveItem( pin, gridpt );
@ -1720,7 +1718,7 @@ int SCH_MOVE_TOOL::AlignElements( const TOOL_EVENT& aEvent )
EDA_ITEMS drag_items{ item }; EDA_ITEMS drag_items{ item };
for( const VECTOR2I& point : connections ) for( const VECTOR2I& point : connections )
getConnectedDragItems( schItem, point, drag_items, appendUndo ); getConnectedDragItems( &commit, schItem, point, drag_items );
std::map<VECTOR2I, int> shifts; std::map<VECTOR2I, int> shifts;
VECTOR2I most_common( 0, 0 ); VECTOR2I most_common( 0, 0 );
@ -1753,39 +1751,19 @@ int SCH_MOVE_TOOL::AlignElements( const TOOL_EVENT& aEvent )
} }
SCH_LINE_WIRE_BUS_TOOL* lwbTool = m_toolMgr->GetTool<SCH_LINE_WIRE_BUS_TOOL>(); SCH_LINE_WIRE_BUS_TOOL* lwbTool = m_toolMgr->GetTool<SCH_LINE_WIRE_BUS_TOOL>();
lwbTool->TrimOverLappingWires( &selection ); lwbTool->TrimOverLappingWires( &commit, &selection );
lwbTool->AddJunctionsIfNeeded( &selection ); lwbTool->AddJunctionsIfNeeded( &commit, &selection );
m_toolMgr->PostEvent( EVENTS::SelectedItemsMoved ); m_toolMgr->PostEvent( EVENTS::SelectedItemsMoved );
m_frame->SchematicCleanUp(); m_frame->SchematicCleanUp( &commit );
m_frame->TestDanglingEnds(); m_frame->TestDanglingEnds();
commit.Push( _( "Align" ) );
m_frame->OnModify();
return 0; return 0;
} }
void SCH_MOVE_TOOL::commitDragLines()
{
for( SCH_LINE* newLine : m_newDragLines )
{
newLine->ClearEditFlags();
saveCopyInUndoList( newLine, UNDO_REDO::NEWITEM, true );
}
// These lines have been changed, but aren't selected. We need
// to manually clear these edit flags or they'll stick around.
for( SCH_LINE* oldLine : m_changedDragLines )
{
oldLine->ClearEditFlags();
}
m_newDragLines.clear();
m_changedDragLines.clear();
}
void SCH_MOVE_TOOL::clearNewDragLines() void SCH_MOVE_TOOL::clearNewDragLines()
{ {
// Remove new bend lines added during the drag // Remove new bend lines added during the drag

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2019 CERN * Copyright (C) 2019 CERN
* Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -69,15 +69,12 @@ private:
///< Connected items with no wire are included (as there is no wire to adjust for the drag). ///< Connected items with no wire are included (as there is no wire to adjust for the drag).
///< Connected wires are included with any un-connected ends flagged (STARTPOINT or ENDPOINT). ///< Connected wires are included with any un-connected ends flagged (STARTPOINT or ENDPOINT).
void getConnectedItems( SCH_ITEM* aOriginalItem, const VECTOR2I& aPoint, EDA_ITEMS& aList ); void getConnectedItems( SCH_ITEM* aOriginalItem, const VECTOR2I& aPoint, EDA_ITEMS& aList );
void getConnectedDragItems( SCH_ITEM* fixed, const VECTOR2I& selected, EDA_ITEMS& aList, void getConnectedDragItems( SCHEMATIC_COMMIT* aCommit, SCH_ITEM* fixed,
bool& aAppendUndo ); const VECTOR2I& selected, EDA_ITEMS& aList );
void orthoLineDrag( SCH_LINE* line, const VECTOR2I& splitDelta, int& xBendCount, void orthoLineDrag( SCH_LINE* line, const VECTOR2I& splitDelta, int& xBendCount,
int& yBendCount, const EE_GRID_HELPER& grid ); int& yBendCount, const EE_GRID_HELPER& grid );
///< Saves the new drag lines to the undo list
void commitDragLines();
///< Clears the new drag lines and removes them from the screen ///< Clears the new drag lines and removes them from the screen
void clearNewDragLines(); void clearNewDragLines();
@ -85,7 +82,7 @@ private:
void setTransitions() override; void setTransitions() override;
///< Cleanup dangling lines left after a drag ///< Cleanup dangling lines left after a drag
void trimDanglingLines(); void trimDanglingLines( SCHEMATIC_COMMIT* aCommit );
private: private:
///< Re-entrancy guard ///< Re-entrancy guard

View File

@ -28,20 +28,20 @@
#include <tools/symbol_editor_drawing_tools.h> #include <tools/symbol_editor_drawing_tools.h>
#include <tools/symbol_editor_move_tool.h> #include <tools/symbol_editor_move_tool.h>
#include <ee_actions.h> #include <ee_actions.h>
#include <bitmaps.h>
#include <string_utils.h> #include <string_utils.h>
#include <symbol_edit_frame.h> #include <symbol_edit_frame.h>
#include <schematic_commit.h>
#include <dialogs/dialog_lib_shape_properties.h> #include <dialogs/dialog_lib_shape_properties.h>
#include <dialogs/dialog_lib_text_properties.h> #include <dialogs/dialog_lib_text_properties.h>
#include <dialogs/dialog_lib_textbox_properties.h>
#include <dialogs/dialog_field_properties.h> #include <dialogs/dialog_field_properties.h>
#include <dialogs/dialog_lib_symbol_properties.h> #include <dialogs/dialog_lib_symbol_properties.h>
#include <dialogs/dialog_lib_edit_pin_table.h> #include <dialogs/dialog_lib_edit_pin_table.h>
#include <dialogs/dialog_update_symbol_fields.h> #include <dialogs/dialog_update_symbol_fields.h>
#include <sch_plugins/kicad/sch_sexpr_plugin.h> #include <sch_plugins/kicad/sch_sexpr_plugin.h>
#include <lib_text.h> #include <lib_text.h>
#include <lib_textbox.h>
#include "symbol_editor_edit_tool.h" #include "symbol_editor_edit_tool.h"
#include "dialog_lib_textbox_properties.h"
#include "lib_textbox.h"
#include <wx/textdlg.h> // for wxTextEntryDialog #include <wx/textdlg.h> // for wxTextEntryDialog
#include <math/util.h> // for KiROUND #include <math/util.h> // for KiROUND
@ -755,7 +755,7 @@ int SYMBOL_EDITOR_EDIT_TOOL::Copy( const TOOL_EVENT& aEvent )
int SYMBOL_EDITOR_EDIT_TOOL::Paste( const TOOL_EVENT& aEvent ) int SYMBOL_EDITOR_EDIT_TOOL::Paste( const TOOL_EVENT& aEvent )
{ {
LIB_SYMBOL* symbol = m_frame->GetCurSymbol(); LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
if( !symbol || symbol->IsAlias() ) if( !symbol || symbol->IsAlias() )
return 0; return 0;
@ -780,7 +780,9 @@ int SYMBOL_EDITOR_EDIT_TOOL::Paste( const TOOL_EVENT& aEvent )
if( !newPart ) if( !newPart )
return -1; return -1;
m_frame->SaveCopyInUndoList( symbol ); SCHEMATIC_COMMIT commit( m_toolMgr );
commit.Modify( symbol );
m_selectionTool->ClearSelection(); m_selectionTool->ClearSelection();
for( LIB_ITEM& item : symbol->GetDrawItems() ) for( LIB_ITEM& item : symbol->GetDrawItems() )
@ -811,7 +813,8 @@ int SYMBOL_EDITOR_EDIT_TOOL::Paste( const TOOL_EVENT& aEvent )
if( !selection.Empty() ) if( !selection.Empty() )
{ {
selection.SetReferencePoint( getViewControls()->GetCursorPosition( true ) ); selection.SetReferencePoint( getViewControls()->GetCursorPosition( true ) );
m_toolMgr->RunAction( EE_ACTIONS::move, false ); m_toolMgr->RunAction( EE_ACTIONS::move, true, &commit );
commit.Push( _( "Paste" ) );
} }
return 0; return 0;
@ -820,8 +823,9 @@ int SYMBOL_EDITOR_EDIT_TOOL::Paste( const TOOL_EVENT& aEvent )
int SYMBOL_EDITOR_EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent ) int SYMBOL_EDITOR_EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
{ {
LIB_SYMBOL* symbol = m_frame->GetCurSymbol(); LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
EE_SELECTION& selection = m_selectionTool->RequestSelection( nonFields ); EE_SELECTION& selection = m_selectionTool->RequestSelection( nonFields );
SCHEMATIC_COMMIT commit( m_toolMgr );
if( selection.GetSize() == 0 ) if( selection.GetSize() == 0 )
return 0; return 0;
@ -832,7 +836,7 @@ int SYMBOL_EDITOR_EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
return 0; return 0;
if( !selection.Front()->IsMoving() ) if( !selection.Front()->IsMoving() )
saveCopyInUndoList( m_frame->GetCurSymbol(), UNDO_REDO::LIBEDIT ); commit.Modify( symbol, m_frame->GetScreen() );
EDA_ITEMS newItems; EDA_ITEMS newItems;
int symbolLastPinNumber = -1; int symbolLastPinNumber = -1;
@ -866,7 +870,8 @@ int SYMBOL_EDITOR_EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
m_toolMgr->RunAction( EE_ACTIONS::addItemsToSel, true, &newItems ); m_toolMgr->RunAction( EE_ACTIONS::addItemsToSel, true, &newItems );
selection.SetReferencePoint( mapCoords( getViewControls()->GetCursorPosition( true ) ) ); selection.SetReferencePoint( mapCoords( getViewControls()->GetCursorPosition( true ) ) );
m_toolMgr->RunAction( EE_ACTIONS::move, false ); m_toolMgr->RunAction( EE_ACTIONS::move, true, &commit );
commit.Push( _( "Duplicate" ) );
return 0; return 0;
} }

View File

@ -344,7 +344,7 @@ void PCB_SHAPE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_I
wxString PCB_SHAPE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const wxString PCB_SHAPE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
{ {
return wxString::Format( _( "%s on %s" ), ShowShape(), GetLayerName() ); return wxString::Format( _( "%s on %s" ), GetFriendlyName(), GetLayerName() );
} }