1 /* 2 * This program source code file is part of KiCad, a free EDA CAD application. 3 * 4 * Copyright 2016-2017 CERN 5 * Copyright (C) 2020-2021 KiCad Developers, see change_log.txt for contributors. 6 * 7 * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> 8 * @author Maciej Suminski <maciej.suminski@cern.ch> 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License 12 * as published by the Free Software Foundation; either version 2 13 * of the License, or (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, you may find one here: 22 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 23 * or you may search the http://www.gnu.org website for the version 2 license, 24 * or you may write to the Free Software Foundation, Inc., 25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 26 */ 27 28 #ifndef __COMMIT_H 29 #define __COMMIT_H 30 31 #include <set> 32 #include <vector> 33 #include <wx/string.h> 34 #include <undo_redo_container.h> 35 36 class EDA_ITEM; 37 38 ///< Types of changes 39 enum CHANGE_TYPE { 40 CHT_ADD = 1, 41 CHT_REMOVE = 2, 42 CHT_MODIFY = 4, 43 CHT_TYPE = CHT_ADD | CHT_REMOVE | CHT_MODIFY, 44 45 ///< Flag to indicate the change is already applied, 46 ///< just notify observers (not compatible with CHT_MODIFY) 47 CHT_DONE = 8, 48 CHT_FLAGS = CHT_DONE 49 }; 50 51 template<typename T> 52 CHANGE_TYPE operator|( CHANGE_TYPE aTypeA, T aTypeB ) 53 { 54 return CHANGE_TYPE( (int) aTypeA | (int) aTypeB ); 55 } 56 57 template<typename T> 58 CHANGE_TYPE operator&( CHANGE_TYPE aTypeA, T aTypeB ) 59 { 60 return CHANGE_TYPE( (int) aTypeA & (int) aTypeB ); 61 } 62 63 64 /** 65 * Represent a set of changes (additions, deletions or modifications) of a data model 66 * (e.g. the BOARD) class. 67 * 68 * The class can be used to propagate changes to subscribed objects (e.g. views, ratsnest), 69 * and automatically create undo/redo points. 70 */ 71 class COMMIT 72 { 73 public: 74 COMMIT(); 75 virtual ~COMMIT(); 76 77 ///< Add a new item to the model Add(EDA_ITEM * aItem)78 COMMIT& Add( EDA_ITEM* aItem ) 79 { 80 return Stage( aItem, CHT_ADD ); 81 } 82 83 ///< Notify observers that aItem has been added Added(EDA_ITEM * aItem)84 COMMIT& Added( EDA_ITEM* aItem ) 85 { 86 return Stage( aItem, CHT_ADD | CHT_DONE ); 87 } 88 89 ///< Remove a new item from the model Remove(EDA_ITEM * aItem)90 COMMIT& Remove( EDA_ITEM* aItem ) 91 { 92 return Stage( aItem, CHT_REMOVE ); 93 } 94 95 ///< Notify observers that aItem has been removed Removed(EDA_ITEM * aItem)96 COMMIT& Removed( EDA_ITEM* aItem ) 97 { 98 return Stage( aItem, CHT_REMOVE | CHT_DONE ); 99 } 100 101 ///< Modify a given item in the model. 102 ///< Must be called before modification is performed. Modify(EDA_ITEM * aItem)103 COMMIT& Modify( EDA_ITEM* aItem ) 104 { 105 return Stage( aItem, CHT_MODIFY ); 106 } 107 108 ///< Create an undo entry for an item that has been already modified. Requires a copy done 109 ///< before the modification. Modified(EDA_ITEM * aItem,EDA_ITEM * aCopy)110 COMMIT& Modified( EDA_ITEM* aItem, EDA_ITEM* aCopy ) 111 { 112 return createModified( aItem, aCopy ); 113 } 114 115 template<class Range> 116 StageItems(const Range & aRange,CHANGE_TYPE aChangeType)117 COMMIT& StageItems( const Range& aRange, CHANGE_TYPE aChangeType ) 118 { 119 for( const auto& item : aRange ) 120 Stage( item, aChangeType ); 121 122 return *this; 123 } 124 125 ///< Add a change of the item aItem of type aChangeType to the change list. 126 virtual COMMIT& Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType ); 127 128 virtual COMMIT& Stage( std::vector<EDA_ITEM*>& container, CHANGE_TYPE aChangeType ); 129 130 virtual COMMIT& Stage( const PICKED_ITEMS_LIST& aItems, 131 UNDO_REDO aModFlag = UNDO_REDO::UNSPECIFIED ); 132 133 ///< Execute the changes. 134 virtual void Push( const wxString& aMessage = wxT( "A commit" ), 135 bool aCreateUndoEntry = true, bool aSetDirtyBit = true ) = 0; 136 137 ///< Revert the commit by restoring the modified items state. 138 virtual void Revert() = 0; 139 Empty()140 bool Empty() const 141 { 142 return m_changes.empty(); 143 } 144 145 ///< Returns status of an item. 146 int GetStatus( EDA_ITEM* aItem ); 147 148 protected: 149 struct COMMIT_LINE 150 { 151 EDA_ITEM* m_item; ///< Main item that is added/deleted/modified 152 EDA_ITEM* m_copy; ///< Optional copy of the item 153 CHANGE_TYPE m_type; ///< Modification type 154 }; 155 156 // Should be called in Push() & Revert() methods clear()157 void clear() 158 { 159 m_changedItems.clear(); 160 m_changes.clear(); 161 } 162 163 COMMIT& createModified( EDA_ITEM* aItem, EDA_ITEM* aCopy, int aExtraFlags = 0 ); 164 165 virtual void makeEntry( EDA_ITEM* aItem, CHANGE_TYPE aType, EDA_ITEM* aCopy = nullptr ); 166 167 /** 168 * Search for an entry describing change for a particular item. 169 * 170 * @return null if there is no related entry. 171 */ 172 COMMIT_LINE* findEntry( EDA_ITEM* aItem ); 173 174 virtual EDA_ITEM* parentObject( EDA_ITEM* aItem ) const = 0; 175 176 CHANGE_TYPE convert( UNDO_REDO aType ) const; 177 178 std::set<EDA_ITEM*> m_changedItems; 179 std::vector<COMMIT_LINE> m_changes; 180 }; 181 182 #endif 183