KiCad PCB EDA Suite
zones_functions_for_undo_redo.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2009 Jean-Pierre Charras <[email protected]>
5 * Copyright (C) 2007-2022 KiCad Developers, see change_log.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25
26/* These functions are relative to undo redo function, when zones are involved.
27 *
28 * When a zone outline is modified (or created) this zone, or others zones on the same layer
29 * and with the same netcode can change or can be deleted due to the fact overlapping zones are
30 * merged. Also, when a zone outline is modified by adding a cutout area, this zone can be
31 * converted to more than one area, if the outline is break to 2 or more outlines and therefore
32 * new zones are created
33 *
34 * Due to the complexity of potential changes, and the fact there are only few zones in a board,
35 * and a zone has only few segments outlines, the more easy way to undo redo changes is to make
36 * a copy of all zones that can be changed and see after zone editing or creation what zones that
37 * are really modified, and ones they are modified (changes, deletion or addition)
38 */
39
40#include <pcb_edit_frame.h>
41
42#include <board.h>
43#include <zone.h>
44#include <zones.h>
46
54bool ZONE::IsSame( const ZONE& aZoneToCompare )
55{
56 // compare basic parameters:
57 if( GetLayerSet() != aZoneToCompare.GetLayerSet() )
58 return false;
59
60 if( GetNetCode() != aZoneToCompare.GetNetCode() )
61 return false;
62
63 if( GetAssignedPriority() != aZoneToCompare.GetAssignedPriority() )
64 return false;
65
66 // Compare zone specific parameters
67 if( GetIsRuleArea() != aZoneToCompare.GetIsRuleArea() )
68 return false;
69
70 if( GetIsRuleArea() )
71 {
72 if( GetDoNotAllowCopperPour() != aZoneToCompare.GetDoNotAllowCopperPour() )
73 return false;
74
75 if( GetDoNotAllowVias() != aZoneToCompare.GetDoNotAllowVias() )
76 return false;
77
78 if( GetDoNotAllowTracks() != aZoneToCompare.GetDoNotAllowTracks() )
79 return false;
80
81 if( GetDoNotAllowPads() != aZoneToCompare.GetDoNotAllowPads() )
82 return false;
83
84 if( GetDoNotAllowFootprints() != aZoneToCompare.GetDoNotAllowFootprints() )
85 return false;
86 }
87
88 if( m_ZoneClearance != aZoneToCompare.m_ZoneClearance )
89 return false;
90
91 if( m_ZoneMinThickness != aZoneToCompare.GetMinThickness() )
92 return false;
93
94 if( m_fillMode != aZoneToCompare.GetFillMode() )
95 return false;
96
97 if( m_PadConnection != aZoneToCompare.m_PadConnection )
98 return false;
99
100 if( m_thermalReliefGap != aZoneToCompare.m_thermalReliefGap )
101 return false;
102
104 return false;
105
106 if( m_zoneName != aZoneToCompare.m_zoneName )
107 return false;
108
109 if( m_islandRemovalMode != aZoneToCompare.m_islandRemovalMode )
110 return false;
111
112 if( m_minIslandArea != aZoneToCompare.m_minIslandArea )
113 return false;
114
115
116 // Compare outlines
117 wxASSERT( m_Poly ); // m_Poly == NULL Should never happen
118 wxASSERT( aZoneToCompare.Outline() );
119
120 if( Outline() != aZoneToCompare.Outline() ) // Compare vector
121 return false;
122
123 return true;
124}
125
126
136void SaveCopyOfZones( PICKED_ITEMS_LIST& aPickList, BOARD* aPcb )
137{
138 for( ZONE* zone : aPcb->Zones() )
139 {
140 ZONE* zoneDup = new ZONE( *zone );
141 zoneDup->SetParent( aPcb );
142 zoneDup->SetParentGroup( nullptr );
143
144 ITEM_PICKER picker( nullptr, zone, UNDO_REDO::CHANGED );
145 picker.SetLink( zoneDup );
146 aPickList.PushItem( picker );
147 }
148}
149
150
187 BOARD* aPcb )
188{
189 for( unsigned kk = 0; kk < aPickList.GetCount(); kk++ )
190 {
191 UNDO_REDO status = aPickList.GetPickedItemStatus( kk );
192
193 ZONE* ref = (ZONE*) aPickList.GetPickedItem( kk );
194
195 for( unsigned ii = 0; ; ii++ ) // analyse the main picked list
196 {
197 ZONE* zone = aPcb->GetArea( ii );
198
199 if( zone == nullptr )
200 {
201 /* End of list: the stored item is not found:
202 * it must be in aDeletedList:
203 * search it and restore initial values
204 * or
205 * if flagged NEWITEM: remove it definitively
206 */
207 if( status == UNDO_REDO::NEWITEM )
208 {
209 delete ref;
210 ref = nullptr;
211 aPickList.RemovePicker( kk );
212 kk--;
213 }
214 else
215 {
216 ZONE* zcopy = (ZONE*) aPickList.GetPickedItemLink( kk );
218
219 wxASSERT_MSG( zcopy != nullptr,
220 wxT( "UpdateCopyOfZonesList() error: link = NULL" ) );
221
222 ref->SwapItemData( zcopy );
223
224 // the copy was deleted; the link does not exists now.
225 aPickList.SetPickedItemLink( nullptr, kk );
226 delete zcopy;
227 }
228
229 // Remove this item from aAuxiliaryList, mainly for tests purpose
230 bool notfound = true;
231
232 for( unsigned nn = 0; nn < aAuxiliaryList.GetCount(); nn++ )
233 {
234 if( ref != nullptr && aAuxiliaryList.GetPickedItem( nn ) == ref )
235 {
236 aAuxiliaryList.RemovePicker( nn );
237 notfound = false;
238 break;
239 }
240 }
241
242 if( notfound ) // happens when the new zone overlaps an existing zone
243 // and these zones are combined
244 {
245#if defined(DEBUG)
246 printf( "UpdateCopyOfZonesList(): item not found in aAuxiliaryList,"
247 "combined with another zone\n" );
248 fflush(nullptr);
249#endif
250 }
251
252 break;
253 }
254
255 if( zone == ref ) // picked zone found
256 {
257 if( aPickList.GetPickedItemStatus( kk ) != UNDO_REDO::NEWITEM )
258 {
259 ZONE* zcopy = (ZONE*) aPickList.GetPickedItemLink( kk );
260
261 if( zone->IsSame( *zcopy ) ) // Remove picked, because no changes
262 {
263 delete zcopy; // Delete copy
264 aPickList.RemovePicker( kk );
265 kk--;
266 }
267 }
268
269 break;
270 }
271 }
272 }
273
274 // Add new zones in main pick list, and remove pickers from Auxiliary List
275 for( unsigned ii = 0; ii < aAuxiliaryList.GetCount(); )
276 {
277 if( aAuxiliaryList.GetPickedItemStatus( ii ) == UNDO_REDO::NEWITEM )
278 {
279 ITEM_PICKER picker = aAuxiliaryList.GetItemWrapper( ii );
280 aPickList.PushItem( picker );
281 aAuxiliaryList.RemovePicker( ii );
282 }
283 else if( aAuxiliaryList.GetPickedItemStatus( ii ) == UNDO_REDO::DELETED )
284 {
285 delete aAuxiliaryList.GetPickedItemLink( ii );
286 aAuxiliaryList.RemovePicker( ii );
287 }
288 else
289 {
290 ii++;
291 }
292 }
293
294 // Should not occur:
295 wxASSERT_MSG( aAuxiliaryList.GetCount() == 0,
296 wxT( "UpdateCopyOfZonesList() error: aAuxiliaryList not empty." ) );
297}
void SetParentGroup(PCB_GROUP *aGroup)
Definition: board_item.h:71
void SwapItemData(BOARD_ITEM *aImage)
Swap data between aItem and aImage.
Definition: board_item.cpp:166
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:265
ZONE * GetArea(int index) const
Return the Zone at a given index.
Definition: board.h:912
ZONES & Zones()
Definition: board.h:313
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:100
void SetLink(EDA_ITEM *aItem)
A holder to handle information on schematic or board items.
bool SetPickedItemStatus(UNDO_REDO aStatus, unsigned aIdx)
Set the type of undo/redo operation for a given picked item.
void PushItem(const ITEM_PICKER &aItem)
Push aItem to the top of the list.
UNDO_REDO GetPickedItemStatus(unsigned int aIdx) const
ITEM_PICKER GetItemWrapper(unsigned int aIdx) const
EDA_ITEM * GetPickedItemLink(unsigned int aIdx) const
bool RemovePicker(unsigned aIdx)
Remove one entry (one picker) from the list of picked items.
unsigned GetCount() const
bool SetPickedItemLink(EDA_ITEM *aLink, unsigned aIdx)
Set the link associated to a given picked item.
EDA_ITEM * GetPickedItem(unsigned int aIdx) const
Handle a list of polygons defining a copper zone.
Definition: zone.h:57
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition: zone.h:697
bool GetDoNotAllowVias() const
Definition: zone.h:699
ZONE_FILL_MODE m_fillMode
How to fill areas:
Definition: zone.h:857
int m_ZoneMinThickness
Definition: zone.h:826
int m_thermalReliefSpokeWidth
Definition: zone.h:848
wxString m_zoneName
An optional unique name for this zone, used for identifying it in DRC checking.
Definition: zone.h:794
bool GetDoNotAllowPads() const
Definition: zone.h:701
bool GetDoNotAllowTracks() const
Definition: zone.h:700
bool IsSame(const ZONE &aZoneToCompare)
Test if 2 zones are equivalent.
SHAPE_POLY_SET * Outline()
Definition: zone.h:312
SHAPE_POLY_SET * m_Poly
Outline of the zone.
Definition: zone.h:789
int m_ZoneClearance
Definition: zone.h:825
int GetMinThickness() const
Definition: zone.h:251
bool GetDoNotAllowFootprints() const
Definition: zone.h:702
ZONE_FILL_MODE GetFillMode() const
Definition: zone.h:174
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:122
bool GetDoNotAllowCopperPour() const
Definition: zone.h:698
ISLAND_REMOVAL_MODE m_islandRemovalMode
Definition: zone.h:829
int m_thermalReliefGap
Definition: zone.h:847
ZONE_CONNECTION m_PadConnection
Definition: zone.h:824
unsigned GetAssignedPriority() const
Definition: zone.h:112
long long int m_minIslandArea
When island removal mode is set to AREA, islands below this area will be removed.
Definition: zone.h:835
UNDO_REDO
Undo Redo considerations: Basically we have 3 cases New item Deleted item Modified item there is also...
void UpdateCopyOfZonesList(PICKED_ITEMS_LIST &aPickList, PICKED_ITEMS_LIST &aAuxiliaryList, BOARD *aPcb)
Function UpdateCopyOfZonesList Check a pick list to remove zones identical to their copies and set th...
void SaveCopyOfZones(PICKED_ITEMS_LIST &aPickList, BOARD *aPcb)
Function SaveCopyOfZones creates a copy of zones having a given netcode on a given layer,...