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
311void SCH_GROUP::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
312 int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
313{
314 // TODO: should we plot the name & border of named groups?
315}
316
317
318wxString SCH_GROUP::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
319{
320 if( m_name.empty() )
321 return wxString::Format( _( "Unnamed Group, %zu members" ), m_items.size() );
322 else
323 return wxString::Format( _( "Group '%s', %zu members" ), m_name, m_items.size() );
324}
325
326
328{
329 return BITMAPS::module;
330}
331
332
333void SCH_GROUP::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
334{
335 aList.emplace_back( _( "Group" ), m_name.empty() ? _( "<unnamed>" ) : m_name );
336 aList.emplace_back( _( "Members" ), wxString::Format( wxT( "%zu" ), m_items.size() ) );
337}
338
339
340bool SCH_GROUP::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
341{
342 return EDA_ITEM::Matches( UnescapeString( GetName() ), aSearchData );
343}
344
345
346void SCH_GROUP::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction, RECURSE_MODE aMode )
347{
348 try
349 {
350 for( EDA_ITEM* item : m_items )
351 {
352 aFunction( static_cast<SCH_ITEM*>( item ) );
353
354 if( item->Type() == SCH_GROUP_T && aMode == RECURSE_MODE::RECURSE )
355 static_cast<SCH_GROUP*>( item )->RunOnChildren( aFunction, RECURSE_MODE::RECURSE );
356 }
357 }
358 catch( std::bad_function_call& )
359 {
360 wxFAIL_MSG( wxT( "Error calling function in SCH_GROUP::RunOnChildren" ) );
361 }
362}
363
364
365bool SCH_GROUP::operator==( const SCH_ITEM& aSchItem ) const
366{
367 if( aSchItem.Type() != Type() )
368 return false;
369
370 const SCH_GROUP& other = static_cast<const SCH_GROUP&>( aSchItem );
371
372 return *this == other;
373}
374
375
376bool SCH_GROUP::operator==( const SCH_GROUP& aOther ) const
377{
378 if( m_items.size() != aOther.m_items.size() )
379 return false;
380
381 // The items in groups are in unordered sets hashed by the pointer value, so we need to
382 // order them by UUID (EDA_ITEM_SET) to compare
383 EDA_ITEM_SET itemSet( m_items.begin(), m_items.end() );
384 EDA_ITEM_SET otherItemSet( aOther.m_items.begin(), aOther.m_items.end() );
385
386 for( auto it1 = itemSet.begin(), it2 = otherItemSet.begin(); it1 != itemSet.end(); ++it1, ++it2 )
387 {
388 // Compare UUID instead of the items themselves because we only care if the contents
389 // of the group has changed, not which elements in the group have changed
390 if( ( *it1 )->m_Uuid != ( *it2 )->m_Uuid )
391 return false;
392 }
393
394 return true;
395}
396
397
398double SCH_GROUP::Similarity( const SCH_ITEM& aOther ) const
399{
400 if( aOther.Type() != Type() )
401 return 0.0;
402
403 const SCH_GROUP& other = static_cast<const SCH_GROUP&>( aOther );
404
405 double similarity = 0.0;
406
407 for( EDA_ITEM* item : m_items )
408 {
409 for( EDA_ITEM* otherItem : other.m_items )
410 {
411 similarity += static_cast<SCH_ITEM*>( item )->Similarity( *static_cast<SCH_ITEM*>( otherItem ) );
412 }
413 }
414
415 return similarity / m_items.size();
416}
417
418
419static struct SCH_GROUP_DESC
420{
422 {
429
430 propMgr.Mask( TYPE_HASH( SCH_GROUP ), TYPE_HASH( SCH_ITEM ), _HKI( "Position X" ) );
431 propMgr.Mask( TYPE_HASH( SCH_GROUP ), TYPE_HASH( SCH_ITEM ), _HKI( "Position Y" ) );
432
433 const wxString groupTab = _HKI( "Group Properties" );
434
435 propMgr.AddProperty(
437 groupTab );
438 }
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:98
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
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.
Definition: property_mgr.h:74
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:76
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:327
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:398
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:340
bool operator==(const SCH_GROUP &aOther) const
Definition: sch_group.cpp:376
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:333
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
Definition: sch_group.cpp:318
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:346
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
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.
Definition: sch_group.cpp:311
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:137
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:50
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:489
Message panel definition file.
#define TYPE_HASH(x)
Definition: property.h:72
#define REGISTER_TYPE(x)
Definition: property_mgr.h:351
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
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:174
@ SCH_LINE_T
Definition: typeinfo.h:164
@ LIB_SYMBOL_T
Definition: typeinfo.h:149
@ SCH_SYMBOL_T
Definition: typeinfo.h:173