KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_marker.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 The KiCad Developers, see AUTHORS.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, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <sch_draw_panel.h>
22#include <google/protobuf/any.pb.h>
23#include <api/api_enums.h>
24#include <api/api_sch_utils.h>
25#include <api/api_utils.h>
26#include <api/schematic/schematic_rules.pb.h>
27#include <trigo.h>
28#include <widgets/msgpanel.h>
29#include <bitmaps.h>
30#include <base_units.h>
31#include <eda_draw_frame.h>
32#include <erc/erc_settings.h>
33#include <sch_marker.h>
34#include <schematic.h>
35#include <widgets/ui_common.h>
37#include <pgm_base.h>
40#include <erc/erc_item.h>
41#include <sch_screen.h>
42
44#define SCALING_FACTOR schIUScale.mmToIU( 0.15 )
45
46
47SCH_MARKER::SCH_MARKER( std::shared_ptr<ERC_ITEM> aItem, const VECTOR2I& aPos ) :
48 SCH_ITEM( nullptr, SCH_MARKER_T ),
50{
51 if( m_rcItem )
52 m_rcItem->SetParent( this );
53
54 m_Pos = aPos;
55}
56
57
59{
60 if( m_rcItem )
61 m_rcItem->SetParent( nullptr );
62}
63
64
66{
67 SCH_MARKER* res = new SCH_MARKER( *this );
68
69 // An RC_ITEM is shared between its marker and various tree views. It cannot be shared between
70 // two markers.
71 if( m_rcItem )
72 {
73 res->m_rcItem = std::make_shared<ERC_ITEM>(
74 *std::static_pointer_cast<ERC_ITEM>( m_rcItem ) );
75 res->m_rcItem->SetParent( res );
76 }
77
78 return res;
79}
80
81
83{
84 SCH_MARKER* item = static_cast<SCH_MARKER*>( aItem );
85
86 std::swap( m_Pos, item->m_Pos );
87
88 std::swap( m_markerType, item->m_markerType );
89 std::swap( m_excluded, item->m_excluded );
90 std::swap( m_comment, item->m_comment );
91
92 std::swap( m_rcItem, item->m_rcItem );
93 {
94 if( m_rcItem )
95 m_rcItem->SetParent( this );
96
97 if( item->m_rcItem )
98 item->m_rcItem->SetParent( item );
99 }
100
101 std::swap( m_scalingFactor, item->m_scalingFactor );
102 std::swap( m_shapeBoundingBox, item->m_shapeBoundingBox );
103}
104
105
106static void ToProto( kiapi::schematic::ErcMarker& aMsg, const SCH_MARKER& aMarker )
107{
108 std::shared_ptr<ERC_ITEM> erc = std::static_pointer_cast<ERC_ITEM>( aMarker.GetRCItem() );
109
110 aMsg.set_error_type(
111 ToProtoEnum<ERCE_T, kiapi::schematic::ErcErrorType>( static_cast<ERCE_T>( erc->GetErrorCode() ) ) );
112
113 kiapi::common::PackVector2( *aMsg.mutable_position(), aMarker.GetPos(), schIUScale );
114
115 if( erc->IsSheetSpecific() )
116 PackSheetPath( *aMsg.mutable_sheet_specific_path(), erc->GetSpecificSheetPath() );
117
118 if( erc->MainItemHasSheetPath() )
119 PackSheetPath( *aMsg.mutable_main_item_sheet_path(), erc->GetMainItemSheetPath() );
120
121 if( erc->AuxItemHasSheetPath() )
122 PackSheetPath( *aMsg.mutable_aux_item_sheet_path(), erc->GetAuxItemSheetPath() );
123
124 if( erc->GetErrorCode() == ERCE_GENERIC_WARNING
125 || erc->GetErrorCode() == ERCE_GENERIC_ERROR
126 || erc->GetErrorCode() == ERCE_UNRESOLVED_VARIABLE )
127 {
128 SCH_ITEM* sch_item = aMarker.Schematic()->ResolveItem( erc->GetMainItemID() );
129 SCH_ITEM* parent = sch_item ? static_cast<SCH_ITEM*>( sch_item->GetParent() ) : nullptr;
130 EDA_TEXT* text_item = dynamic_cast<EDA_TEXT*>( sch_item );
131
132 // SCH_FIELDs and SCH_ITEMs inside LIB_SYMBOLs don't have persistent KIIDs. So the
133 // exclusion must refer to the parent's KIID, and include the text of the original text
134 // item for later look-up.
135 if( parent && parent->IsType( { SCH_SYMBOL_T, SCH_LABEL_T, SCH_SHEET_T } ) && text_item )
136 {
137 aMsg.add_items()->set_value( parent->m_Uuid.AsStdString() );
138 aMsg.mutable_child()->set_text_value( text_item->GetText().ToUTF8() );
139 }
140 }
141
142 for( const KIID& id : erc->GetIDs() )
143 {
144 if( id != niluuid )
145 aMsg.add_items()->set_value( id.AsStdString() );
146 }
147}
148
149
150SCH_MARKER* SCH_MARKER::FromProto( const kiapi::schematic::ErcMarker& aMsg, const SCH_SHEET_LIST& aSheetList )
151{
153
154 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( code );
155
156 if( !ercItem )
157 return nullptr;
158
159 VECTOR2I pos = kiapi::common::UnpackVector2( aMsg.position(), schIUScale );
160
161 if( aMsg.has_aux_item_sheet_path() && !aMsg.has_main_item_sheet_path() )
162 return nullptr;
163
164 if( aMsg.has_sheet_specific_path() )
165 {
166 KIID_PATH path = kiapi::common::UnpackSheetPath( aMsg.sheet_specific_path() );
167 std::optional<SCH_SHEET_PATH> sheetPath = aSheetList.GetSheetPathByKIIDPath( path, true );
168
169 if( sheetPath.has_value() )
170 ercItem->SetSheetSpecificPath( sheetPath.value() );
171 else
172 return nullptr;
173 }
174
175 if( aMsg.has_main_item_sheet_path() )
176 {
177 KIID_PATH path = kiapi::common::UnpackSheetPath( aMsg.main_item_sheet_path() );
178 std::optional<SCH_SHEET_PATH> mainPath = aSheetList.GetSheetPathByKIIDPath( path, true );
179
180 if( mainPath.has_value() )
181 {
182 if( aMsg.has_aux_item_sheet_path() )
183 {
184 KIID_PATH auxPath =
185 kiapi::common::UnpackSheetPath( aMsg.aux_item_sheet_path() );
186 std::optional<SCH_SHEET_PATH> auxPathResolved =
187 aSheetList.GetSheetPathByKIIDPath( auxPath, true );
188
189 if( auxPathResolved.has_value() )
190 ercItem->SetItemsSheetPaths( mainPath.value(), auxPathResolved.value() );
191 else
192 return nullptr;
193 }
194 else
195 {
196 ercItem->SetItemsSheetPaths( mainPath.value() );
197 }
198 }
199 else
200 {
201 return nullptr;
202 }
203 }
204
205 if( aMsg.has_child() && aMsg.items_size() > 0 )
206 {
207 SCH_ITEM* parent = aSheetList.ResolveItem( KIID( aMsg.items( 0 ).value() ) );
208
209 if( !parent )
210 return nullptr;
211
212 wxString text = wxString::FromUTF8( aMsg.child().text_value() );
213 KIID uuid = niluuid;
214
215 parent->RunOnChildren(
216 [&]( SCH_ITEM* child )
217 {
218 if( EDA_TEXT* text_item = dynamic_cast<EDA_TEXT*>( child ) )
219 {
220 if( text_item->GetText() == text )
221 uuid = child->m_Uuid;
222 }
223 },
225
226 if( uuid == niluuid && parent->Type() == SCH_SYMBOL_T )
227 {
228 static_cast<SCH_SYMBOL*>( parent )->GetLibSymbolRef()->RunOnChildren(
229 [&]( SCH_ITEM* child )
230 {
231 if( child->Type() == SCH_FIELD_T )
232 {
233 // Match only on SCH_SYMBOL fields, not LIB_SYMBOL fields.
234 }
235 else if( EDA_TEXT* text_item = dynamic_cast<EDA_TEXT*>( child ) )
236 {
237 if( text_item->GetText() == text )
238 uuid = child->m_Uuid;
239 }
240 },
242 }
243
244 if( uuid != niluuid )
245 ercItem->SetItems( uuid );
246 else
247 return nullptr;
248 }
249 else
250 {
251 std::vector<KIID> ids;
252 ids.reserve( aMsg.items_size() );
253
254 for( const auto& item : aMsg.items() )
255 ids.emplace_back( item.value() );
256
257 ercItem->SetItems( ids );
258 }
259
260 SCH_MARKER* marker = new SCH_MARKER( std::move( ercItem ), pos );
261
262 return marker;
263}
264
265
266void SCH_MARKER::Serialize( google::protobuf::Any& aContainer ) const
267{
268 kiapi::schematic::ErcMarker msg;
269 ToProto( msg, *this );
270 aContainer.PackFrom( msg );
271}
272
273
274bool SCH_MARKER::Deserialize( const google::protobuf::Any& aContainer )
275{
276 kiapi::schematic::ErcMarker msg;
277
278 if( !aContainer.UnpackTo( &msg ) )
279 return false;
280
281 if( !Schematic() )
282 return false;
283
284 std::unique_ptr<SCH_MARKER> tmp( SCH_MARKER::FromProto( msg, Schematic()->Hierarchy() ) );
285
286 if( !tmp )
287 return false;
288
289 swapData( tmp.get() );
290 return true;
291}
292
293
294#if defined(DEBUG)
295
296void SCH_MARKER::Show( int nestLevel, std::ostream& os ) const
297{
298 // for now, make it look like XML:
299 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << GetPos() << "/>\n";
300}
301
302#endif
303
304
305std::vector<int> SCH_MARKER::ViewGetLayers() const
306{
307 wxCHECK2_MSG( Schematic(), return {}, "No SCHEMATIC set for SCH_MARKER!" );
308
309 // Don't display sheet-specific markers when SCH_SHEET_PATHs do not match
310 std::shared_ptr<ERC_ITEM> ercItem = std::static_pointer_cast<ERC_ITEM>( GetRCItem() );
311
312 if( ercItem->IsSheetSpecific()
313 && ( ercItem->GetSpecificSheetPath() != Schematic()->CurrentSheet() ) )
314 {
315 return {};
316 }
317
318 std::vector<int> layers( 2 );
319
320 if( IsExcluded() )
321 {
322 layers[0] = LAYER_ERC_EXCLUSION;
323 }
324 else
325 {
326 switch( Schematic()->ErcSettings().GetSeverity( m_rcItem->GetErrorCode() ) )
327 {
328 case SEVERITY::RPT_SEVERITY_IGNORE: return {};
329 case SEVERITY::RPT_SEVERITY_WARNING: layers[0] = LAYER_ERC_WARN; break;
330 default:
331 case SEVERITY::RPT_SEVERITY_ERROR: layers[0] = LAYER_ERC_ERR; break;
332 }
333 }
334
335 layers[1] = LAYER_SELECTION_SHADOWS;
336 return layers;
337}
338
339
341{
342 if( IsExcluded() )
343 return LAYER_ERC_EXCLUSION;
344
345 wxCHECK_MSG( Schematic(), LAYER_ERC_ERR, "No SCHEMATIC set for SCH_MARKER!" );
346
347 switch( Schematic()->ErcSettings().GetSeverity( m_rcItem->GetErrorCode() ) )
348 {
349 default:
352 }
353}
354
355
357{
358 return ::GetColorSettings( DEFAULT_THEME )->GetColor( GetColorLayer() );
359}
360
361
363{
364 if( IsExcluded() )
366
367 ERC_ITEM* item = static_cast<ERC_ITEM*>( m_rcItem.get() );
368
369 return Schematic()->ErcSettings().GetSeverity( item->GetErrorCode() );
370}
371
372
373bool SCH_MARKER::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
374{
375 return SCH_ITEM::Matches( m_rcItem->GetErrorMessage( true ), aSearchData );
376}
377
378
380{
381 return GetBoundingBoxMarker();
382}
383
384
385void SCH_MARKER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
386{
387 aList.emplace_back( _( "Type" ), _( "Marker" ) );
388 aList.emplace_back( _( "Violation" ), HYPERLINK_DV_RENDERER::StripMarkup( m_rcItem->GetErrorMessage( true ) ) );
389
390 switch( GetSeverity() )
391 {
393 aList.emplace_back( _( "Severity" ), _( "Ignore" ) );
394 break;
396 aList.emplace_back( _( "Severity" ), _( "Warning" ) );
397 break;
399 aList.emplace_back( _( "Severity" ), _( "Error" ) );
400 break;
401 default:
402 break;
403 }
404
406 {
407 aList.emplace_back( _( "Drawing Sheet" ), wxEmptyString );
408 }
409 else
410 {
411 wxString mainText;
412 wxString auxText;
413 EDA_ITEM* mainItem = nullptr;
414 EDA_ITEM* auxItem = nullptr;
415
416 if( m_rcItem->GetMainItemID() != niluuid )
417 mainItem = aFrame->ResolveItem( m_rcItem->GetMainItemID() );
418
419 if( m_rcItem->GetAuxItemID() != niluuid )
420 auxItem = aFrame->ResolveItem( m_rcItem->GetAuxItemID() );
421
422 if( mainItem )
423 mainText = mainItem->GetItemDescription( aFrame, true );
424
425 if( auxItem )
426 auxText = auxItem->GetItemDescription( aFrame, true );
427
428 aList.emplace_back( mainText, auxText );
429 }
430
431 if( IsExcluded() )
432 aList.emplace_back( _( "Excluded" ), m_comment );
433}
434
435
437{
438 return BITMAPS::erc;
439}
440
441
442void SCH_MARKER::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
443{
444 // Marker geometry isn't user-editable
445}
446
447
449{
450 // Marker geometry isn't user-editable
451}
452
453
455{
456 // Marker geometry isn't user-editable
457}
458
459
460bool SCH_MARKER::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
461{
462 return HitTestMarker( aPosition, aAccuracy );
463}
KICOMMON_API types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICOMMON_API KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
Definition api_enums.cpp:55
void PackSheetPath(types::SheetPath &aOutput, const SCH_SHEET_PATH &aInput)
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:123
BITMAPS
A list of all bitmap identifiers.
BOX2< VECTOR2I > BOX2I
Definition box2.h:927
The base class for create windows for drawing purpose.
virtual EDA_ITEM * ResolveItem(const KIID &aId, bool aAllowNullptrReturn=false) const
Fetch an item by KIID.
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const
Return a user-visible description string of this item.
Definition eda_item.cpp:304
const KIID m_Uuid
Definition eda_item.h:597
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:482
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:84
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:94
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:118
static std::shared_ptr< ERC_ITEM > Create(int aErrorCode)
Constructs an ERC_ITEM for the given error code.
Definition erc_item.cpp:305
SEVERITY GetSeverity(int aErrorCode) const
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
Definition kiid.h:46
std::string AsStdString() const
Definition kiid.cpp:270
bool IsExcluded() const
Definition marker_base.h:89
bool HitTestMarker(const VECTOR2I &aHitPosition, int aAccuracy) const
Test if the given VECTOR2I is within the bounds of this object.
std::shared_ptr< RC_ITEM > GetRCItem() const
int m_scalingFactor
Scaling factor to convert corners coordinates to internal units.
wxString m_comment
User supplied comment.
const VECTOR2I & GetPos() const
Definition marker_base.h:79
VECTOR2I m_Pos
Position of the marker.
@ MARKER_DRAWING_SHEET
Definition marker_base.h:52
MARKER_T m_markerType
The type of marker.
bool m_excluded
User has excluded this specific error.
std::shared_ptr< RC_ITEM > m_rcItem
enum MARKER_T GetMarkerType() const
Definition marker_base.h:87
BOX2I m_shapeBoundingBox
Bounding box of the graphic symbol relative to the position of the shape in marker shape units.
MARKER_BASE(int aScalingFactor, std::shared_ptr< RC_ITEM > aItem, MARKER_T aType=MARKER_UNSPEC)
BOX2I GetBoundingBoxMarker() const
Return the orthogonal, bounding box of this object for display purposes.
int GetErrorCode() const
Definition rc_item.h:158
void SetParent(MARKER_BASE *aMarker)
Definition rc_item.h:133
SCH_ITEM * ResolveItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr, bool aAllowNullptrReturn=false) const
Definition schematic.h:193
ERC_SETTINGS & ErcSettings() const
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:165
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode)
Definition sch_item.h:641
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:281
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:52
bool IsType(const std::vector< KICAD_T > &aScanTypes) const override
Check whether the item is one of the listed types.
Definition sch_item.h:180
SEVERITY GetSeverity() const override
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxDat) const override
Compare DRC marker main and auxiliary text against search string.
wxString GetClass() const override
Return the class name.
Definition sch_marker.h:47
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
SCH_LAYER_ID GetColorLayer() const
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
std::vector< int > ViewGetLayers() const override
Return the layers the item is drawn on (which may be more than its "home" layer)
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
void swapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
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.
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
static SCH_MARKER * FromProto(const kiapi::schematic::ErcMarker &aMsg, const SCH_SHEET_LIST &aSheetList)
KIGFX::COLOR4D getColor() const override
BOX2I const GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
SCH_MARKER(std::shared_ptr< ERC_ITEM > aItem, const VECTOR2I &aPos)
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
std::optional< SCH_SHEET_PATH > GetSheetPathByKIIDPath(const KIID_PATH &aPath, bool aIncludeLastSheet=true) const
Finds a SCH_SHEET_PATH that matches the provided KIID_PATH.
SCH_ITEM * ResolveItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr, bool aAllowNullptrReturn=false) const
Fetch a SCH_ITEM by ID.
Schematic symbol object.
Definition sch_symbol.h:75
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode) override
#define _(s)
@ NO_RECURSE
Definition eda_item.h:52
ERCE_T
ERC error codes.
@ ERCE_UNRESOLVED_VARIABLE
A text variable could not be resolved.
@ ERCE_GENERIC_ERROR
@ ERCE_GENERIC_WARNING
KIID niluuid(0)
SCH_LAYER_ID
Eeschema drawing layers.
Definition layer_ids.h:471
@ LAYER_ERC_WARN
Definition layer_ids.h:501
@ LAYER_ERC_EXCLUSION
Definition layer_ids.h:503
@ LAYER_ERC_ERR
Definition layer_ids.h:502
@ LAYER_SELECTION_SHADOWS
Definition layer_ids.h:517
Message panel definition file.
KICOMMON_API KIID_PATH UnpackSheetPath(const types::SheetPath &aInput)
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackVector2(types::Vector2 &aOutput, const VECTOR2I &aInput, const EDA_IU_SCALE &aScale)
see class PGM_BASE
SEVERITY
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_EXCLUSION
@ RPT_SEVERITY_IGNORE
#define SCALING_FACTOR
Factor to convert the maker unit shape to internal units:
static void ToProto(kiapi::schematic::ErcMarker &aMsg, const SCH_MARKER &aMarker)
#define DEFAULT_THEME
std::string path
VECTOR3I res
@ SCH_SYMBOL_T
Definition typeinfo.h:168
@ SCH_FIELD_T
Definition typeinfo.h:146
@ SCH_MARKER_T
Definition typeinfo.h:154
Functions to provide common constants and other functions to assist in making a consistent UI.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683