1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2009 jean-pierre.charras@gipsa-lab.inpg.fr
5  * Copyright (C) 2011 Wayne Stambaugh <stambaughw@gmail.com>
6  * Copyright (C) 2009-2021 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
24  */
25 
26 #ifndef _CLASS_UNDOREDO_CONTAINER_H
27 #define _CLASS_UNDOREDO_CONTAINER_H
28 
29 #include <core/typeinfo.h>
30 #include <eda_item_flags.h>
31 #include <vector>
32 
33 class EDA_ITEM;
34 class PICKED_ITEMS_LIST;
35 class BASE_SCREEN;
36 
37 
38 /**
39  * Undo Redo considerations:
40  * Basically we have 3 cases
41  *      New item
42  *      Deleted item
43  *      Modified item
44  * there is also a specific case in Eeschema, when wires are modified
45  * If an item is modified, a copy of the "old" item parameters value is held.
46  * When an item is deleted or added (new item) the pointer points the item, and there is
47  * no other copy.
48  */
49 
50 
51 /**
52  * Type of undo/redo operations
53  *
54  * Each type must be redo/undone by a specific operation.
55  */
56 enum class UNDO_REDO {
57     UNSPECIFIED = 0,    // illegal
58     NOP,                // Undo/redo will ignore this entry.  Only forces the start of a new stack
59     CHANGED,            // params of items have a value changed: undo is made by exchange
60                         // values with a copy of these values
61     NEWITEM,            // new item, undo by changing in deleted
62     DELETED,            // deleted item, undo by changing in deleted
63     LIBEDIT,            // Specific to the component editor (symbol_editor creates a full copy
64                         // of the current component when changed)
65     LIB_RENAME,         // As LIBEDIT, but old copy should be removed from library
66     EXCHANGE_T,         // Use for changing the schematic text type where swapping
67                         // data structure is insufficient to restore the change.
68     DRILLORIGIN,        // origin changed (like CHANGED, contains the origin and a copy)
69     GRIDORIGIN,         // origin changed (like CHANGED, contains the origin and a copy)
70     PAGESETTINGS,       // page settings or title block changes
71     REGROUP,            // new group of items created (do not use GROUP to avoid collision
72                         // with an header on msys2)
73     UNGROUP             // existing group destroyed (items not destroyed)
74 };
75 
76 
77 class ITEM_PICKER
78 {
79 public:
80 //    ITEM_PICKER( EDA_ITEM* aItem = NULL, UNDO_REDO aStatus = UNSPECIFIED );
81     ITEM_PICKER();
82     ITEM_PICKER( BASE_SCREEN* aScreen, EDA_ITEM* aItem,
83                  UNDO_REDO aStatus = UNDO_REDO::UNSPECIFIED );
84 
GetItem()85     EDA_ITEM* GetItem() const { return m_pickedItem; }
86 
87     void SetItem( EDA_ITEM* aItem );
88 
GetItemType()89     KICAD_T GetItemType() const { return m_pickedItemType; }
90 
SetStatus(UNDO_REDO aStatus)91     void SetStatus( UNDO_REDO aStatus ) { m_undoRedoStatus = aStatus; }
92 
GetStatus()93     UNDO_REDO GetStatus() const { return m_undoRedoStatus; }
94 
SetFlags(EDA_ITEM_FLAGS aFlags)95     void SetFlags( EDA_ITEM_FLAGS aFlags ) { m_pickerFlags = aFlags; }
96 
GetFlags()97     EDA_ITEM_FLAGS GetFlags() const { return m_pickerFlags; }
98 
SetLink(EDA_ITEM * aItem)99     void SetLink( EDA_ITEM* aItem ) { m_link = aItem; }
100 
GetLink()101     EDA_ITEM* GetLink() const { return m_link; }
102 
GetScreen()103     BASE_SCREEN* GetScreen() const { return m_screen; }
104 
105 private:
106     EDA_ITEM_FLAGS m_pickerFlags;      /* a copy of m_flags member. useful in mode/drag
107                                         * undo/redo commands */
108     UNDO_REDO      m_undoRedoStatus;   /* type of operation to undo/redo for this item */
109     EDA_ITEM*      m_pickedItem;       /* Pointer on the schematic or board item that is concerned
110                                         * (picked), or in undo redo commands, the copy of an
111                                         * edited item. */
112     KICAD_T        m_pickedItemType;   /* type of schematic or board item that is concerned */
113 
114     EDA_ITEM*      m_link;             /* Pointer on another item. Used in undo redo command
115                                         * used when a duplicate exists i.e. when an item is
116                                         * modified, and the copy of initial item exists (the
117                                         * duplicate) m_Item points the duplicate (i.e the old
118                                         * copy of an active item) and m_Link points the active
119                                         * item in schematic */
120 
121     BASE_SCREEN*   m_screen;           /* For new and deleted items the screen the item should
122                                         * be added to/removed from. */
123 
124 };
125 
126 
127 /**
128  * A holder to handle information on schematic or board items.
129  *
130  * The information held is a pointer on each item, and the command made.
131  */
132 class PICKED_ITEMS_LIST
133 {
134 private:
135     std::vector <ITEM_PICKER> m_ItemsList;
136 
137 public:
138     PICKED_ITEMS_LIST();
139     ~PICKED_ITEMS_LIST();
140 
141     /**
142      * Push \a aItem to the top of the list.
143      *
144      * @param aItem Picker to push on to the list.
145      */
146     void PushItem( const ITEM_PICKER& aItem );
147 
148     /**
149      * @return The picker removed from the top of the list.
150      */
151     ITEM_PICKER PopItem();
152 
153     /**
154      * @return True if \a aItem is found in the pick list.
155      */
156     bool ContainsItem( const EDA_ITEM* aItem ) const;
157 
158     /**
159      * @return Index of the searched item. If the item is not stored in the list, negative value
160      *         is returned.
161      */
162     int FindItem( const EDA_ITEM* aItem ) const;
163 
164     /**
165      * Delete only the list of pickers NOT the picked data itself.
166      */
167     void ClearItemsList();
168 
169     /**
170      * Delete the list of pickers AND the data pointed by #m_PickedItem or #m_PickedItemLink
171      * according to the type of undo/redo command recorded.
172      */
173     void ClearListAndDeleteItems();
174 
175     /**
176      * @return The count of pickers stored in this list.
177      */
GetCount()178     unsigned GetCount() const
179     {
180         return m_ItemsList.size();
181     }
182 
183     /**
184      * Reverse the order of pickers stored in this list.
185      *
186      * This is useful when pop a list from Undo to Redo (and vice-versa) because
187      * sometimes undo (or redo) a command needs to keep the order of successive
188      * changes.  Obviously, undo and redo are in reverse order
189      */
190     void ReversePickersListOrder();
191 
192     /**
193      * @return The picker of a picked item.
194      * @param aIdx Index of the picker in the picked list if this picker does not exist,
195      *             a picker is returned, with its members set to 0 or NULL.
196      */
197     ITEM_PICKER GetItemWrapper( unsigned int aIdx ) const;
198 
199     /**
200      * @return A pointer to the picked item.
201      * @param aIdx Index of the picked item in the picked list.
202      */
203     EDA_ITEM* GetPickedItem( unsigned int aIdx ) const;
204 
205     /**
206      * @return A pointer to the picked item's screen.
207      * @param aIdx Index of the picked item in the picked list.
208      */
209     BASE_SCREEN* GetScreenForItem( unsigned int aIdx ) const;
210 
211     /**
212      * @return link of the picked item, or null if does not exist.
213      * @param aIdx Index of the picked item in the picked list.
214      */
215     EDA_ITEM* GetPickedItemLink( unsigned int aIdx ) const;
216 
217     /**
218      * @return The type of undo/redo operation associated to the picked item,
219      *          or UNSPECIFIED if does not exist.
220      * @param aIdx Index of the picked item in the picked list.
221      */
222     UNDO_REDO GetPickedItemStatus( unsigned int aIdx ) const;
223 
224     /**
225      * Return the value of the picker flag.
226      *
227      * @param aIdx Index of the picker in the picked list.
228      * @return The value stored in the picker, if the picker exists, or 0 if does not exist.
229      */
230     EDA_ITEM_FLAGS GetPickerFlags( unsigned aIdx ) const;
231 
232     /**
233      * @param aItem A pointer to the item to pick.
234      * @param aIdx Index of the picker in the picked list.
235      * @return True if the picker exists or false if does not exist.
236      */
237     bool SetPickedItem( EDA_ITEM* aItem, unsigned aIdx );
238 
239     /**
240      * @param aItem A pointer to the item to pick.
241      * @param aStatus The type of undo/redo operation associated to the item to pick.
242      * @param aIdx Index of the picker in the picked list.
243      * @return True if the picker exists or false if does not exist.
244      */
245     bool SetPickedItem( EDA_ITEM* aItem, UNDO_REDO aStatus, unsigned aIdx );
246 
247     /**
248      * Set the link associated to a given picked item.
249      *
250      * @param aLink is the link to the item associated to the picked item.
251      * @param aIdx is index of the picker in the picked list.
252      * @return true if the picker exists, or false if does not exist.
253      */
254     bool SetPickedItemLink( EDA_ITEM* aLink, unsigned aIdx );
255 
256     /**
257      * Set the type of undo/redo operation for a given picked item.
258      *
259      * @param aStatus The type of undo/redo operation associated to the picked item
260      * @param aIdx Index of the picker in the picked list
261      * @return True if the picker exists or false if does not exist
262      */
263     bool SetPickedItemStatus( UNDO_REDO aStatus, unsigned aIdx );
264 
265     /**
266      * Set the flags of the picker (usually to the picked item m_flags value).
267      *
268      * @param aFlags The flag value to save in picker.
269      * @param aIdx Index of the picker in the picked list.
270      * @return True if the picker exists or false if does not exist.
271      */
272     bool SetPickerFlags( EDA_ITEM_FLAGS aFlags, unsigned aIdx );
273 
274     /**
275      * Remove one entry (one picker) from the list of picked items.
276      *
277      * @param aIdx Index of the picker in the picked list.
278      * @return True if ok or false if did not exist.
279      */
280     bool RemovePicker( unsigned aIdx );
281 
282     /**
283      * Copy all data from aSource to the list.
284      *
285      * Items picked are not copied. just pointer in them are copied.
286      *
287      * @param aSource The list of items to copy to the list.
288      */
289     void CopyList( const PICKED_ITEMS_LIST& aSource );
290 };
291 
292 
293 /**
294  * A holder to handle a list of undo (or redo) commands.
295  */
296 class UNDO_REDO_CONTAINER
297 {
298 public:
299     UNDO_REDO_CONTAINER();
300     ~UNDO_REDO_CONTAINER();
301 
302     void PushCommand( PICKED_ITEMS_LIST* aCommand );
303 
304     PICKED_ITEMS_LIST* PopCommand();
305 
306     void ClearCommandList();
307 
308     std::vector <PICKED_ITEMS_LIST*> m_CommandsList;   // the list of possible undo/redo commands
309 };
310 
311 
312 #endif      // _CLASS_UNDOREDO_CONTAINER_H
313