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
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 ) )
225 }
226 }
227
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.
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: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.
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
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:75
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:498
Message panel definition file.
#define _HKI(x)
Definition page_info.cpp:44
#define TYPE_HASH(x)
Definition property.h:73
#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: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)
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:175
@ SCH_LINE_T
Definition typeinfo.h:165
@ LIB_SYMBOL_T
Definition typeinfo.h:150
@ SCH_SYMBOL_T
Definition typeinfo.h:174
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695