KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_group.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23#include <bitmaps.h>
24#include <eda_draw_frame.h>
25#include <eda_group.h>
27#include <sch_item.h>
28#include <sch_group.h>
29#include <sch_screen.h>
30#include <sch_symbol.h>
31#include <symbol.h>
32#include <confirm.h>
33#include <widgets/msgpanel.h>
34#include <view/view.h>
35
36#include <wx/debug.h>
37
39{
40}
41
43{
44}
45
47{
48}
49
50std::unordered_set<SCH_ITEM*> SCH_GROUP::GetSchItems() const
51{
52 std::unordered_set<SCH_ITEM*> items;
53
54 for( EDA_ITEM* item : m_items )
55 {
56 if( item->IsSCH_ITEM() )
57 items.insert( static_cast<SCH_ITEM*>( item ) );
58 }
59
60 return items;
61}
62
63
64/*
65 * @return if not in the symbol editor and aItem is in a symbol, returns the
66 * symbol's parent group. Otherwise, returns the aItem's parent group.
67 */
68EDA_GROUP* getClosestGroup( SCH_ITEM* aItem, bool isSymbolEditor )
69{
70 if( !isSymbolEditor && aItem->GetParent() && aItem->GetParent()->Type() == SCH_SYMBOL_T )
71 return static_cast<SCH_SYMBOL*>( aItem->GetParent() )->GetParentGroup();
72 else
73 return aItem->GetParentGroup();
74}
75
76
78EDA_GROUP* getNestedGroup( SCH_ITEM* aItem, EDA_GROUP* aScope, bool isSymbolEditor )
79{
80 EDA_GROUP* group = getClosestGroup( aItem, isSymbolEditor );
81
82 if( group == aScope )
83 return nullptr;
84
85 while( group && group->AsEdaItem()->GetParentGroup() && group->AsEdaItem()->GetParentGroup() != aScope )
86 {
87 if( group->AsEdaItem()->GetParent()->Type() == LIB_SYMBOL_T && isSymbolEditor )
88 break;
89
90 group = group->AsEdaItem()->GetParentGroup();
91 }
92
93 return group;
94}
95
96
97EDA_GROUP* SCH_GROUP::TopLevelGroup( SCH_ITEM* aItem, EDA_GROUP* aScope, bool isSymbolEditor )
98{
99 return getNestedGroup( aItem, aScope, isSymbolEditor );
100}
101
102
103bool SCH_GROUP::WithinScope( SCH_ITEM* aItem, SCH_GROUP* aScope, bool isSymbolEditor )
104{
105 EDA_GROUP* group = getClosestGroup( aItem, isSymbolEditor );
106
107 if( group && group == aScope )
108 return true;
109
110 EDA_GROUP* nested = getNestedGroup( aItem, aScope, isSymbolEditor );
111
112 return nested && nested->AsEdaItem()->GetParentGroup() && nested->AsEdaItem()->GetParentGroup() == aScope;
113}
114
115
117{
118 return GetBoundingBox().Centre();
119}
120
121
122void SCH_GROUP::SetPosition( const VECTOR2I& aNewpos )
123{
124 VECTOR2I delta = aNewpos - GetPosition();
125
126 Move( delta );
127}
128
129
131{
132 // Use copy constructor to get the same uuid and other fields
133 SCH_GROUP* newGroup = new SCH_GROUP( *this );
134 return newGroup;
135}
136
137
139{
140 // Use copy constructor to get the same uuid and other fields
141 SCH_GROUP* newGroup = new SCH_GROUP( *this );
142 newGroup->m_items.clear();
143
144 for( EDA_ITEM* member : m_items )
145 {
146 if( member->Type() == SCH_GROUP_T )
147 newGroup->AddItem( static_cast<SCH_GROUP*>( member )->DeepClone() );
148 else
149 newGroup->AddItem( static_cast<SCH_ITEM*>( member->Clone() ) );
150 }
151
152 return newGroup;
153}
154
155
156SCH_GROUP* SCH_GROUP::DeepDuplicate( bool addToParentGroup, SCH_COMMIT* aCommit ) const
157{
158 SCH_GROUP* newGroup = static_cast<SCH_GROUP*>( Duplicate( addToParentGroup, aCommit ) );
159 newGroup->m_items.clear();
160
161 for( EDA_ITEM* member : m_items )
162 {
163 if( member->Type() == SCH_GROUP_T )
164 newGroup->AddItem( static_cast<SCH_GROUP*>( member )->DeepDuplicate( IGNORE_PARENT_GROUP ) );
165 else
166 newGroup->AddItem( static_cast<SCH_ITEM*>( member )->Duplicate( IGNORE_PARENT_GROUP ) );
167 }
168
169 return newGroup;
170}
171
172
174{
175 assert( aImage->Type() == SCH_GROUP_T );
176 SCH_GROUP* image = static_cast<SCH_GROUP*>( aImage );
177
178 std::swap( m_items, image->m_items );
179 std::swap( m_name, image->m_name );
180 std::swap( m_designBlockLibId, image->m_designBlockLibId );
181}
182
183
184bool SCH_GROUP::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
185{
186 // Groups are selected by promoting a selection of one of their children
187 return false;
188}
189
190
191bool SCH_GROUP::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
192{
193 // Groups are selected by promoting a selection of one of their children
194 return false;
195}
196
197
199{
200 BOX2I bbox;
201
202 for( EDA_ITEM* item : m_items )
203 {
204 if( item->Type() == SCH_SYMBOL_T || item->Type() == LIB_SYMBOL_T )
205 bbox.Merge( static_cast<SYMBOL*>( item )->GetBoundingBox() );
206 else
207 bbox.Merge( item->GetBoundingBox() );
208 }
209
210 bbox.Inflate( schIUScale.MilsToIU( 10 ) );
211
212 return bbox;
213}
214
215
216INSPECT_RESULT SCH_GROUP::Visit( INSPECTOR aInspector, void* aTestData,
217 const std::vector<KICAD_T>& aScanTypes )
218{
219 for( KICAD_T scanType : aScanTypes )
220 {
221 if( scanType == Type() )
222 {
223 if( INSPECT_RESULT::QUIT == aInspector( this, aTestData ) )
224 return INSPECT_RESULT::QUIT;
225 }
226 }
227
228 return INSPECT_RESULT::CONTINUE;
229}
230
231
232std::vector<int> SCH_GROUP::ViewGetLayers() const
233{
234 return { LAYER_SCHEMATIC_ANCHOR };
235}
236
237
238double SCH_GROUP::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
239{
241 return LOD_SHOW;
242
243 return LOD_HIDE;
244}
245
246
247void SCH_GROUP::Move( const VECTOR2I& aMoveVector )
248{
249 for( EDA_ITEM* member : m_items )
250 {
251 EDA_ITEM_FLAGS flags = member->GetFlags();
252
253 if( member->Type() == SCH_LINE_T )
254 member->SetFlags( STARTPOINT | ENDPOINT );
255
256 static_cast<SCH_ITEM*>( member )->Move( aMoveVector );
257
258 member->SetFlags( flags );
259 }
260}
261
262
263void SCH_GROUP::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
264{
265 for( EDA_ITEM* member : m_items )
266 {
267 EDA_ITEM_FLAGS flags = member->GetFlags();
268
269 if( member->Type() == SCH_LINE_T )
270 member->SetFlags( STARTPOINT | ENDPOINT );
271
272 static_cast<SCH_ITEM*>( member )->Rotate( aCenter, aRotateCCW );
273
274 member->SetFlags( flags );
275 }
276}
277
278
280{
281 for( EDA_ITEM* member : m_items )
282 {
283 EDA_ITEM_FLAGS flags = member->GetFlags();
284
285 if( member->Type() == SCH_LINE_T )
286 member->SetFlags( STARTPOINT | ENDPOINT );
287
288 static_cast<SCH_ITEM*>( member )->MirrorHorizontally( aCenter );
289
290 member->SetFlags( flags );
291 }
292}
293
294
296{
297 for( EDA_ITEM* member : m_items )
298 {
299 EDA_ITEM_FLAGS flags = member->GetFlags();
300
301 if( member->Type() == SCH_LINE_T )
302 member->SetFlags( STARTPOINT | ENDPOINT );
303
304 static_cast<SCH_ITEM*>( member )->MirrorVertically( aCenter );
305
306 member->SetFlags( flags );
307 }
308}
309
310
311wxString SCH_GROUP::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
312{
313 if( m_name.empty() )
314 return wxString::Format( _( "Unnamed Group, %zu members" ), m_items.size() );
315 else
316 return wxString::Format( _( "Group '%s', %zu members" ), m_name, m_items.size() );
317}
318
319
321{
322 return BITMAPS::module;
323}
324
325
326void SCH_GROUP::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
327{
328 aList.emplace_back( _( "Group" ), m_name.empty() ? _( "<unnamed>" ) : m_name );
329 aList.emplace_back( _( "Members" ), wxString::Format( wxT( "%zu" ), m_items.size() ) );
330}
331
332
333bool SCH_GROUP::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
334{
335 return EDA_ITEM::Matches( UnescapeString( GetName() ), aSearchData );
336}
337
338
339void SCH_GROUP::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction, RECURSE_MODE aMode )
340{
341 try
342 {
343 for( EDA_ITEM* item : m_items )
344 {
345 aFunction( static_cast<SCH_ITEM*>( item ) );
346
347 if( item->Type() == SCH_GROUP_T && aMode == RECURSE_MODE::RECURSE )
348 static_cast<SCH_GROUP*>( item )->RunOnChildren( aFunction, RECURSE_MODE::RECURSE );
349 }
350 }
351 catch( std::bad_function_call& )
352 {
353 wxFAIL_MSG( wxT( "Error calling function in SCH_GROUP::RunOnChildren" ) );
354 }
355}
356
357
358bool SCH_GROUP::operator==( const SCH_ITEM& aSchItem ) const
359{
360 if( aSchItem.Type() != Type() )
361 return false;
362
363 const SCH_GROUP& other = static_cast<const SCH_GROUP&>( aSchItem );
364
365 return *this == other;
366}
367
368
369bool SCH_GROUP::operator==( const SCH_GROUP& aOther ) const
370{
371 if( m_items.size() != aOther.m_items.size() )
372 return false;
373
374 // The items in groups are in unordered sets hashed by the pointer value, so we need to
375 // order them by UUID (EDA_ITEM_SET) to compare
376 EDA_ITEM_SET itemSet( m_items.begin(), m_items.end() );
377 EDA_ITEM_SET otherItemSet( aOther.m_items.begin(), aOther.m_items.end() );
378
379 for( auto it1 = itemSet.begin(), it2 = otherItemSet.begin(); it1 != itemSet.end(); ++it1, ++it2 )
380 {
381 // Compare UUID instead of the items themselves because we only care if the contents
382 // of the group has changed, not which elements in the group have changed
383 if( ( *it1 )->m_Uuid != ( *it2 )->m_Uuid )
384 return false;
385 }
386
387 return true;
388}
389
390
391double SCH_GROUP::Similarity( const SCH_ITEM& aOther ) const
392{
393 if( aOther.Type() != Type() )
394 return 0.0;
395
396 const SCH_GROUP& other = static_cast<const SCH_GROUP&>( aOther );
397
398 double similarity = 0.0;
399
400 for( EDA_ITEM* item : m_items )
401 {
402 for( EDA_ITEM* otherItem : other.m_items )
403 {
404 similarity += static_cast<SCH_ITEM*>( item )->Similarity( *static_cast<SCH_ITEM*>( otherItem ) );
405 }
406 }
407
408 return similarity / m_items.size();
409}
410
411
412static struct SCH_GROUP_DESC
413{
415 {
422
423 propMgr.Mask( TYPE_HASH( SCH_GROUP ), TYPE_HASH( SCH_ITEM ), _HKI( "Position X" ) );
424 propMgr.Mask( TYPE_HASH( SCH_GROUP ), TYPE_HASH( SCH_ITEM ), _HKI( "Position Y" ) );
425
426 const wxString groupTab = _HKI( "Group Properties" );
427
428 propMgr.AddProperty(
430 groupTab );
431 }
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:114
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:33
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:558
constexpr Vec Centre() const
Definition: box2.h:97
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:658
The base class for create windows for drawing purpose.
A set of EDA_ITEMs (i.e., without duplicates).
Definition: eda_group.h:46
wxString m_name
Definition: eda_group.h:77
std::unordered_set< EDA_ITEM * > m_items
Definition: eda_group.h:76
wxString GetName() const
Definition: eda_group.h:51
LIB_ID m_designBlockLibId
Definition: eda_group.h:78
void AddItem(EDA_ITEM *aItem)
Add item to group.
Definition: eda_group.cpp:27
virtual EDA_ITEM * AsEdaItem()=0
void SetName(const wxString &aName)
Definition: eda_group.h:52
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:97
virtual EDA_GROUP * GetParentGroup() const
Definition: eda_item.h:115
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:109
virtual bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const
Compare the item against the search criteria in aSearchData.
Definition: eda_item.h:393
EDA_ITEM * GetParent() const
Definition: eda_item.h:111
static constexpr double LOD_HIDE
Return this constant from ViewGetLOD() to hide the item unconditionally.
Definition: view_item.h:174
static constexpr double LOD_SHOW
Return this constant from ViewGetLOD() to show the item unconditionally.
Definition: view_item.h:179
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:67
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:418
Provide class metadata.Helper macro to map type hashes to names.
Definition: property_mgr.h:85
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
void Mask(TYPE_ID aDerived, TYPE_ID aBase, const wxString &aName)
Sets a base class property as masked in a derived class.
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:87
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
void AddTypeCast(TYPE_CAST_BASE *aCast)
Register a type converter.
A set of SCH_ITEMs (i.e., without duplicates).
Definition: sch_group.h:52
SCH_GROUP * DeepDuplicate(bool addToParentGroup, SCH_COMMIT *aCommit=nullptr) const
Definition: sch_group.cpp:156
void Move(const VECTOR2I &aMoveVector) override
Move the item by aMoveVector to a new position.
Definition: sch_group.cpp:247
std::vector< int > ViewGetLayers() const override
Definition: sch_group.cpp:232
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition: sch_group.cpp:320
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
Definition: sch_group.cpp:263
double Similarity(const SCH_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
Definition: sch_group.cpp:391
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: sch_group.cpp:130
static bool WithinScope(SCH_ITEM *aItem, SCH_GROUP *aScope, bool isSymbolEditor)
Definition: sch_group.cpp:103
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: sch_group.cpp:333
bool operator==(const SCH_GROUP &aOther) const
Definition: sch_group.cpp:369
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
Definition: sch_group.cpp:326
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
Definition: sch_group.cpp:311
SCH_GROUP * DeepClone() const
Definition: sch_group.cpp:138
double ViewGetLOD(int aLayer, const KIGFX::VIEW *aView) const override
Definition: sch_group.cpp:238
INSPECT_RESULT Visit(INSPECTOR aInspector, void *aTestData, const std::vector< KICAD_T > &aScanTypes) override
May be re-implemented for each derived class in order to handle all the types given by its member dat...
Definition: sch_group.cpp:216
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
Definition: sch_group.cpp:295
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode) override
Definition: sch_group.cpp:339
void SetPosition(const VECTOR2I &aNewpos) override
Definition: sch_group.cpp:122
std::unordered_set< SCH_ITEM * > GetSchItems() const
Definition: sch_group.cpp:50
static EDA_GROUP * TopLevelGroup(SCH_ITEM *aItem, EDA_GROUP *aScope, bool isSymbolEditor)
Definition: sch_group.cpp:97
void swapData(SCH_ITEM *aImage) override
Swap the internal data structures aItem with the schematic item.
Definition: sch_group.cpp:173
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
Definition: sch_group.cpp:279
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
Definition: sch_group.cpp:184
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_group.cpp:198
VECTOR2I GetPosition() const override
Definition: sch_group.cpp:116
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:168
SCH_ITEM * Duplicate(bool addToParentGroup, SCH_COMMIT *aCommit=nullptr, bool doClone=false) const
Routine to create a new copy of given item.
Definition: sch_item.cpp:159
Schematic symbol object.
Definition: sch_symbol.h:75
A base class for LIB_SYMBOL and SCH_SYMBOL.
Definition: symbol.h:63
This file is part of the common library.
#define _HKI(x)
#define _(s)
RECURSE_MODE
Definition: eda_item.h:49
INSPECT_RESULT
Definition: eda_item.h:43
std::set< EDA_ITEM *, CompareByUuid > EDA_ITEM_SET
Definition: eda_item.h:559
const INSPECTOR_FUNC & INSPECTOR
std::function passed to nested users by ref, avoids copying std::function.
Definition: eda_item.h:90
#define IGNORE_PARENT_GROUP
Definition: eda_item.h:54
#define ENDPOINT
ends. (Used to support dragging.)
std::uint32_t EDA_ITEM_FLAGS
#define STARTPOINT
When a line is selected, these flags indicate which.
@ LAYER_SCHEMATIC_ANCHOR
Definition: layer_ids.h:488
Message panel definition file.
#define TYPE_HASH(x)
Definition: property.h:72
#define REGISTER_TYPE(x)
Definition: property_mgr.h:371
static struct SCH_GROUP_DESC _SCH_GROUP_DESC
EDA_GROUP * getNestedGroup(SCH_ITEM *aItem, EDA_GROUP *aScope, bool isSymbolEditor)
Returns the top level group inside the aScope group, or nullptr.
Definition: sch_group.cpp:78
EDA_GROUP * getClosestGroup(SCH_ITEM *aItem, bool isSymbolEditor)
Definition: sch_group.cpp:68
Class to handle a set of SCH_ITEMs.
wxString UnescapeString(const wxString &aSource)
constexpr int MilsToIU(int mils) const
Definition: base_units.h:97
constexpr int delta
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ SCH_GROUP_T
Definition: typeinfo.h:173
@ SCH_LINE_T
Definition: typeinfo.h:163
@ LIB_SYMBOL_T
Definition: typeinfo.h:148
@ SCH_SYMBOL_T
Definition: typeinfo.h:172