Fixed UNDO behaviour

- Undo actions are pushed to the appropriate sheet(s)
- Each sheet's actions are grouped together
This commit is contained in:
Oliver Walters 2017-04-19 00:10:17 +10:00 committed by Wayne Stambaugh
parent 47ee2773d2
commit 48893ab2b1
3 changed files with 71 additions and 20 deletions

View File

@ -1446,9 +1446,9 @@ bool BOM_TABLE_MODEL::HaveFieldsChanged() const
/** /**
* Returns a list of only those components that have been changed * Returns a list of only those components that have been changed
*/ */
std::vector<SCH_COMPONENT*> BOM_TABLE_MODEL::GetChangedComponents() std::vector<SCH_REFERENCE> BOM_TABLE_MODEL::GetChangedComponents()
{ {
std::vector<SCH_COMPONENT*> components; std::vector<SCH_REFERENCE> components;
for( auto& group : Groups ) for( auto& group : Groups )
{ {
@ -1464,12 +1464,7 @@ std::vector<SCH_COMPONENT*> BOM_TABLE_MODEL::GetChangedComponents()
{ {
for( auto& unit : component->Units ) for( auto& unit : component->Units )
{ {
auto cmp = unit.GetComp(); components.push_back( unit );
if( cmp )
{
components.push_back( cmp );
}
} }
} }
} }

View File

@ -315,7 +315,7 @@ public:
bool HaveFieldsChanged() const; bool HaveFieldsChanged() const;
std::vector<SCH_COMPONENT*> GetChangedComponents(); std::vector<SCH_REFERENCE> GetChangedComponents();
unsigned int CountChangedComponents(); unsigned int CountChangedComponents();
}; };

View File

@ -93,6 +93,18 @@ DIALOG_BOM_EDITOR::~DIALOG_BOM_EDITOR()
//TODO //TODO
} }
/* Struct for keeping track of schematic sheet changes
* Stores:
* SHEET_PATH - Schematic to apply changes to
* PICKED_ITEMS_LIST - List of changes to apply
*/
typedef struct
{
SCH_SHEET_PATH path;
PICKED_ITEMS_LIST items;
} SheetUndoList;
/** /**
* When the component table dialog is closed, * When the component table dialog is closed,
* work out if we need to save any changed. * work out if we need to save any changed.
@ -124,36 +136,80 @@ bool DIALOG_BOM_EDITOR::TransferDataFromWindow()
if( saveChanges ) if( saveChanges )
{ {
/** Create a list of picked items for undo /**
* PICKED_ITEMS_LIST contains multiple ITEM_PICKER instances * As we may be saving changes across multiple sheets,
* Each ITEM_PICKER contains a component and a command * we need to first determine which changes need to be made to which sheet.
* To this end, we perform the following:
* 1. Save the "path" of the currently displayed sheet
* 2. Create a MAP of <SheetPath:ChangeList> changes that need to be made
* 3. Push UNDO actions to appropriate sheets
* 4. Perform all the update actions
* 5. Reset the sheet view to the current sheet
*/ */
auto pickerList = PICKED_ITEMS_LIST(); auto currentSheet = m_parent->GetCurrentSheet();
//! Create a map of changes required for each sheet
std::map<wxString, SheetUndoList> undoSheetMap;
// List of components that have changed // List of components that have changed
auto changed = m_bom->GetChangedComponents(); auto changed = m_bom->GetChangedComponents();
ITEM_PICKER picker; ITEM_PICKER picker;
for( auto cmp : changed ) // Iterate through each of the components that were changed
for( auto ref : changed )
{ {
// Extract the SCH_COMPONENT* object
auto cmp = ref.GetComp();
wxString path = ref.GetSheetPath().Path();
// Push the component into the picker list // Push the component into the picker list
picker = ITEM_PICKER( cmp, UR_CHANGED ); picker = ITEM_PICKER( cmp, UR_CHANGED );
picker.SetFlags( cmp->GetFlags() ); picker.SetFlags( cmp->GetFlags() );
//picker.SetLink( DuplicateStruct( cmp, true ) );
pickerList.PushItem( picker );
/*
* If there is not currently an undo list for the given sheet,
* create an empty one
*/
if( undoSheetMap.count( path ) == 0 )
{
SheetUndoList newList;
newList.path = ref.GetSheetPath();
undoSheetMap[path] = newList;
}
auto& pickerList = undoSheetMap[path];
pickerList.items.PushItem( picker );
} }
if( pickerList.GetCount() > 0 ) // Iterate through each sheet that needs updating
for( auto it = undoSheetMap.begin(); it != undoSheetMap.end(); ++it )
{ {
m_parent->SaveCopyInUndoList( pickerList, UR_CHANGED ); auto undo = it->second;
m_bom->ApplyFieldChanges();
m_parent->Refresh(); m_parent->SetCurrentSheet( undo.path );
m_parent->SaveCopyInUndoList( undo.items, UR_CHANGED );
m_parent->OnModify();
} }
// Apply all the field changes
m_bom->ApplyFieldChanges();
// Redraw the current sheet and mark as dirty
m_parent->Refresh();
m_parent->OnModify(); m_parent->OnModify();
// Reset the view to where we left the user
m_parent->SetCurrentSheet(currentSheet);
} }
return true; return true;