diff --git a/common/commit.cpp b/common/commit.cpp index 22c053e43b..f398ad6399 100644 --- a/common/commit.cpp +++ b/common/commit.cpp @@ -42,15 +42,19 @@ COMMIT::~COMMIT() COMMIT& COMMIT::Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType ) { - switch( aChangeType ) + assert( aChangeType != ( CHT_MODIFY | CHT_DONE ) ); // CHT_MODIFY and CHT_DONE are not compatible + + int flag = aChangeType & CHT_FLAGS; + + switch( aChangeType & CHT_TYPE ) { case CHT_ADD: assert( m_changedItems.find( aItem ) == m_changedItems.end() ); - makeEntry( aItem, CHT_ADD ); + makeEntry( aItem, CHT_ADD | flag ); return *this; case CHT_REMOVE: - makeEntry( aItem, CHT_REMOVE ); + makeEntry( aItem, CHT_REMOVE | flag ); return *this; case CHT_MODIFY: @@ -58,9 +62,9 @@ COMMIT& COMMIT::Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType ) EDA_ITEM* parent = parentObject( aItem ); if( m_changedItems.find( parent ) != m_changedItems.end() ) - return *this; // item already modifed once + return *this; // item has been already modified once - makeEntry( parent, CHT_MODIFY, parent->Clone() ); + makeEntry( parent, CHT_MODIFY | flag, parent->Clone() ); return *this; } @@ -78,7 +82,7 @@ COMMIT& COMMIT::Stage( EDA_ITEM* aItem, EDA_ITEM* aCopy ) EDA_ITEM* parent = parentObject( aItem ); if( m_changedItems.find( parent ) != m_changedItems.end() ) - return *this; // item already modifed once + return *this; // item has been already modified once makeEntry( parent, CHT_MODIFY, aCopy ); @@ -131,7 +135,7 @@ COMMIT& COMMIT::Stage( const PICKED_ITEMS_LIST& aItems, UNDO_REDO_T aModFlag ) void COMMIT::makeEntry( EDA_ITEM* aItem, CHANGE_TYPE aType, EDA_ITEM* aCopy ) { // Expect an item copy if it is going to be modified - assert( !!aCopy == ( aType == CHT_MODIFY ) ); + assert( !!aCopy == ( ( aType & CHT_TYPE ) == CHT_MODIFY ) ); COMMIT_LINE ent; @@ -144,7 +148,7 @@ void COMMIT::makeEntry( EDA_ITEM* aItem, CHANGE_TYPE aType, EDA_ITEM* aCopy ) } -COMMIT::CHANGE_TYPE COMMIT::convert( UNDO_REDO_T aType ) const +CHANGE_TYPE COMMIT::convert( UNDO_REDO_T aType ) const { switch( aType ) { diff --git a/include/commit.h b/include/commit.h index a036dda30b..3741536f68 100644 --- a/include/commit.h +++ b/include/commit.h @@ -32,6 +32,32 @@ class EDA_ITEM; +///> Types of changes +enum CHANGE_TYPE { + CHT_ADD = 1, + CHT_REMOVE = 2, + CHT_MODIFY = 4, + CHT_TYPE = CHT_ADD | CHT_REMOVE | CHT_MODIFY, + + ///> Flag to indicate the change is already applied, + ///> just notify observers (not compatible with CHT_MODIFY) + CHT_DONE = 8, + CHT_FLAGS = CHT_DONE +}; + +template +CHANGE_TYPE operator|( CHANGE_TYPE aTypeA, T aTypeB ) +{ + return CHANGE_TYPE( (int) aTypeA | (int) aTypeB ); +} + +template +CHANGE_TYPE operator&( CHANGE_TYPE aTypeA, T aTypeB ) +{ + return CHANGE_TYPE( (int) aTypeA & (int) aTypeB ); +} + + /** * Class COMMIT * @@ -44,13 +70,6 @@ class EDA_ITEM; class COMMIT { public: - ///> types of changes. - enum CHANGE_TYPE { - CHT_ADD = 0, - CHT_REMOVE = 1, - CHT_MODIFY = 2 - }; - COMMIT(); virtual ~COMMIT(); @@ -60,12 +79,24 @@ public: return Stage( aItem, CHT_ADD ); } + ///> Notifies observers that aItem has been added + COMMIT& Added( EDA_ITEM* aItem ) + { + return Stage( aItem, CHT_ADD | CHT_DONE ); + } + ///> Removes a new item from the model COMMIT& Remove( EDA_ITEM* aItem ) { return Stage( aItem, CHT_REMOVE ); } + ///> Notifies observers that aItem has been removed + COMMIT& Removed( EDA_ITEM* aItem ) + { + return Stage( aItem, CHT_REMOVE | CHT_DONE ); + } + ///> Modifies a given item in the model. ///> Must be called before modification is performed. COMMIT& Modify( EDA_ITEM* aItem ) diff --git a/pcbnew/board_commit.cpp b/pcbnew/board_commit.cpp index d2fcfc050b..62139f711e 100644 --- a/pcbnew/board_commit.cpp +++ b/pcbnew/board_commit.cpp @@ -68,6 +68,8 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) for( COMMIT_LINE& ent : m_changes ) { + int changeType = ent.m_type & CHT_TYPE; + int changeFlags = ent.m_type & CHT_FLAGS; BOARD_ITEM* boardItem = static_cast( ent.m_item ); // Module items need to be saved in the undo buffer before modification @@ -82,7 +84,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) { if( !ent.m_copy ) { - assert( ent.m_type != CHT_MODIFY ); // too late to make a copy.. + assert( changeType != CHT_MODIFY ); // too late to make a copy.. ent.m_copy = ent.m_item->Clone(); } @@ -99,14 +101,17 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) } } - switch( ent.m_type ) + switch( changeType ) { case CHT_ADD: { if( !m_editModules ) { undoList.PushItem( ITEM_PICKER( boardItem, UR_NEW ) ); - board->Add( boardItem ); + + if( !( changeFlags & CHT_DONE ) ) + board->Add( boardItem ); + //ratsnest->Add( boardItem ); // TODO currently done by BOARD::Add() if( boardItem->Type() == PCB_MODULE_T ) @@ -117,8 +122,11 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) } else { + // modules inside modules are not supported yet assert( boardItem->Type() != PCB_MODULE_T ); - board->m_Modules->Add( boardItem ); + + if( !( changeFlags & CHT_DONE ) ) + board->m_Modules->Add( boardItem ); } view->Add( boardItem ); @@ -174,9 +182,12 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) { view->Remove( boardItem ); - MODULE* module = static_cast( boardItem->GetParent() ); - assert( module && module->Type() == PCB_MODULE_T ); - module->Delete( boardItem ); + if( !( changeFlags & CHT_DONE ) ) + { + MODULE* module = static_cast( boardItem->GetParent() ); + assert( module && module->Type() == PCB_MODULE_T ); + module->Delete( boardItem ); + } board->m_Status_Pcb = 0; // it is done in the legacy view (ratsnest perhaps?) } @@ -195,7 +206,10 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) case PCB_ZONE_T: // SEG_ZONE items are now deprecated case PCB_ZONE_AREA_T: view->Remove( boardItem ); - board->Remove( boardItem ); + + if( !( changeFlags & CHT_DONE ) ) + board->Remove( boardItem ); + //ratsnest->Remove( boardItem ); // currently done by BOARD::Remove() break; @@ -209,7 +223,9 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) module->RunOnChildren( boost::bind( &KIGFX::VIEW::Remove, view, _1 ) ); view->Remove( module ); - board->Remove( module ); + + if( !( changeFlags & CHT_DONE ) ) + board->Remove( module ); // Clear flags to indicate, that the ratsnest, list of nets & pads are not valid anymore board->m_Status_Pcb = 0;