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
42
44{
46}
47
52
53std::unordered_set<SCH_ITEM*> SCH_GROUP::GetSchItems() const
54{
55 std::unordered_set<SCH_ITEM*> items;
56
57 for( EDA_ITEM* item : m_items )
58 {
59 if( item->IsSCH_ITEM() )
60 items.insert( static_cast<SCH_ITEM*>( item ) );
61 }
62
63 return items;
64}
65
66
67/*
68 * @return if not in the symbol editor and aItem is in a symbol, returns the
69 * symbol's parent group. Otherwise, returns the aItem's parent group.
70 */
71EDA_GROUP* getClosestGroup( SCH_ITEM* aItem, bool isSymbolEditor )
72{
73 if( !isSymbolEditor && aItem->GetParent() && aItem->GetParent()->Type() == SCH_SYMBOL_T )
74 return static_cast<SCH_SYMBOL*>( aItem->GetParent() )->GetParentGroup();
75 else
76 return aItem->GetParentGroup();
77}
78
79
81EDA_GROUP* getNestedGroup( SCH_ITEM* aItem, EDA_GROUP* aScope, bool isSymbolEditor )
82{
83 EDA_GROUP* group = getClosestGroup( aItem, isSymbolEditor );
84
85 if( group == aScope )
86 return nullptr;
87
88 while( group && group->AsEdaItem()->GetParentGroup() && group->AsEdaItem()->GetParentGroup() != aScope )
89 {
90 if( group->AsEdaItem()->GetParent()->Type() == LIB_SYMBOL_T && isSymbolEditor )
91 break;
92
93 group = group->AsEdaItem()->GetParentGroup();
94 }
95
96 return group;
97}
98
99
100EDA_GROUP* SCH_GROUP::TopLevelGroup( SCH_ITEM* aItem, EDA_GROUP* aScope, bool isSymbolEditor )
101{
102 return getNestedGroup( aItem, aScope, isSymbolEditor );
103}
104
105
106bool SCH_GROUP::WithinScope( SCH_ITEM* aItem, SCH_GROUP* aScope, bool isSymbolEditor )
107{
108 EDA_GROUP* group = getClosestGroup( aItem, isSymbolEditor );
109
110 if( group && group == aScope )
111 return true;
112
113 EDA_GROUP* nested = getNestedGroup( aItem, aScope, isSymbolEditor );
114
115 return nested && nested->AsEdaItem()->GetParentGroup() && nested->AsEdaItem()->GetParentGroup() == aScope;
116}
117
118
120{
121 return GetBoundingBox().Centre();
122}
123
124
125void SCH_GROUP::SetPosition( const VECTOR2I& aNewpos )
126{
127 VECTOR2I delta = aNewpos - GetPosition();
128
129 Move( delta );
130}
131
132
134{
135 // Use copy constructor to get the same uuid and other fields
136 SCH_GROUP* newGroup = new SCH_GROUP( *this );
137 return newGroup;
138}
139
140
142{
143 // Use copy constructor to get the same uuid and other fields
144 SCH_GROUP* newGroup = new SCH_GROUP( *this );
145 newGroup->m_items.clear();
146
147 for( EDA_ITEM* member : m_items )
148 {
149 if( member->Type() == SCH_GROUP_T )
150 newGroup->AddItem( static_cast<SCH_GROUP*>( member )->DeepClone() );
151 else
152 newGroup->AddItem( static_cast<SCH_ITEM*>( member->Clone() ) );
153 }
154
155 return newGroup;
156}
157
158
159SCH_GROUP* SCH_GROUP::DeepDuplicate( bool addToParentGroup, SCH_COMMIT* aCommit ) const
160{
161 SCH_GROUP* newGroup = static_cast<SCH_GROUP*>( Duplicate( addToParentGroup, aCommit ) );
162 newGroup->m_items.clear();
163
164 for( EDA_ITEM* member : m_items )
165 {
166 if( member->Type() == SCH_GROUP_T )
167 newGroup->AddItem( static_cast<SCH_GROUP*>( member )->DeepDuplicate( IGNORE_PARENT_GROUP ) );
168 else
169 newGroup->AddItem( static_cast<SCH_ITEM*>( member )->Duplicate( IGNORE_PARENT_GROUP ) );
170 }
171
172 return newGroup;
173}
174
175
177{
178 assert( aImage->Type() == SCH_GROUP_T );
179 SCH_GROUP* image = static_cast<SCH_GROUP*>( aImage );
180
181 std::swap( m_items, image->m_items );
182 std::swap( m_name, image->m_name );
183 std::swap( m_designBlockLibId, image->m_designBlockLibId );
184}
185
186
187bool SCH_GROUP::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
188{
189 // Groups are selected by promoting a selection of one of their children
190 return false;
191}
192
193
194bool SCH_GROUP::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
195{
196 // Groups are selected by promoting a selection of one of their children
197 return false;
198}
199
200
202{
203 BOX2I bbox;
204
205 for( EDA_ITEM* item : m_items )
206 {
207 if( item->Type() == SCH_SYMBOL_T || item->Type() == LIB_SYMBOL_T )
208 bbox.Merge( static_cast<SYMBOL*>( item )->GetBoundingBox() );
209 else
210 bbox.Merge( item->GetBoundingBox() );
211 }
212
213 bbox.Inflate( schIUScale.MilsToIU( 10 ) );
214
215 return bbox;
216}
217
218
219INSPECT_RESULT SCH_GROUP::Visit( INSPECTOR aInspector, void* aTestData,
220 const std::vector<KICAD_T>& aScanTypes )
221{
222 for( KICAD_T scanType : aScanTypes )
223 {
224 if( scanType == Type() )
225 {
226 if( INSPECT_RESULT::QUIT == aInspector( this, aTestData ) )
228 }
229 }
230
232}
233
234
235std::vector<int> SCH_GROUP::ViewGetLayers() const
236{
237 return { LAYER_SCHEMATIC_ANCHOR };
238}
239
240
241double SCH_GROUP::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
242{
244 return LOD_SHOW;
245
246 return LOD_HIDE;
247}
248
249
250void SCH_GROUP::Move( const VECTOR2I& aMoveVector )
251{
252 for( EDA_ITEM* member : m_items )
253 {
254 EDA_ITEM_FLAGS flags = member->GetFlags();
255
256 if( member->Type() == SCH_LINE_T )
257 member->SetFlags( STARTPOINT | ENDPOINT );
258
259 static_cast<SCH_ITEM*>( member )->Move( aMoveVector );
260
261 member->SetFlags( flags );
262 }
263}
264
265
266void SCH_GROUP::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
267{
268 for( EDA_ITEM* member : m_items )
269 {
270 EDA_ITEM_FLAGS flags = member->GetFlags();
271
272 if( member->Type() == SCH_LINE_T )
273 member->SetFlags( STARTPOINT | ENDPOINT );
274
275 static_cast<SCH_ITEM*>( member )->Rotate( aCenter, aRotateCCW );
276
277 member->SetFlags( flags );
278 }
279}
280
281
283{
284 for( EDA_ITEM* member : m_items )
285 {
286 EDA_ITEM_FLAGS flags = member->GetFlags();
287
288 if( member->Type() == SCH_LINE_T )
289 member->SetFlags( STARTPOINT | ENDPOINT );
290
291 static_cast<SCH_ITEM*>( member )->MirrorHorizontally( aCenter );
292
293 member->SetFlags( flags );
294 }
295}
296
297
299{
300 for( EDA_ITEM* member : m_items )
301 {
302 EDA_ITEM_FLAGS flags = member->GetFlags();
303
304 if( member->Type() == SCH_LINE_T )
305 member->SetFlags( STARTPOINT | ENDPOINT );
306
307 static_cast<SCH_ITEM*>( member )->MirrorVertically( aCenter );
308
309 member->SetFlags( flags );
310 }
311}
312
313
314void SCH_GROUP::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
315 int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
316{
317 // TODO: should we plot the name & border of named groups?
318}
319
320
321wxString SCH_GROUP::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
322{
323 if( m_name.empty() )
324 return wxString::Format( _( "Unnamed Group, %zu members" ), m_items.size() );
325 else
326 return wxString::Format( _( "Group '%s', %zu members" ), m_name, m_items.size() );
327}
328
329
331{
332 return BITMAPS::module;
333}
334
335
336void SCH_GROUP::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
337{
338 aList.emplace_back( _( "Group" ), m_name.empty() ? _( "<unnamed>" ) : m_name );
339 aList.emplace_back( _( "Members" ), wxString::Format( wxT( "%zu" ), m_items.size() ) );
340}
341
342
343bool SCH_GROUP::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
344{
345 return EDA_ITEM::Matches( UnescapeString( GetName() ), aSearchData );
346}
347
348
349void SCH_GROUP::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction, RECURSE_MODE aMode )
350{
351 try
352 {
353 for( EDA_ITEM* item : m_items )
354 {
355 aFunction( static_cast<SCH_ITEM*>( item ) );
356
357 if( item->Type() == SCH_GROUP_T && aMode == RECURSE_MODE::RECURSE )
358 static_cast<SCH_GROUP*>( item )->RunOnChildren( aFunction, RECURSE_MODE::RECURSE );
359 }
360 }
361 catch( std::bad_function_call& )
362 {
363 wxFAIL_MSG( wxT( "Error calling function in SCH_GROUP::RunOnChildren" ) );
364 }
365}
366
367
368bool SCH_GROUP::operator==( const SCH_ITEM& aSchItem ) const
369{
370 if( aSchItem.Type() != Type() )
371 return false;
372
373 const SCH_GROUP& other = static_cast<const SCH_GROUP&>( aSchItem );
374
375 return *this == other;
376}
377
378
379bool SCH_GROUP::operator==( const SCH_GROUP& aOther ) const
380{
381 if( m_items.size() != aOther.m_items.size() )
382 return false;
383
384 // The items in groups are in unordered sets hashed by the pointer value, so we need to
385 // order them by UUID (EDA_ITEM_SET) to compare
386 EDA_ITEM_SET itemSet( m_items.begin(), m_items.end() );
387 EDA_ITEM_SET otherItemSet( aOther.m_items.begin(), aOther.m_items.end() );
388
389 for( auto it1 = itemSet.begin(), it2 = otherItemSet.begin(); it1 != itemSet.end(); ++it1, ++it2 )
390 {
391 // Compare UUID instead of the items themselves because we only care if the contents
392 // of the group has changed, not which elements in the group have changed
393 if( ( *it1 )->m_Uuid != ( *it2 )->m_Uuid )
394 return false;
395 }
396
397 return true;
398}
399
400
401double SCH_GROUP::Similarity( const SCH_ITEM& aOther ) const
402{
403 if( aOther.Type() != Type() )
404 return 0.0;
405
406 const SCH_GROUP& other = static_cast<const SCH_GROUP&>( aOther );
407
408 double similarity = 0.0;
409
410 for( EDA_ITEM* item : m_items )
411 {
412 for( EDA_ITEM* otherItem : other.m_items )
413 {
414 similarity += static_cast<SCH_ITEM*>( item )->Similarity( *static_cast<SCH_ITEM*>( otherItem ) );
415 }
416 }
417
418 return similarity / m_items.size();
419}
420
421
422static struct SCH_GROUP_DESC
423{
425 {
432
433 propMgr.Mask( TYPE_HASH( SCH_GROUP ), TYPE_HASH( SCH_ITEM ), _HKI( "Position X" ) );
434 propMgr.Mask( TYPE_HASH( SCH_GROUP ), TYPE_HASH( SCH_ITEM ), _HKI( "Position Y" ) );
435
436 const wxString groupTab = _HKI( "Group Properties" );
437
438 propMgr.AddProperty(
440 groupTab );
441 }
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:114
BITMAPS
A list of all bitmap identifiers.
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
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
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:116
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
virtual bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const
Compare the item against the search criteria in aSearchData.
Definition eda_item.h:401
EDA_ITEM * GetParent() const
Definition eda_item.h:112
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:39
static constexpr double LOD_HIDE
Return this constant from ViewGetLOD() to hide the item unconditionally.
Definition view_item.h:180
static constexpr double LOD_SHOW
Return this constant from ViewGetLOD() to show the item unconditionally.
Definition view_item.h:185
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:66
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition view.h:422
Base plotter engine class.
Definition plotter.h:121
Provide class metadata.Helper macro to map type hashes to names.
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()
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
void Move(const VECTOR2I &aMoveVector) override
Move the item by aMoveVector to a new position.
std::vector< int > ViewGetLayers() const override
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
double Similarity(const SCH_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
static bool WithinScope(SCH_ITEM *aItem, SCH_GROUP *aScope, bool isSymbolEditor)
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
bool operator==(const SCH_GROUP &aOther) const
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.
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
SCH_GROUP * DeepClone() const
double ViewGetLOD(int aLayer, const KIGFX::VIEW *aView) const override
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...
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode) override
void SetPosition(const VECTOR2I &aNewpos) override
std::unordered_set< SCH_ITEM * > GetSchItems() const
Definition sch_group.cpp:53
static EDA_GROUP * TopLevelGroup(SCH_ITEM *aItem, EDA_GROUP *aScope, bool isSymbolEditor)
void swapData(SCH_ITEM *aImage) override
Swap the internal data structures aItem with the schematic item.
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
void Plot(PLOTTER *aPlotter, bool aBackground, const SCH_PLOT_OPTS &aPlotOpts, int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aDimmed) override
Plot the item to aPlotter.
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
VECTOR2I GetPosition() const override
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:167
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:137
void SetLayer(SCH_LAYER_ID aLayer)
Definition sch_item.h:322
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:51
Schematic symbol object.
Definition sch_symbol.h:76
A base class for LIB_SYMBOL and SCH_SYMBOL.
Definition symbol.h:63
This file is part of the common library.
#define _(s)
RECURSE_MODE
Definition eda_item.h:50
@ RECURSE
Definition eda_item.h:51
INSPECT_RESULT
Definition eda_item.h:44
std::set< EDA_ITEM *, CompareByUuid > EDA_ITEM_SET
Definition eda_item.h:568
const INSPECTOR_FUNC & INSPECTOR
std::function passed to nested users by ref, avoids copying std::function.
Definition eda_item.h:91
#define IGNORE_PARENT_GROUP
Definition eda_item.h:55
#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:500
@ LAYER_GROUP
Definition layer_ids.h:503
Message panel definition file.
#define _HKI(x)
Definition page_info.cpp:44
#define TYPE_HASH(x)
Definition property.h:74
#define REGISTER_TYPE(x)
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:81
EDA_GROUP * getClosestGroup(SCH_ITEM *aItem, bool isSymbolEditor)
Definition sch_group.cpp:71
Class to handle a set of SCH_ITEMs.
wxString UnescapeString(const wxString &aSource)
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:177
@ SCH_LINE_T
Definition typeinfo.h:167
@ LIB_SYMBOL_T
Definition typeinfo.h:152
@ SCH_SYMBOL_T
Definition typeinfo.h:176
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695