From 9588a7974c1718ee5c384e823de9f48fe4568738 Mon Sep 17 00:00:00 2001 From: Tomasz Wlostowski Date: Tue, 10 May 2016 17:57:21 +0200 Subject: [PATCH] Added classes COMMIT & BOARD_COMMIT. --- common/CMakeLists.txt | 1 + common/commit.cpp | 97 ++++++++++++++++++ common/commit.h | 113 +++++++++++++++++++++ pcbnew/CMakeLists.txt | 1 + pcbnew/board_commit.cpp | 215 ++++++++++++++++++++++++++++++++++++++++ pcbnew/board_commit.h | 48 +++++++++ 6 files changed, 475 insertions(+) create mode 100644 common/commit.cpp create mode 100644 common/commit.h create mode 100644 pcbnew/board_commit.cpp create mode 100644 pcbnew/board_commit.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 612c817bed..2791ae821d 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -203,6 +203,7 @@ set( COMMON_SRCS class_plotter.cpp class_undoredo_container.cpp colors.cpp + commit.cpp common.cpp common_plot_functions.cpp common_plotHPGL_functions.cpp diff --git a/common/commit.cpp b/common/commit.cpp new file mode 100644 index 0000000000..7f94f90375 --- /dev/null +++ b/common/commit.cpp @@ -0,0 +1,97 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2016 CERN + * @author Tomasz Wlostowski + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include + +#include + +COMMIT::COMMIT() +{ + m_committed = false; +} + + +COMMIT::~COMMIT() +{ + if( !m_committed ) + { + BOOST_FOREACH( COMMIT_LINE& ent, m_changes ) + { + if( ent.m_copy ) + delete ent.m_copy; + } + } +} + + +void COMMIT::makeEntry( EDA_ITEM* aItem, CHANGE_TYPE type, bool saveCopy ) +{ + COMMIT_LINE ent; + + ent.m_item = aItem; + ent.m_type = type; + ent.m_copy = saveCopy ? (EDA_ITEM*) aItem->Clone() : NULL; + + m_changedItems.insert( aItem ); + m_changes.push_back( ent ); +} + + +COMMIT& COMMIT::Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType ) +{ + switch( aChangeType ) + { + case CHT_ADD: + assert( m_changedItems.find( aItem ) == m_changedItems.end() ); + makeEntry( aItem, CHT_ADD, false ); + return *this; + + case CHT_REMOVE: + makeEntry( aItem, CHT_REMOVE, false ); + return *this; + + case CHT_MODIFY: + { + EDA_ITEM* parent = parentObject( aItem ); + + if( m_changedItems.find( parent ) != m_changedItems.end() ) + return *this; // item already modifed once + + makeEntry( aItem, CHT_MODIFY, true ); + return *this; + } + + default: + assert( false ); + } +} + + +void COMMIT::Stage( const PICKED_ITEMS_LIST& aItems, CHANGE_TYPE aChangeType ) +{ + for( int i = 0; i < aItems.GetCount(); i++ ) + Stage( aItems.GetPickedItem( i ), aChangeType ); +} + diff --git a/common/commit.h b/common/commit.h new file mode 100644 index 0000000000..4256c7f8a2 --- /dev/null +++ b/common/commit.h @@ -0,0 +1,113 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2016 CERN + * @author Tomasz Wlostowski + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __COMMIT_H +#define __COMMIT_H + +#include +#include +#include + +#include + +class PICKED_ITEMS_LIST; + +/** + * Class COMMIT + * + * Represents a set of changes (additions, deletions or modifications) + * of a data model (e.g. the BOARD) class. + * + * The class can be used to propagate changes to subscribed objects (e.g. views, ratsnest), + * and automatically create undo/redo points. + */ +class COMMIT +{ +public: + ///> types of changes. + enum CHANGE_TYPE { + CHT_ADD = 0, + CHT_REMOVE = 1, + CHT_MODIFY = 2 + }; + + COMMIT(); + virtual ~COMMIT(); + + ///> Adds a new item to the model + COMMIT& Add( EDA_ITEM* aItem ) + { + return Stage( aItem, CHT_ADD ); + } + + ///> Removes a new item from the model + COMMIT& Remove( EDA_ITEM* aItem ) + { + return Stage( aItem, CHT_REMOVE ); + } + + ///> Modifies a given item in the model. + ///> Must be called before modification is performed. + COMMIT& Modify( EDA_ITEM* aItem ) + { + return Stage( aItem, CHT_MODIFY ); + } + + ///> Adds a change of the item aItem of type aChangeType to the change list. + virtual COMMIT& Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType ); + + void Stage( std::vector& container, CHANGE_TYPE aChangeType ) + { + BOOST_FOREACH( EDA_ITEM* item, container ) + { + Stage( item, aChangeType ); + } + } + + void Stage( const PICKED_ITEMS_LIST& aItems, CHANGE_TYPE aChangeType ); + + ///> Executes the changes. + virtual void Push( const wxString& aMessage ) = 0; + + ///> Revertes the commit by restoring the modifed items state. + virtual void Revert() = 0; + +protected: + struct COMMIT_LINE + { + EDA_ITEM *m_item; + EDA_ITEM *m_copy; + CHANGE_TYPE m_type; + }; + + virtual void makeEntry( EDA_ITEM* aItem, CHANGE_TYPE type, bool saveCopy ); + virtual EDA_ITEM* parentObject( EDA_ITEM* aItem ) const = 0; + + bool m_committed; + + std::set m_changedItems; + std::vector m_changes; +}; + +#endif diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 21380aaecb..a2e094b487 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -182,6 +182,7 @@ set( PCBNEW_AUTOROUTER_SRCS ) set( PCBNEW_CLASS_SRCS + board_commit.cpp tool_modview.cpp modview_frame.cpp pcbframe.cpp diff --git a/pcbnew/board_commit.cpp b/pcbnew/board_commit.cpp new file mode 100644 index 0000000000..0fa58381a5 --- /dev/null +++ b/pcbnew/board_commit.cpp @@ -0,0 +1,215 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2016 CERN + * @author Tomasz Wlostowski + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +BOARD_COMMIT::BOARD_COMMIT( PCB_TOOL* aTool ) +{ + m_tool = aTool; +} + + +BOARD_COMMIT::~BOARD_COMMIT() +{ +} + + +void BOARD_COMMIT::Push( const wxString& aMessage ) +{ + // Objects potentially interested in changes: + PICKED_ITEMS_LIST undoList; + TOOL_MANAGER* toolMgr = m_tool->GetManager(); + KIGFX::VIEW* view = toolMgr->GetView(); + BOARD* board = (BOARD*) toolMgr->GetModel(); + PCB_EDIT_FRAME* frame = (PCB_EDIT_FRAME*) toolMgr->GetEditFrame(); + RN_DATA* ratsnest = board->GetRatsnest(); + + bool editModules = m_tool->EditingModules(); + + // Module items need to be saved in the undo buffer before modification + if( editModules ) + { + frame->SaveCopyInUndoList( board->m_Modules, UR_CHANGED ); + } + + BOOST_FOREACH( COMMIT_LINE& ent, m_changes ) + { + BOARD_ITEM* boardItem = static_cast( ent.m_item ); + + switch( ent.m_type ) + { + case CHT_ADD: + { + if( !editModules ) + { + ITEM_PICKER itemWrapper( boardItem, UR_NEW ); + undoList.PushItem( itemWrapper ); + board->Add( boardItem ); + } + else + { + board->m_Modules->Add( boardItem ); + } + + if( boardItem->Type() == PCB_MODULE_T ) + { + MODULE* mod = static_cast( boardItem ); + mod->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) ); + } + + view->Add( boardItem ); + break; + } + + case CHT_REMOVE: + { + if( !editModules ) + { + ITEM_PICKER itemWrapper( boardItem, UR_DELETED ); + undoList.PushItem( itemWrapper ); + board->Remove( boardItem ); + } else { + board->m_Modules->Remove( boardItem ); + } + + if(boardItem->Type() == PCB_MODULE_T ) + { + MODULE* mod = static_cast( boardItem ); + mod->RunOnChildren( boost::bind( &KIGFX::VIEW::Remove, view, _1 ) ); + } + + view->Remove( boardItem ); + break; + } + + case CHT_MODIFY: + { + if( !editModules ) + { + ITEM_PICKER itemWrapper( boardItem, UR_CHANGED ); + itemWrapper.SetLink( ent.m_copy ); + undoList.PushItem( itemWrapper ); + } + + if( boardItem->Type() == PCB_MODULE_T ) + { + MODULE* mod = static_cast( boardItem ); + //mod->RunOnChildren( boost::bind( &KIGFX::VIEW::Remove, view, _1 ) ); + mod->RunOnChildren( boost::bind( &RN_DATA::Update, ratsnest, _1 ) ); + } + + boardItem->ViewUpdate( KIGFX::VIEW_ITEM::ALL ); + ratsnest->Update( boardItem ); + break; + } + + default: + break; + } + } + + if( !editModules ) + frame->SaveCopyInUndoList( undoList, UR_UNSPECIFIED ); + + frame->OnModify(); + ratsnest->Recalculate(); + + m_committed = true; +} + + +EDA_ITEM* BOARD_COMMIT::parentObject( EDA_ITEM* aItem ) const +{ + switch( aItem->Type() ) + { + case PCB_PAD_T: + case PCB_MODULE_EDGE_T: + case PCB_MODULE_TEXT_T: + return aItem->GetParent(); + default: + return aItem; + } + + return aItem; +} + + +void BOARD_COMMIT::Revert() +{ + #if 0 + PICKED_ITEMS_LIST undoList; + KIGFX::VIEW* view = m_toolMgr->GetView(); + BOARD *board = (BOARD*) m_toolMgr->GetModel(); + PCB_EDIT_FRAME *frame = (PCB_EDIT_FRAME*) m_toolMgr->GetEditFrame(); + + + BOOST_FOREACH( COMMIT_LINE& ent, m_changes ) + { + BOARD_ITEM *item = static_cast (ent.m_item); + BOARD_ITEM *copy = static_cast (ent.m_copy); + + if(ent.m_type == CHT_MODIFY) + { + printf("revert %p\n", item ); + RN_DATA *ratsnest = board->GetRatsnest(); + + if( item->Type() == PCB_MODULE_T ) + { + MODULE* oldModule = static_cast( item ); + oldModule->RunOnChildren( boost::bind( &KIGFX::VIEW::Remove, view, _1 ) ); + } + view->Remove( item ); + ratsnest->Remove( static_cast ( item ) ); + + item->SwapData( copy ); + + // Update all pads/drawings/texts, as they become invalid + // for the VIEW after SwapData() called for modules + if( item->Type() == PCB_MODULE_T ) + { + MODULE* newModule = static_cast( item ); + newModule->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) ); + } + view->Add( item ); + ratsnest->Add( item ); + + item->ClearFlags( SELECTED ); + + break; + } + } + #endif +} + diff --git a/pcbnew/board_commit.h b/pcbnew/board_commit.h new file mode 100644 index 0000000000..84d87f79ef --- /dev/null +++ b/pcbnew/board_commit.h @@ -0,0 +1,48 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2016 CERN + * @author Tomasz Wlostowski + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __BOARD_COMMIT_H +#define __BOARD_COMMIT_H + +#include + +class BOARD_ITEM; +class PICKED_ITEMS_LIST; +class PCB_TOOL; + +class BOARD_COMMIT : public COMMIT +{ +public: + BOARD_COMMIT( PCB_TOOL* aTool ); + virtual ~BOARD_COMMIT(); + + virtual void Push( const wxString& aMessage ); + virtual void Revert(); + +private: + PCB_TOOL* m_tool; + virtual EDA_ITEM* parentObject( EDA_ITEM* aItem ) const; +}; + +#endif