KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_pin.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) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2015 Wayne Stambaugh <[email protected]>
6 * Copyright (C) 2018 CERN
7 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
8 * @author Jon Evans <[email protected]>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 */
23
24#include <sch_render_settings.h>
25#include "sch_pin.h"
26
28#include <lib_id.h>
29#include <lib_symbol.h>
30#include <pin_map.h>
31#include <sch_symbol.h>
32#include <sch_sheet_path.h>
33#include <api/api_enums.h>
34#include <api/api_utils.h>
35#include <base_units.h>
36#include <pgm_base.h>
37#include <pin_layout_cache.h>
38#include <plotters/plotter.h>
39#include <sch_draw_panel.h>
40#include <sch_edit_frame.h>
41#include <symbol_edit_frame.h>
44#include <trace_helpers.h>
45#include <trigo.h>
46#include <string_utils.h>
47#include <properties/property.h>
49#include <api/schematic/schematic_types.pb.h>
50
51wxString FormatStackedPinForDisplay( const wxString& aPinNumber, int aPinLength, int aTextSize, KIFONT::FONT* aFont,
52 const KIFONT::METRICS& aFontMetrics )
53{
54 // Check if this is stacked pin notation: [A,B,C]
55 if( !aPinNumber.StartsWith( "[" ) || !aPinNumber.EndsWith( "]" ) )
56 return aPinNumber;
57
58 // Escaping must never reach the user, so every display form below is built from the unescaped
59 // items. Range notation (e.g. 1-5) is preserved rather than expanded.
60 wxString inner = aPinNumber.Mid( 1, aPinNumber.Length() - 2 );
61 std::vector<wxString> parts = SplitStackedPinDisplayItems( inner );
62
63 if( parts.empty() )
64 return aPinNumber; // malformed; fallback
65
66 for( wxString& part : parts )
67 part.Trim( true ).Trim( false );
68
69 // Build the single-line (unescaped) form and check whether it fits along the pin.
70 wxString singleLine = "[";
71
72 for( size_t i = 0; i < parts.size(); ++i )
73 {
74 if( i > 0 )
75 singleLine += ",";
76
77 singleLine += parts[i];
78 }
79
80 singleLine += "]";
81
82 const int minPinTextWidth = schIUScale.MilsToIU( 50 );
83 const int maxPinTextWidth = std::max( aPinLength, minPinTextWidth );
84
85 VECTOR2D fontSize( aTextSize, aTextSize );
86 int penWidth = GetPenSizeForNormal( aTextSize );
87 VECTOR2I textExtents = aFont->StringBoundaryLimits( singleLine, fontSize, penWidth, false, false, aFontMetrics );
88
89 if( textExtents.x <= maxPinTextWidth )
90 return singleLine; // Fits already
91
92 // Build multi-line representation inside braces.
93 wxString result = "[";
94
95 for( size_t i = 0; i < parts.size(); ++i )
96 {
97 if( i > 0 )
98 result += "\n";
99
100 result += parts[i];
101 }
102
103 result += "]";
104 return result;
105}
106
107
108// small margin in internal units between the pin text and the pin line
109#define PIN_TEXT_MARGIN 4
110
114static int internalPinDecoSize( const RENDER_SETTINGS* aSettings, const SCH_PIN &aPin )
115{
116 const SCH_RENDER_SETTINGS* settings = static_cast<const SCH_RENDER_SETTINGS*>( aSettings );
117
118 if( settings && settings->m_PinSymbolSize )
119 return settings->m_PinSymbolSize;
120
121 return aPin.GetNameTextSize() != 0 ? aPin.GetNameTextSize() / 2 : aPin.GetNumberTextSize() / 2;
122}
123
124
128static int externalPinDecoSize( const RENDER_SETTINGS* aSettings, const SCH_PIN &aPin )
129{
130 const SCH_RENDER_SETTINGS* settings = static_cast<const SCH_RENDER_SETTINGS*>( aSettings );
131
132 if( settings && settings->m_PinSymbolSize )
133 return settings->m_PinSymbolSize;
134
135 return aPin.GetNumberTextSize() / 2;
136}
137
138
139SCH_PIN::SCH_PIN( LIB_SYMBOL* aParentSymbol ) :
140 SCH_ITEM( aParentSymbol, SCH_PIN_T, 0, 0 ),
141 m_libPin( nullptr ),
142 m_position( { 0, 0 } ),
143 m_length( schIUScale.MilsToIU( DEFAULT_PIN_LENGTH ) ),
144 m_orientation( PIN_ORIENTATION::PIN_RIGHT ),
145 m_shape( GRAPHIC_PINSHAPE::LINE ),
147 m_hidden( false ),
148 m_numTextSize( schIUScale.MilsToIU( DEFAULT_PINNUM_SIZE ) ),
149 m_nameTextSize( schIUScale.MilsToIU( DEFAULT_PINNAME_SIZE ) ),
150 m_isDangling( true )
151{
153 {
154 m_length = schIUScale.MilsToIU( cfg->m_Defaults.pin_length );
155 m_numTextSize = schIUScale.MilsToIU( cfg->m_Defaults.pin_num_size );
156 m_nameTextSize = schIUScale.MilsToIU( cfg->m_Defaults.pin_name_size );
157 }
158
159 m_layer = LAYER_DEVICE;
160}
161
162
163SCH_PIN::SCH_PIN( LIB_SYMBOL* aParentSymbol, const wxString& aName, const wxString& aNumber,
164 PIN_ORIENTATION aOrientation, ELECTRICAL_PINTYPE aPinType, int aLength,
165 int aNameTextSize, int aNumTextSize, int aBodyStyle, const VECTOR2I& aPos,
166 int aUnit ) :
167 SCH_ITEM( aParentSymbol, SCH_PIN_T, aUnit, aBodyStyle ),
168 m_libPin( nullptr ),
169 m_position( aPos ),
170 m_length( aLength ),
171 m_orientation( aOrientation ),
173 m_type( aPinType ),
174 m_hidden( false ),
175 m_numTextSize( aNumTextSize ),
176 m_nameTextSize( aNameTextSize ),
177 m_isDangling( true )
178{
179 SetName( aName );
180 SetNumber( aNumber );
181
183}
184
185
186SCH_PIN::SCH_PIN( SCH_SYMBOL* aParentSymbol, SCH_PIN* aLibPin ) :
187 SCH_ITEM( aParentSymbol, SCH_PIN_T, 0, 0 ),
188 m_libPin( aLibPin ),
192 m_isDangling( true )
193{
194 wxASSERT( aParentSymbol );
195
196 SetName( m_libPin->GetName() );
197 SetNumber( m_libPin->GetNumber() );
198 m_position = m_libPin->GetPosition();
199
201}
202
203
204SCH_PIN::SCH_PIN( SCH_SYMBOL* aParentSymbol, const wxString& aNumber, const wxString& aAlt,
205 const KIID& aUuid ) :
206 SCH_ITEM( aParentSymbol, SCH_PIN_T ),
207 m_libPin( nullptr ),
211 m_number( aNumber ),
212 m_alt( aAlt ),
213 m_isDangling( true )
214{
215 wxASSERT( aParentSymbol );
216
217 const_cast<KIID&>( m_Uuid ) = aUuid;
219}
220
221
222SCH_PIN::SCH_PIN( const SCH_PIN& aPin ) :
223 SCH_ITEM( aPin ),
224 m_libPin( aPin.m_libPin ),
226 m_position( aPin.m_position ),
227 m_length( aPin.m_length ),
229 m_shape( aPin.m_shape ),
230 m_type( aPin.m_type ),
231 m_hidden( aPin.m_hidden ),
234 m_alt( aPin.m_alt ),
236{
237 SetName( aPin.m_name );
238 SetNumber( aPin.m_number );
239
240 m_layer = aPin.m_layer;
241}
242
243
247
248
250{
251 SCH_ITEM::operator=( aPin );
252
253 m_libPin = aPin.m_libPin;
255 m_alt = aPin.m_alt;
256 m_name = aPin.m_name;
257 m_number = aPin.m_number;
258 m_position = aPin.m_position;
259 m_length = aPin.m_length;
261 m_shape = aPin.m_shape;
262 m_type = aPin.m_type;
263 m_hidden = aPin.m_hidden;
267 m_layoutCache.reset();
268
269 return *this;
270}
271
272
274{
275 wxCHECK( aItem && aItem->Type() == SCH_PIN_T, /* void */ );
276
277 SCH_PIN* pin = static_cast<SCH_PIN*>( aItem );
278
279 std::swap( m_libPin, pin->m_libPin );
280 std::swap( m_alternates, pin->m_alternates );
281 std::swap( m_alt, pin->m_alt );
282 std::swap( m_name, pin->m_name );
283 std::swap( m_number, pin->m_number );
284 std::swap( m_position, pin->m_position );
285 std::swap( m_length, pin->m_length );
286 std::swap( m_orientation, pin->m_orientation );
287 std::swap( m_shape, pin->m_shape );
288 std::swap( m_type, pin->m_type );
289 std::swap( m_hidden, pin->m_hidden );
290 std::swap( m_numTextSize, pin->m_numTextSize );
291 std::swap( m_nameTextSize, pin->m_nameTextSize );
292 std::swap( m_isDangling, pin->m_isDangling );
293}
294
295
296void SCH_PIN::Serialize( google::protobuf::Any& aContainer ) const
297{
298 using namespace kiapi::common;
299 using namespace kiapi::schematic::types;
300 SchematicPin pin;
301
302 pin.mutable_id()->set_value( m_Uuid.AsStdString() );
303 pin.set_name( GetBaseName().ToUTF8() );
304 pin.set_number( GetNumber().ToUTF8() );
305
306 PackVector2( *pin.mutable_position(), GetLocalPosition(), schIUScale );
307 PackDistance( *pin.mutable_length(), GetLength(), schIUScale );
309
312 pin.set_visible( IsVisible() );
313
314 PackDistance( *pin.mutable_name_text_size(), GetNameTextSize(), schIUScale );
315 PackDistance( *pin.mutable_number_text_size(), GetNumberTextSize(), schIUScale );
316
317 for( const ALT& alt : GetAlternates() | std::views::values )
318 {
319 SchematicPinAlternate* altProto = pin.add_alternates();
320 altProto->set_name( alt.m_Name.ToUTF8() );
321 altProto->set_shape( ToProtoEnum<GRAPHIC_PINSHAPE, SchematicPinShape>( alt.m_Shape ) );
322 altProto->set_electrical_type( ToProtoEnum<ELECTRICAL_PINTYPE, types::ElectricalPinType>( alt.m_Type ) );
323 }
324
325 if( !m_alt.IsEmpty() && m_alt != GetBaseName() )
326 pin.set_active_alternate( m_alt.ToUTF8() );
327
328 kiapi::common::PackCustomProperties( pin.mutable_custom_properties(), *this );
329 aContainer.PackFrom( pin );
330}
331
332
333bool SCH_PIN::Deserialize( const google::protobuf::Any& aContainer )
334{
335 using namespace kiapi::common;
336 using namespace kiapi::schematic::types;
337
338 SchematicPin pin;
339
340 if( !aContainer.UnpackTo( &pin ) )
341 return false;
342
343 const_cast<KIID&>( m_Uuid ) = KIID( pin.id().value() );
344 m_name = wxString::FromUTF8( pin.name() );
345 m_number = wxString::FromUTF8( pin.number() );
346
347 SetPosition( UnpackVector2( pin.position(), schIUScale ) );
348 SetLength( UnpackDistance( pin.length(), schIUScale ) );
350
351 m_type = FromProtoEnum<ELECTRICAL_PINTYPE>( pin.electrical_type() );
353 SetVisible( pin.visible() );
354
355 m_nameTextSize = UnpackDistance( pin.name_text_size(), schIUScale );
356 m_numTextSize = UnpackDistance( pin.number_text_size(), schIUScale );
357
358 std::map<wxString, ALT>& alts = GetAlternates();
359
360 for( const SchematicPinAlternate& altProto : pin.alternates() )
361 {
362 ALT alt;
363 alt.m_Name = wxString::FromUTF8( altProto.name() );
364 alt.m_Shape = FromProtoEnum<GRAPHIC_PINSHAPE>( altProto.shape() );
365 alt.m_Type = FromProtoEnum<ELECTRICAL_PINTYPE>( altProto.electrical_type() );
366 alts.emplace( alt.m_Name, alt );
367 }
368
369 kiapi::common::UnpackCustomProperties( pin.custom_properties(), *this );
370
371 if( m_layoutCache )
373
374 return true;
375}
376
377
379{
380 if( const SCH_SYMBOL* symbol = dynamic_cast<const SCH_SYMBOL*>( GetParentSymbol() ) )
381 return symbol->GetTransform().TransformCoordinate( m_position ) + symbol->GetPosition();
382 else
383 return m_position;
384}
385
387{
389 {
390 if( !m_libPin )
392
393 return m_libPin->GetOrientation();
394 }
395
396 return m_orientation;
397}
398
399
401{
402 if( !m_alt.IsEmpty() )
403 {
404 if( !m_libPin )
406
407 return m_libPin->GetAlt( m_alt ).m_Shape;
408 }
410 {
411 if( !m_libPin )
413
414 return m_libPin->GetShape();
415 }
416
417 return m_shape;
418}
419
420
422{
423 if( !m_length.has_value() )
424 {
425 if( !m_libPin )
426 return 0;
427
428 return m_libPin->GetLength();
429 }
430
431 return m_length.value();
432}
433
434
436{
437 if( !m_alt.IsEmpty() )
438 {
439 if( !m_libPin )
441
442 return m_libPin->GetAlt( m_alt ).m_Type;
443 }
445 {
446 if( !m_libPin )
448
449 return m_libPin->GetType();
450 }
451
452 return m_type;
453}
454
456{
457 if( aType == m_type )
458 return;
459
460 m_type = aType;
461
462 if( m_layoutCache )
464}
465
466
468{
469 // Use GetType() which correctly handles alternates
470 return ::GetCanonicalElectricalTypeName( GetType() );
471}
472
473
475{
476 // Use GetType() which correctly handles alternates
478}
479
480
482{
484 return false;
485
486 const SYMBOL* parent = GetParentSymbol();
487
488 if( parent->IsGlobalPower() )
489 return true;
490
491 // Local power symbols are never global, even with invisible pins
492 if( parent->IsLocalPower() )
493 return false;
494
495 // Legacy support: invisible power-in pins on non-power symbols act as global power
496 return !IsVisible();
497}
498
499
505
506
508{
509 return IsLocalPower() || IsGlobalPower();
510}
511
512
514{
515 if( !m_hidden.has_value() )
516 {
517 if( !m_libPin )
518 return true;
519
520 return m_libPin->IsVisible();
521 }
522
523 return !m_hidden.value();
524}
525
526
527const wxString& SCH_PIN::GetName() const
528{
529 if( !m_alt.IsEmpty() )
530 return m_alt;
531
532 return GetBaseName();
533}
534
535
536const wxString& SCH_PIN::GetBaseName() const
537{
538 if( m_libPin )
539 return m_libPin->GetBaseName();
540
541 return m_name;
542}
543
544
545void SCH_PIN::SetName( const wxString& aName )
546{
547 if( m_name == aName )
548 return;
549
550 m_name = aName;
551
552 // pin name string does not support spaces
553 m_name.Replace( wxT( " " ), wxT( "_" ) );
554
555 if( m_layoutCache )
557}
558
559
560void SCH_PIN::SetAlt( const wxString& aAlt )
561{
562 // Do not set the alternate pin definition to the default pin name. This breaks the library
563 // symbol comparison for the ERC and the library diff tool. It also incorrectly causes the
564 // schematic symbol pin alternate to be set.
565 if( aAlt.IsEmpty() || aAlt == GetBaseName() )
566 {
567 m_alt = wxEmptyString;
568 return;
569 }
570
571 if( !m_libPin )
572 {
573 wxFAIL_MSG( wxString::Format( wxS( "Pin '%s' has no corresponding lib_pin" ), m_number ) );
574 m_alt = wxEmptyString;
575 return;
576 }
577
578 if( !m_libPin->GetAlternates().contains( aAlt ) )
579 {
580 wxFAIL_MSG( wxString::Format( wxS( "Pin '%s' has no alterate '%s'" ), m_number, aAlt ) );
581 m_alt = wxEmptyString;
582 return;
583 }
584
585 m_alt = aAlt;
586}
587
589{
591 return false;
592
593 return m_isDangling;
594}
595
596
597bool SCH_PIN::SetIsDangling( bool aIsDangling )
598{
599 const bool changed = m_isDangling != aIsDangling;
600 m_isDangling = aIsDangling;
601 return changed;
602}
603
604
605bool SCH_PIN::IsStacked( const SCH_PIN* aPin ) const
606{
607 const auto isPassiveOrNic = []( ELECTRICAL_PINTYPE t )
608 {
610 };
611
612 const bool sameParent = m_parent == aPin->GetParent();
613 const bool samePos = GetPosition() == aPin->GetPosition();
614 const bool sameName = GetName() == aPin->GetName();
615 const bool typeCompat = GetType() == aPin->GetType()
616 || isPassiveOrNic( GetType() )
617 || isPassiveOrNic( aPin->GetType() );
618
619 wxLogTrace( traceStackedPins,
620 wxString::Format( "IsStacked: this='%s/%s' other='%s/%s' sameParent=%d samePos=%d sameName=%d typeCompat=%d",
621 GetName(), GetNumber(), aPin->GetName(), aPin->GetNumber(), sameParent,
622 samePos, sameName, typeCompat ) );
623
624 return sameParent && samePos && sameName && typeCompat;
625}
626
627
628bool SCH_PIN::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
629{
630 const SCH_SEARCH_DATA& schSearchData =
631 dynamic_cast<const SCH_SEARCH_DATA&>( aSearchData );
632
633 if( schSearchData.searchAllPins
634 && ( EDA_ITEM::Matches( GetName(), aSearchData )
635 || EDA_ITEM::Matches( GetNumber(), aSearchData ) ) )
636 {
637 return true;
638 }
639
640 SCH_SHEET_PATH* sheetPath = reinterpret_cast<SCH_SHEET_PATH*>( aAuxData );
641
642 return schSearchData.searchNetNames && sheetPath && MatchesNetName( aSearchData, sheetPath );
643}
644
645
646bool SCH_PIN::Replace( const EDA_SEARCH_DATA& aSearchData, void* aAuxData )
647{
648 bool isReplaced = false;
649
650 if( dynamic_cast<LIB_SYMBOL*>( GetParentSymbol() ) )
651 {
652 isReplaced |= EDA_ITEM::Replace( aSearchData, m_name );
653 isReplaced |= EDA_ITEM::Replace( aSearchData, m_number );
654 }
655 else
656 {
657 /* TODO: waiting on a way to override pins in the schematic...
658 isReplaced |= EDA_ITEM::Replace( aSearchData, m_name );
659 isReplaced |= EDA_ITEM::Replace( aSearchData, m_number );
660 */
661 }
662
663 return isReplaced;
664}
665
666
667bool SCH_PIN::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
668{
669 // When looking for an "exact" hit aAccuracy will be 0 which works poorly if the pin has
670 // no pin number or name. Give it a floor.
671 if( Schematic() )
672 aAccuracy = std::max( aAccuracy, Schematic()->Settings().m_PinSymbolSize / 4 );
673
674 BOX2I rect = GetBoundingBox( false, true, m_flags & SHOW_ELEC_TYPE );
675
676 return rect.Inflate( aAccuracy ).Contains( aPosition );
677}
678
679
680bool SCH_PIN::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
681{
683 return false;
684
685 BOX2I sel = aRect;
686
687 if ( aAccuracy )
688 sel.Inflate( aAccuracy );
689
690 if( aContained )
691 return sel.Contains( GetBoundingBox( false, false, false ) );
692
693 return sel.Intersects( GetBoundingBox( false, true, m_flags & SHOW_ELEC_TYPE ) );
694}
695
696
697const wxString& SCH_PIN::GetShownName() const
698{
699 if( !m_alt.IsEmpty() )
700 return m_alt;
701 else if( m_libPin )
702 return m_libPin->GetShownName();
703
704 return m_name;
705}
706
707
708const wxString& SCH_PIN::GetShownNumber() const
709{
710 return m_number;
711}
712
713
714std::vector<wxString> SCH_PIN::GetStackedPinNumbers( bool* aValid ) const
715{
716 return ExpandStackedPinNotation( GetShownNumber(), aValid );
717}
718
719
720int SCH_PIN::GetStackedPinCount( bool* aValid ) const
721{
722 const wxString& shown = GetShownNumber();
723 return CountStackedPinNotation( shown, aValid );
724}
725
726
727std::optional<wxString> SCH_PIN::GetSmallestLogicalNumber() const
728{
729 bool valid = false;
730 auto numbers = GetStackedPinNumbers( &valid );
731
732 if( valid && !numbers.empty() )
733 return numbers.front(); // Already in ascending order
734
735 return std::nullopt;
736}
737
738
740{
741 if( auto smallest = GetSmallestLogicalNumber() )
742 return *smallest;
743
744 return GetShownNumber();
745}
746
747
748wxString SCH_PIN::GetEffectivePadNumber( const SCH_SHEET_PATH& aSheet, const wxString& aVariantName,
749 const LIB_ID& aFootprintLibId, const std::set<wxString>* aFootprintPadNumbers,
750 PAD_RESOLUTION* aState ) const
751{
752 const wxString& pinNumber = GetNumber();
753 const PIN_MAP* map = nullptr;
754
755 if( const SCH_SYMBOL* symbol = dynamic_cast<const SCH_SYMBOL*>( GetParentSymbol() ) )
756 {
757 PIN_MAP_INSTANCE_OVERRIDE ovr = symbol->GetPinMapOverride( &aSheet, aVariantName );
758
759 const LIB_SYMBOL* lib = symbol->GetLibSymbolRef().get();
760
763
764 // Library default, or a named map that no longer exists, resolves through the footprint.
765 if( !map && ovr.m_Mode != PIN_MAP_OVERRIDE_MODE::FORCE_IDENTITY && lib )
766 {
767 for( const ASSOCIATED_FOOTPRINT& assoc : lib->GetEffectiveAssociatedFootprints() )
768 {
769 if( assoc.m_FootprintLibId == aFootprintLibId )
770 {
771 map = lib->GetEffectivePinMaps().FindByName( assoc.m_MapName );
772 break;
773 }
774 }
775 }
776
777 // Instance-local sparse edits patch the resolved map, but are ignored under forced
778 // identity per the PIN_MAP_INSTANCE_OVERRIDE contract.
780 {
781 for( const PIN_MAP_ENTRY& edit : ovr.m_Edits )
782 {
783 if( edit.m_PinNumber == pinNumber )
784 {
785 if( aState )
786 *aState = PAD_RESOLUTION::MAPPED;
787
788 return edit.m_PadNumber;
789 }
790 }
791 }
792 }
793
794 // 1. MAPPED - an explicit entry wins and needs no footprint.
795 if( map && map->HasEntry( pinNumber ) )
796 {
797 if( aState )
798 *aState = PAD_RESOLUTION::MAPPED;
799
800 return map->GetPadNumber( pinNumber );
801 }
802
803 if( aFootprintPadNumbers && HasIdentityPad( pinNumber, *aFootprintPadNumbers ) )
804 {
805 if( aState )
806 *aState = PAD_RESOLUTION::IDENTITY;
807
808 return pinNumber;
809 }
810
811 // 3. UNMAPPED, or assumed identity when no footprint is available (the painter path).
812 if( aState )
813 *aState = aFootprintPadNumbers ? PAD_RESOLUTION::UNMAPPED : PAD_RESOLUTION::IDENTITY;
814
815 return aFootprintPadNumbers ? wxString() : pinNumber;
816}
817
818
819bool SCH_PIN::HasIdentityPad( const wxString& aPinNumber, const std::set<wxString>& aPads )
820{
821 if( aPads.contains( aPinNumber ) )
822 return true;
823
824 bool valid = false;
825 const auto numbers = ExpandStackedPinNotation( aPinNumber, &valid );
826 return valid && std::any_of( numbers.begin(), numbers.end(),
827 [&]( const wxString& number ) { return aPads.contains( number ); } );
828}
829
830
831wxString SCH_PIN::GetEffectivePadNumber( const SCH_SHEET_PATH& aSheet, const wxString& aVariantName ) const
832{
833 LIB_ID footprintLibId;
834
835 if( const SCH_SYMBOL* symbol = dynamic_cast<const SCH_SYMBOL*>( GetParentSymbol() ) )
836 footprintLibId.Parse( symbol->GetFootprintFieldText( &aSheet, RESOLVED, aVariantName ) );
837
838 return GetEffectivePadNumber( aSheet, aVariantName, footprintLibId, nullptr );
839}
840
841
842void SCH_PIN::SetNumber( const wxString& aNumber )
843{
844 if( m_number == aNumber )
845 return;
846
847 m_number = aNumber;
848 // pin number string does not support spaces
849 m_number.Replace( wxT( " " ), wxT( "_" ) );
850
851 if( m_layoutCache )
853}
854
855
857{
858 if( !m_nameTextSize.has_value() )
859 {
860 if( !m_libPin )
861 return schIUScale.MilsToIU( DEFAULT_PINNAME_SIZE );
862
863 return m_libPin->GetNameTextSize();
864 }
865
866 return m_nameTextSize.value();
867}
868
869
871{
872 if( aSize == m_nameTextSize )
873 return;
874
875 m_nameTextSize = aSize;
876
877 if( m_layoutCache )
879}
880
881
883{
884 if( !m_numTextSize.has_value() )
885 {
886 if( !m_libPin )
887 return schIUScale.MilsToIU( DEFAULT_PINNUM_SIZE );
888
889 return m_libPin->GetNumberTextSize();
890 }
891
892 return m_numTextSize.value();
893}
894
895
897{
898 if( aSize == m_numTextSize )
899 return;
900
901 m_numTextSize = aSize;
902
903 if( m_layoutCache )
905}
906
907
909{
910 if( const SCH_SYMBOL* symbol = dynamic_cast<const SCH_SYMBOL*>( GetParentSymbol() ) )
911 {
912 const TRANSFORM& t = symbol->GetTransform();
913
914 if( !m_libPin )
915 return GetPosition();
916
917 return t.TransformCoordinate( m_libPin->GetPinRoot() ) + symbol->GetPosition();
918 }
919
920 switch( GetOrientation() )
921 {
922 default:
927 }
928}
929
930
931void SCH_PIN::PlotPinType( PLOTTER *aPlotter, const VECTOR2I &aPosition,
932 PIN_ORIENTATION aOrientation, bool aDimmed ) const
933{
934 int MapX1, MapY1, x1, y1;
935 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
936 COLOR4D color = renderSettings->GetLayerColor( LAYER_PIN );
937 COLOR4D bg = renderSettings->GetBackgroundColor();
938 int penWidth = GetEffectivePenWidth( renderSettings );
939 int pinLength = GetLength();
940
941 if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
942 bg = COLOR4D::WHITE;
943
944 if( color.m_text && Schematic() )
945 color = COLOR4D( ResolveText( *color.m_text, &Schematic()->CurrentSheet() ) );
946
947 if( aDimmed )
948 {
949 color.Desaturate( );
950 color = color.Mix( bg, 0.5f );
951 }
952
953 aPlotter->SetColor( color );
954 aPlotter->SetCurrentLineWidth( penWidth );
955
956 MapX1 = MapY1 = 0;
957 x1 = aPosition.x; y1 = aPosition.y;
958
959 switch( aOrientation )
960 {
961 case PIN_ORIENTATION::PIN_UP: y1 = aPosition.y - pinLength; MapY1 = 1; break;
962 case PIN_ORIENTATION::PIN_DOWN: y1 = aPosition.y + pinLength; MapY1 = -1; break;
963 case PIN_ORIENTATION::PIN_LEFT: x1 = aPosition.x - pinLength; MapX1 = 1; break;
964 case PIN_ORIENTATION::PIN_RIGHT: x1 = aPosition.x + pinLength; MapX1 = -1; break;
965 case PIN_ORIENTATION::INHERIT: wxFAIL_MSG( wxS( "aOrientation must be resolved!" ) ); break;
966 }
967
969 {
970 const int radius = externalPinDecoSize( aPlotter->RenderSettings(), *this );
971 aPlotter->Circle( VECTOR2I( MapX1 * radius + x1, MapY1 * radius + y1 ), radius * 2,
972 FILL_T::NO_FILL, penWidth );
973
974 aPlotter->MoveTo( VECTOR2I( MapX1 * radius * 2 + x1, MapY1 * radius * 2 + y1 ) );
975 aPlotter->FinishTo( aPosition );
976 }
978 {
979 const int deco_size = internalPinDecoSize( aPlotter->RenderSettings(), *this );
980 if( MapY1 == 0 ) /* MapX1 = +- 1 */
981 {
982 aPlotter->MoveTo( VECTOR2I( x1, y1 + deco_size ) );
983 aPlotter->LineTo( VECTOR2I( x1 + MapX1 * deco_size * 2, y1 ) );
984 aPlotter->FinishTo( VECTOR2I( x1, y1 - deco_size ) );
985 }
986 else /* MapX1 = 0 */
987 {
988 aPlotter->MoveTo( VECTOR2I( x1 + deco_size, y1 ) );
989 aPlotter->LineTo( VECTOR2I( x1, y1 + MapY1 * deco_size * 2 ) );
990 aPlotter->FinishTo( VECTOR2I( x1 - deco_size, y1 ) );
991 }
992
993 aPlotter->MoveTo( VECTOR2I( MapX1 * deco_size * 2 + x1, MapY1 * deco_size * 2 + y1 ) );
994 aPlotter->FinishTo( aPosition );
995 }
996 else
997 {
998 aPlotter->MoveTo( VECTOR2I( x1, y1 ) );
999 aPlotter->FinishTo( aPosition );
1000 }
1001
1005 {
1006 const int deco_size = internalPinDecoSize( aPlotter->RenderSettings(), *this );
1007
1008 if( MapY1 == 0 ) /* MapX1 = +- 1 */
1009 {
1010 aPlotter->MoveTo( VECTOR2I( x1, y1 + deco_size ) );
1011 aPlotter->LineTo( VECTOR2I( x1 - MapX1 * deco_size * 2, y1 ) );
1012 aPlotter->FinishTo( VECTOR2I( x1, y1 - deco_size ) );
1013 }
1014 else /* MapX1 = 0 */
1015 {
1016 aPlotter->MoveTo( VECTOR2I( x1 + deco_size, y1 ) );
1017 aPlotter->LineTo( VECTOR2I( x1, y1 - MapY1 * deco_size * 2 ) );
1018 aPlotter->FinishTo( VECTOR2I( x1 - deco_size, y1 ) );
1019 }
1020 }
1021
1023 || m_shape == GRAPHIC_PINSHAPE::CLOCK_LOW ) /* IEEE symbol "Active Low Input" */
1024 {
1025 const int deco_size = externalPinDecoSize( aPlotter->RenderSettings(), *this );
1026
1027 if( MapY1 == 0 ) /* MapX1 = +- 1 */
1028 {
1029 aPlotter->MoveTo( VECTOR2I( x1 + MapX1 * deco_size * 2, y1 ) );
1030 aPlotter->LineTo( VECTOR2I( x1 + MapX1 * deco_size * 2, y1 - deco_size * 2 ) );
1031 aPlotter->FinishTo( VECTOR2I( x1, y1 ) );
1032 }
1033 else /* MapX1 = 0 */
1034 {
1035 aPlotter->MoveTo( VECTOR2I( x1, y1 + MapY1 * deco_size * 2 ) );
1036 aPlotter->LineTo( VECTOR2I( x1 - deco_size * 2, y1 + MapY1 * deco_size * 2 ) );
1037 aPlotter->FinishTo( VECTOR2I( x1, y1 ) );
1038 }
1039 }
1040
1041 if( m_shape == GRAPHIC_PINSHAPE::OUTPUT_LOW ) /* IEEE symbol "Active Low Output" */
1042 {
1043 const int symbol_size = externalPinDecoSize( aPlotter->RenderSettings(), *this );
1044
1045 if( MapY1 == 0 ) /* MapX1 = +- 1 */
1046 {
1047 aPlotter->MoveTo( VECTOR2I( x1, y1 - symbol_size * 2 ) );
1048 aPlotter->FinishTo( VECTOR2I( x1 + MapX1 * symbol_size * 2, y1 ) );
1049 }
1050 else /* MapX1 = 0 */
1051 {
1052 aPlotter->MoveTo( VECTOR2I( x1 - symbol_size * 2, y1 ) );
1053 aPlotter->FinishTo( VECTOR2I( x1, y1 + MapY1 * symbol_size * 2 ) );
1054 }
1055 }
1056 else if( m_shape == GRAPHIC_PINSHAPE::NONLOGIC ) /* NonLogic pin symbol */
1057 {
1058 const int deco_size = externalPinDecoSize( aPlotter->RenderSettings(), *this );
1059 aPlotter->MoveTo( VECTOR2I( x1 - ( MapX1 + MapY1 ) * deco_size,
1060 y1 - ( MapY1 - MapX1 ) * deco_size ) );
1061 aPlotter->FinishTo( VECTOR2I( x1 + ( MapX1 + MapY1 ) * deco_size,
1062 y1 + ( MapY1 - MapX1 ) * deco_size ) );
1063 aPlotter->MoveTo( VECTOR2I( x1 - ( MapX1 - MapY1 ) * deco_size,
1064 y1 - ( MapY1 + MapX1 ) * deco_size ) );
1065 aPlotter->FinishTo( VECTOR2I( x1 + ( MapX1 - MapY1 ) * deco_size,
1066 y1 + ( MapY1 + MapX1 ) * deco_size ) );
1067 }
1068
1069 if( GetType() == ELECTRICAL_PINTYPE::PT_NC ) // Draw a N.C. symbol
1070 {
1071 const int deco_size = TARGET_PIN_RADIUS;
1072 const int ex1 = aPosition.x;
1073 const int ey1 = aPosition.y;
1074 aPlotter->MoveTo( VECTOR2I( ex1 - deco_size, ey1 - deco_size ) );
1075 aPlotter->FinishTo( VECTOR2I( ex1 + deco_size, ey1 + deco_size ) );
1076 aPlotter->MoveTo( VECTOR2I( ex1 + deco_size, ey1 - deco_size ) );
1077 aPlotter->FinishTo( VECTOR2I( ex1 - deco_size, ey1 + deco_size ) );
1078 }
1079}
1080
1081
1082void SCH_PIN::PlotPinTexts( PLOTTER *aPlotter, const VECTOR2I &aPinPos, PIN_ORIENTATION aPinOrient,
1083 int aTextInside, bool aDrawPinNum, bool aDrawPinName, bool aDimmed ) const
1084{
1085 RENDER_SETTINGS* settings = aPlotter->RenderSettings();
1086 KIFONT::FONT* font = KIFONT::FONT::GetFont( settings->GetDefaultFont(), false, false );
1087 wxString name = GetShownName();
1088 wxString number = GetShownNumber();
1089
1090 // Apply stacked pin display formatting (reuse helper from pin_layout_cache)
1091 if( aDrawPinNum && !number.IsEmpty() )
1092 {
1093 const KIFONT::METRICS& metrics = GetFontMetrics();
1094 number = FormatStackedPinForDisplay( number, GetLength(), GetNumberTextSize(), font, metrics );
1095 }
1096
1097 if( name.IsEmpty() || m_nameTextSize == 0 )
1098 aDrawPinName = false;
1099
1100 if( number.IsEmpty() || m_numTextSize == 0 )
1101 aDrawPinNum = false;
1102
1103 if( !aDrawPinNum && !aDrawPinName )
1104 return;
1105
1106 int namePenWidth = settings->GetDefaultPenWidth();
1107 int numPenWidth = settings->GetDefaultPenWidth();
1108
1109 // Include the painter's clearance (PIN_LAYOUT_CACHE::getPinTextOffset()) so plotted pin text
1110 // sits where it's drawn on screen, not a few mils closer to the pin.
1111 int pinTextOffset = schIUScale.MilsToIU( KiROUND( 24 * getRenderSettings( aPlotter )->m_TextOffsetRatio ) );
1112 int name_offset = pinTextOffset + schIUScale.MilsToIU( PIN_TEXT_MARGIN ) + namePenWidth;
1113 int num_offset = pinTextOffset + schIUScale.MilsToIU( PIN_TEXT_MARGIN ) + numPenWidth;
1114
1115 COLOR4D nameColor = settings->GetLayerColor( LAYER_PINNAM );
1116 COLOR4D numColor = settings->GetLayerColor( LAYER_PINNUM );
1117 COLOR4D bg = settings->GetBackgroundColor();
1118
1119 if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
1120 bg = COLOR4D::WHITE;
1121
1122 if( nameColor.m_text && Schematic() )
1123 nameColor = COLOR4D( ResolveText( *nameColor.m_text, &Schematic()->CurrentSheet() ) );
1124
1125 if( numColor.m_text && Schematic() )
1126 numColor = COLOR4D( ResolveText( *numColor.m_text, &Schematic()->CurrentSheet() ) );
1127
1128 if( aDimmed )
1129 {
1130 nameColor.Desaturate();
1131 numColor.Desaturate();
1132 nameColor = nameColor.Mix( bg, 0.5f );
1133 numColor = numColor.Mix( bg, 0.5f );
1134 }
1135
1136 int x1 = aPinPos.x;
1137 int y1 = aPinPos.y;
1138
1139 switch( aPinOrient )
1140 {
1141 case PIN_ORIENTATION::PIN_UP: y1 -= GetLength(); break;
1142 case PIN_ORIENTATION::PIN_DOWN: y1 += GetLength(); break;
1143 case PIN_ORIENTATION::PIN_LEFT: x1 -= GetLength(); break;
1144 case PIN_ORIENTATION::PIN_RIGHT: x1 += GetLength(); break;
1145 default: break;
1146 }
1147
1148 // Keep a multi-line stacked block on the authored side of a mirrored symbol (issue 24894)
1149 const bool flipStacked =
1150 number.Contains( wxT( "\n" ) ) && StackedTextSideFlipped( getRenderSettings( aPlotter )->m_Transform );
1151
1152 auto plotSimpleText =
1153 [&]( int x, int y, const EDA_ANGLE& angle, GR_TEXT_H_ALIGN_T hJustify, GR_TEXT_V_ALIGN_T vJustify,
1154 const wxString& txt, int size, int penWidth, const COLOR4D& col )
1155 {
1156 TEXT_ATTRIBUTES attrs;
1157 attrs.m_StrokeWidth = penWidth;
1158 attrs.m_Angle = angle;
1159 attrs.m_Size = VECTOR2I( size, size );
1160 attrs.m_Halign = hJustify;
1161 attrs.m_Valign = vJustify;
1162 attrs.m_Multiline = false; // we'll manage multi-line manually
1163 aPlotter->PlotText( VECTOR2I( x, y ), col, txt, attrs, font, GetFontMetrics() );
1164 };
1165
1166 auto plotMultiLineWithBraces =
1167 [&]( int anchorX, int anchorY, EDA_ANGLE angle, GR_TEXT_V_ALIGN_T vAlign, bool aAllowFlip )
1168 {
1169 // If not multi-line formatted, just plot single line centered.
1170 if( !number.StartsWith( "[" ) || !number.EndsWith( "]" ) || !number.Contains( "\n" ) )
1171 {
1172 plotSimpleText( anchorX, anchorY, angle, GR_TEXT_H_ALIGN_CENTER, vAlign, number, GetNumberTextSize(),
1173 numPenWidth, numColor );
1174 return;
1175 }
1176
1177 wxString content = number.Mid( 1, number.Length() - 2 );
1178 wxArrayString lines;
1179 wxStringSplit( content, lines, '\n' );
1180
1181 if( lines.size() <= 1 )
1182 {
1183 plotSimpleText( anchorX, anchorY, angle, GR_TEXT_H_ALIGN_CENTER, vAlign, content, GetNumberTextSize(),
1184 numPenWidth, numColor );
1185 return;
1186 }
1187
1188 const int textSize = GetNumberTextSize();
1189 const int lineSpacing = KiROUND( textSize * 1.3 );
1190 const int numLines = (int) lines.size();
1191 const bool verticalText = ( angle == ANGLE_VERTICAL );
1192 const KIFONT::METRICS& metrics = GetFontMetrics();
1193
1194 if( aAllowFlip && flipStacked )
1195 {
1196 // Reflect the anchor about the pin line
1197 if( verticalText )
1198 anchorX = 2 * aPinPos.x - anchorX;
1199 else
1200 anchorY = 2 * aPinPos.y - anchorY;
1201
1202 if( vAlign == GR_TEXT_V_ALIGN_BOTTOM )
1203 vAlign = GR_TEXT_V_ALIGN_TOP;
1204 else if( vAlign == GR_TEXT_V_ALIGN_TOP )
1205 vAlign = GR_TEXT_V_ALIGN_BOTTOM;
1206 }
1207
1208 // Centre each line and align the stacked block's edge to the anchor, matching the
1209 // on-screen painter (PIN_LAYOUT_CACHE) so stacked numbers plot where they're drawn.
1210 int firstLineCentre;
1211
1212 switch( vAlign )
1213 {
1214 case GR_TEXT_V_ALIGN_BOTTOM: firstLineCentre = -( 2 * numLines - 1 ) * lineSpacing / 2; break;
1215 case GR_TEXT_V_ALIGN_TOP: firstLineCentre = lineSpacing / 2; break;
1216 default: // GR_TEXT_V_ALIGN_CENTER
1217 firstLineCentre = -( numLines - 1 ) * lineSpacing / 2;
1218 break;
1219 }
1220
1221 firstLineCentre += verticalText ? anchorX : anchorY;
1222
1223 // Plot each line centred; track the widest for brace spacing.
1224 int maxLineWidth = 0;
1225
1226 for( int i = 0; i < numLines; ++i )
1227 {
1228 wxString l = lines[i];
1229 l.Trim( true ).Trim( false );
1230
1231 VECTOR2I ext = font->StringBoundaryLimits( l, VECTOR2D( textSize, textSize ),
1232 GetPenSizeForNormal( textSize ), false, false, metrics );
1233 maxLineWidth = std::max( maxLineWidth, ext.x );
1234
1235 int stack = firstLineCentre + i * lineSpacing;
1236 int lx = verticalText ? stack : anchorX;
1237 int ly = verticalText ? anchorY : stack;
1238 plotSimpleText( lx, ly, angle, GR_TEXT_H_ALIGN_CENTER, GR_TEXT_V_ALIGN_CENTER, l, textSize, numPenWidth,
1239 numColor );
1240 }
1241
1242 // Now draw braces emulating SCH_PAINTER brace geometry
1243 auto plotBrace = [&]( const VECTOR2I& top, const VECTOR2I& bottom, bool leftOrTop, bool isVerticalText )
1244 {
1245 // Build 4 small segments approximating curly brace
1246 VECTOR2I mid = ( top + bottom ) / 2;
1247 int braceWidth = textSize / 3; // same scale as painter
1248 VECTOR2I p1 = top;
1249 VECTOR2I p5 = bottom;
1250 VECTOR2I p2 = top;
1251 VECTOR2I p3 = mid;
1252 VECTOR2I p4 = bottom;
1253 int offset = leftOrTop ? -braceWidth : braceWidth;
1254
1255 if( isVerticalText )
1256 {
1257 // Text vertical => brace extends in Y (horizontal brace lines across X axis set)
1258 // For vertical orientation we offset Y for p2/p3/p4
1259 p2.y += offset / 2;
1260 p3.y += offset;
1261 p4.y += offset / 2;
1262 }
1263 else
1264 {
1265 // Horizontal text => brace extends in X
1266 p2.x += offset / 2;
1267 p3.x += offset;
1268 p4.x += offset / 2;
1269 }
1270
1271 aPlotter->MoveTo( p1 );
1272 aPlotter->FinishTo( p2 );
1273 aPlotter->MoveTo( p2 );
1274 aPlotter->FinishTo( p3 );
1275 aPlotter->MoveTo( p3 );
1276 aPlotter->FinishTo( p4 );
1277 aPlotter->MoveTo( p4 );
1278 aPlotter->FinishTo( p5 );
1279 };
1280
1281 aPlotter->SetCurrentLineWidth( numPenWidth );
1282
1283 const int braceWidth = textSize / 3;
1284 const int extraHeight = textSize / 3; // extend beyond text block
1285 const int braceSpacing = maxLineWidth / 2 + braceWidth;
1286 const int blockSpan = ( numLines - 1 ) * lineSpacing;
1287
1288 if( verticalText )
1289 {
1290 VECTOR2I braceStart( firstLineCentre - 2 * extraHeight, anchorY );
1291 VECTOR2I braceEnd( firstLineCentre + blockSpan, anchorY );
1292
1293 VECTOR2I topStart = braceStart;
1294 topStart.y -= braceSpacing;
1295 VECTOR2I topEnd = braceEnd;
1296 topEnd.y -= braceSpacing;
1297 VECTOR2I bottomStart = braceStart;
1298 bottomStart.y += braceSpacing;
1299 VECTOR2I bottomEnd = braceEnd;
1300 bottomEnd.y += braceSpacing;
1301
1302 plotBrace( topStart, topEnd, true, true ); // leftOrTop=true
1303 plotBrace( bottomStart, bottomEnd, false, true );
1304 }
1305 else
1306 {
1307 VECTOR2I braceStart( anchorX, firstLineCentre - 2 * extraHeight );
1308 VECTOR2I braceEnd( anchorX, firstLineCentre + blockSpan );
1309
1310 VECTOR2I leftTop = braceStart;
1311 leftTop.x -= braceSpacing;
1312 VECTOR2I leftBot = braceEnd;
1313 leftBot.x -= braceSpacing;
1314 VECTOR2I rightTop = braceStart;
1315 rightTop.x += braceSpacing;
1316 VECTOR2I rightBot = braceEnd;
1317 rightBot.x += braceSpacing;
1318
1319 plotBrace( leftTop, leftBot, true, false );
1320 plotBrace( rightTop, rightBot, false, false );
1321 }
1322 };
1323
1324 // Logic largely mirrors original single-line placement but calls multi-line path for numbers
1325 if( aTextInside )
1326 {
1327 if( ( aPinOrient == PIN_ORIENTATION::PIN_LEFT ) || ( aPinOrient == PIN_ORIENTATION::PIN_RIGHT ) )
1328 {
1329 if( aDrawPinName )
1330 {
1331 if( aPinOrient == PIN_ORIENTATION::PIN_RIGHT )
1332 {
1333 plotSimpleText( x1 + aTextInside, y1, ANGLE_HORIZONTAL, GR_TEXT_H_ALIGN_LEFT,
1334 GR_TEXT_V_ALIGN_CENTER, name, GetNameTextSize(), namePenWidth, nameColor );
1335 }
1336 else
1337 {
1338 plotSimpleText( x1 - aTextInside, y1, ANGLE_HORIZONTAL, GR_TEXT_H_ALIGN_RIGHT,
1339 GR_TEXT_V_ALIGN_CENTER, name, GetNameTextSize(), namePenWidth, nameColor );
1340 }
1341 }
1342
1343 if( aDrawPinNum )
1344 {
1345 plotMultiLineWithBraces( ( x1 + aPinPos.x ) / 2, y1 - num_offset, ANGLE_HORIZONTAL,
1346 GR_TEXT_V_ALIGN_BOTTOM, true );
1347 }
1348 }
1349 else
1350 {
1351 if( aPinOrient == PIN_ORIENTATION::PIN_DOWN )
1352 {
1353 if( aDrawPinName )
1354 {
1355 plotSimpleText( x1, y1 + aTextInside, ANGLE_VERTICAL, GR_TEXT_H_ALIGN_RIGHT,
1356 GR_TEXT_V_ALIGN_CENTER, name, GetNameTextSize(), namePenWidth, nameColor );
1357 }
1358
1359 if( aDrawPinNum )
1360 {
1361 plotMultiLineWithBraces( x1 - num_offset, ( y1 + aPinPos.y ) / 2, ANGLE_VERTICAL,
1362 GR_TEXT_V_ALIGN_BOTTOM, true );
1363 }
1364 }
1365 else // PIN_UP
1366 {
1367 if( aDrawPinName )
1368 {
1369 plotSimpleText( x1, y1 - aTextInside, ANGLE_VERTICAL, GR_TEXT_H_ALIGN_LEFT,
1370 GR_TEXT_V_ALIGN_CENTER, name, GetNameTextSize(), namePenWidth, nameColor );
1371 }
1372
1373 if( aDrawPinNum )
1374 {
1375 plotMultiLineWithBraces( x1 - num_offset, ( y1 + aPinPos.y ) / 2, ANGLE_VERTICAL,
1376 GR_TEXT_V_ALIGN_BOTTOM, true );
1377 }
1378 }
1379 }
1380 }
1381 else
1382 {
1383 if( ( aPinOrient == PIN_ORIENTATION::PIN_LEFT ) || ( aPinOrient == PIN_ORIENTATION::PIN_RIGHT ) )
1384 {
1385 if( aDrawPinName && aDrawPinNum )
1386 {
1387 plotSimpleText( ( x1 + aPinPos.x ) / 2, y1 - name_offset, ANGLE_HORIZONTAL,
1389 GetNameTextSize(), namePenWidth, nameColor );
1390 plotMultiLineWithBraces( ( x1 + aPinPos.x ) / 2, y1 + num_offset, ANGLE_HORIZONTAL, GR_TEXT_V_ALIGN_TOP,
1391 false );
1392 }
1393 else if( aDrawPinName )
1394 {
1395 plotSimpleText( ( x1 + aPinPos.x ) / 2, y1 - name_offset, ANGLE_HORIZONTAL,
1397 GetNameTextSize(), namePenWidth, nameColor );
1398 }
1399 else if( aDrawPinNum )
1400 {
1401 plotMultiLineWithBraces( ( x1 + aPinPos.x ) / 2, y1 - name_offset, ANGLE_HORIZONTAL,
1402 GR_TEXT_V_ALIGN_BOTTOM, true );
1403 }
1404 }
1405 else
1406 {
1407 if( aDrawPinName && aDrawPinNum )
1408 {
1409 plotSimpleText( x1 - name_offset, ( y1 + aPinPos.y ) / 2, ANGLE_VERTICAL,
1411 GetNameTextSize(), namePenWidth, nameColor );
1412 plotMultiLineWithBraces( x1 + num_offset, ( y1 + aPinPos.y ) / 2, ANGLE_VERTICAL, GR_TEXT_V_ALIGN_TOP,
1413 false );
1414 }
1415 else if( aDrawPinName )
1416 {
1417 plotSimpleText( x1 - name_offset, ( y1 + aPinPos.y ) / 2, ANGLE_VERTICAL,
1419 GetNameTextSize(), namePenWidth, nameColor );
1420 }
1421 else if( aDrawPinNum )
1422 {
1423 plotMultiLineWithBraces( x1 - num_offset, ( y1 + aPinPos.y ) / 2, ANGLE_VERTICAL,
1424 GR_TEXT_V_ALIGN_BOTTOM, true );
1425 }
1426 }
1427 }
1428}
1429
1430
1432{
1433 PIN_ORIENTATION orient;
1434 VECTOR2I end; // position of pin end starting at 0,0 according to its orientation, length = 1
1435
1436 switch( GetOrientation() )
1437 {
1438 default:
1439 case PIN_ORIENTATION::PIN_RIGHT: end.x = 1; break;
1440 case PIN_ORIENTATION::PIN_UP: end.y = -1; break;
1441 case PIN_ORIENTATION::PIN_DOWN: end.y = 1; break;
1442 case PIN_ORIENTATION::PIN_LEFT: end.x = -1; break;
1443 }
1444
1445 // = pos of end point, according to the symbol orientation.
1446 end = aTransform.TransformCoordinate( end );
1447 orient = PIN_ORIENTATION::PIN_UP;
1448
1449 if( end.x == 0 )
1450 {
1451 if( end.y > 0 )
1453 }
1454 else
1455 {
1457
1458 if( end.x < 0 )
1460 }
1461
1462 return orient;
1463}
1464
1465
1466bool SCH_PIN::StackedTextSideFlipped( const TRANSFORM& aTransform ) const
1467{
1468 // Side the number block is drawn on (above horizontal pins, left of vertical pins)
1469 auto ruleSide = []( PIN_ORIENTATION aOrient ) -> VECTOR2I
1470 {
1471 if( aOrient == PIN_ORIENTATION::PIN_UP || aOrient == PIN_ORIENTATION::PIN_DOWN )
1472 return VECTOR2I( -1, 0 );
1473
1474 return VECTOR2I( 0, -1 );
1475 };
1476
1477 VECTOR2I mapped = aTransform.TransformCoordinate( ruleSide( GetOrientation() ) );
1478
1479 return mapped == -ruleSide( PinDrawOrient( aTransform ) );
1480}
1481
1482
1484{
1485 //return new SCH_PIN( *this );
1486 SCH_ITEM* newPin = new SCH_PIN( *this );
1487 wxASSERT( newPin->GetUnit() == m_unit && newPin->GetBodyStyle() == m_bodyStyle );
1488 return newPin;
1489}
1490
1491
1492void SCH_PIN::ChangeLength( int aLength )
1493{
1494 int lengthChange = GetLength() - aLength;
1495 int offsetX = 0;
1496 int offsetY = 0;
1497
1498 switch( GetOrientation() )
1499 {
1500 default:
1502 offsetX = lengthChange;
1503 break;
1505 offsetX = -1 * lengthChange;
1506 break;
1508 offsetY = -1 * lengthChange;
1509 break;
1511 offsetY = lengthChange;
1512 break;
1513 }
1514
1515 m_position += VECTOR2I( offsetX, offsetY );
1516 m_length = aLength;
1517}
1518
1519
1520void SCH_PIN::Move( const VECTOR2I& aOffset )
1521{
1522 m_position += aOffset;
1523}
1524
1525
1527{
1528 m_position.x -= aCenter;
1529 m_position.x *= -1;
1530 m_position.x += aCenter;
1531
1536}
1537
1538
1540{
1541 if( dynamic_cast<LIB_SYMBOL*>( GetParentSymbol() ) )
1542 MirrorHorizontallyPin( aCenter );
1543}
1544
1545
1547{
1548 m_position.y -= aCenter;
1549 m_position.y *= -1;
1550 m_position.y += aCenter;
1551
1556}
1557
1558
1559void SCH_PIN::MirrorVertically( int aCenter )
1560{
1561 if( dynamic_cast<LIB_SYMBOL*>( GetParentSymbol() ) )
1562 MirrorVerticallyPin( aCenter );
1563}
1564
1565
1566void SCH_PIN::RotatePin( const VECTOR2I& aCenter, bool aRotateCCW )
1567{
1568 if( aRotateCCW )
1569 {
1570 RotatePoint( m_position, aCenter, ANGLE_90 );
1571
1572 switch( GetOrientation() )
1573 {
1574 default:
1579 }
1580 }
1581 else
1582 {
1583 RotatePoint( m_position, aCenter, -ANGLE_90 );
1584
1585 switch( GetOrientation() )
1586 {
1587 default:
1592 }
1593 }
1594}
1595
1596
1597void SCH_PIN::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
1598{
1599 if( dynamic_cast<LIB_SYMBOL*>( GetParentSymbol() ) )
1600 RotatePin( aCenter, aRotateCCW );
1601}
1602
1603
1604void SCH_PIN::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
1605 int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
1606{
1607 if( aBackground )
1608 return;
1609
1610 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
1611
1612 if( !IsVisible() && !renderSettings->m_ShowHiddenPins )
1613 return;
1614
1615 const SYMBOL* part = GetParentSymbol();
1616 PIN_ORIENTATION orient = PinDrawOrient( renderSettings->m_Transform );
1617 VECTOR2I pos = renderSettings->TransformCoordinate( m_position ) + aOffset;
1618
1619 PlotPinType( aPlotter, pos, orient, aDimmed );
1620 PlotPinTexts( aPlotter, pos, orient, part->GetPinNameOffset(), part->GetShowPinNumbers(),
1621 part->GetShowPinNames(), aDimmed );
1622}
1623
1624
1625void SCH_PIN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1626{
1627 SYMBOL* symbol = GetParentSymbol();
1628
1629 aList.emplace_back( _( "Type" ), _( "Pin" ) );
1630
1631 SCH_ITEM::GetMsgPanelInfo( aFrame, aList );
1632
1633 aList.emplace_back( _( "Name" ), UnescapeString( GetShownName() ) );
1634 aList.emplace_back( _( "Number" ), GetShownNumber() );
1635 aList.emplace_back( _( "Type" ), ElectricalPinTypeGetText( GetType() ) );
1636 aList.emplace_back( _( "Style" ), PinShapeGetText( GetShape() ) );
1637
1638 aList.emplace_back( _( "Visible" ), IsVisible() ? _( "Yes" ) : _( "No" ) );
1639
1640 // Display pin length
1641 aList.emplace_back( _( "Length" ), aFrame->MessageTextFromValue( GetLength(), true ) );
1642
1643 aList.emplace_back( _( "Orientation" ), PinOrientationName( GetOrientation() ) );
1644
1645 if( dynamic_cast<LIB_SYMBOL*>( symbol ) )
1646 {
1647 aList.emplace_back( _( "Pos X" ), aFrame->MessageTextFromValue( GetPosition().x, true ) );
1648 aList.emplace_back( _( "Pos Y" ), aFrame->MessageTextFromValue( GetPosition().y, true ) );
1649 }
1650 else if( SCH_SYMBOL* schsymbol = dynamic_cast<SCH_SYMBOL*>( symbol ) )
1651 {
1652 SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( aFrame );
1653 SCH_SHEET_PATH* currentSheet = schframe ? &schframe->GetCurrentSheet() : nullptr;
1654
1655 // Don't use GetShownText(); we want to see the variable references here
1656 aList.emplace_back( symbol->GetRef( currentSheet ),
1657 UnescapeString( schsymbol->GetField( FIELD_T::VALUE )->GetText() ) );
1658 }
1659
1660#if defined(DEBUG)
1661 if( !IsConnectivityDirty() && dynamic_cast<SCH_EDIT_FRAME*>( aFrame ) )
1662 {
1663 SCH_CONNECTION* conn = Connection();
1664
1665 if( conn )
1666 conn->AppendInfoToMsgPanel( aList );
1667 }
1668#endif
1669}
1670
1671
1673{
1674 std::lock_guard<std::recursive_mutex> lock( m_netmap_mutex );
1675
1676 if( aPath )
1677 m_net_name_map.erase( *aPath );
1678 else
1679 m_net_name_map.clear();
1680}
1681
1682
1683wxString SCH_PIN::GetDefaultNetName( const SCH_SHEET_PATH& aPath, bool aForceNoConnect )
1684{
1685 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( GetParentSymbol() );
1686
1687 // Need to check for parent as power symbol to make sure we aren't dealing
1688 // with legacy global power pins on non-power symbols
1689 if( IsGlobalPower() || IsLocalPower() )
1690 {
1691 SYMBOL* parent = GetLibPin() ? GetLibPin()->GetParentSymbol() : nullptr;
1692
1693 if( parent && ( parent->IsGlobalPower() || parent->IsLocalPower() ) )
1694 {
1695 return EscapeString( symbol->GetValue( &aPath, FOR_NETNAME ), CTX_NETNAME );
1696 }
1697 else
1698 {
1699 wxString tmp = m_libPin ? m_libPin->GetName() : wxString( "??" );
1700
1701 return EscapeString( tmp, CTX_NETNAME );
1702 }
1703 }
1704
1705 std::lock_guard<std::recursive_mutex> lock( m_netmap_mutex );
1706
1707 auto it = m_net_name_map.find( aPath );
1708
1709 if( it != m_net_name_map.end() )
1710 {
1711 if( it->second.second == aForceNoConnect )
1712 return it->second.first;
1713 }
1714
1716 fact.name = m_libPin ? m_libPin->GetShownName() : wxString( "??" );
1717 fact.shownNumber = m_libPin ? m_libPin->GetShownNumber() : wxString( "??" );
1718 fact.number = m_libPin ? m_libPin->GetNumber() : wxString( "??" );
1719 fact.padNumber = m_libPin ? m_libPin->GetSmallestStackedPadNumber() : fact.shownNumber;
1721
1722 if( !aForceNoConnect && !fact.noConnect )
1723 {
1724 for( const SCH_PIN* pin : symbol->GetPins( &aPath ) )
1725 {
1726 if( pin->GetShownName() == GetShownName()
1727 && pin->GetShownNumber() != GetShownNumber()
1728 && pin->GetType() != ELECTRICAL_PINTYPE::PT_NC )
1729 {
1730 fact.hasDuplicateName = true;
1731 break;
1732 }
1733 }
1734 }
1735
1736 if( fact.padNumber != fact.shownNumber )
1737 {
1738 wxLogTrace( traceStackedPins,
1739 wxString::Format( "GetDefaultNetName: stacked pin shown='%s' -> using smallest logical='%s'",
1740 fact.shownNumber, fact.padNumber ) );
1741 }
1742
1744 symbol->GetRef( &aPath, false ), symbol->GetRef( &aPath, true ), symbol->m_Uuid.AsString()
1745 };
1746 const wxString name = SCH_CONNECTIVITY::RenderPinNetName( fact, reference, aForceNoConnect );
1747
1748 if( !reference.reference.IsEmpty() && reference.reference.Last() != '?' )
1749 m_net_name_map[ aPath ] = std::make_pair( name, aForceNoConnect );
1750
1751 return name;
1752}
1753
1754
1756{
1757 return GetBoundingBox( false, true, m_flags & SHOW_ELEC_TYPE );
1758}
1759
1760
1766
1767
1768void SCH_PIN::validateExtentsCache( KIFONT::FONT* aFont, int aSize, const wxString& aText,
1769 EXTENTS_CACHE* aCache ) const
1770{
1771 if( aCache->m_Font == aFont
1772 && aCache->m_FontSize == aSize
1773 && aCache->m_Extents != VECTOR2I() )
1774 {
1775 return;
1776 }
1777
1778 aCache->m_Font = aFont;
1779 aCache->m_FontSize = aSize;
1780
1781 VECTOR2D fontSize( aSize, aSize );
1782 int penWidth = GetPenSizeForNormal( aSize );
1783
1784 aCache->m_Extents = aFont->StringBoundaryLimits( aText, fontSize, penWidth, false, false,
1785 GetFontMetrics() );
1786}
1787
1788
1789BOX2I SCH_PIN::GetBoundingBox( bool aIncludeLabelsOnInvisiblePins, bool aIncludeNameAndNumber,
1790 bool aIncludeElectricalType ) const
1791{
1792 // Just defer to the cache
1793 return GetLayoutCache().GetPinBoundingBox( aIncludeLabelsOnInvisiblePins,
1794 aIncludeNameAndNumber,
1795 aIncludeElectricalType );
1796}
1797
1798
1800{
1801 if( !m_layoutCache )
1802 m_layoutCache = std::make_unique<PIN_LAYOUT_CACHE>( *this );
1803
1804 return *m_layoutCache;
1805}
1806
1807
1809 const SCH_SHEET_PATH* aInstance ) const
1810{
1811 // Do not compare to ourself.
1812 if( aItem == this )
1813 return false;
1814
1815 const SCH_PIN* pin = dynamic_cast<const SCH_PIN*>( aItem );
1816
1817 // Don't compare against a different SCH_ITEM.
1818 wxCHECK( pin, false );
1819
1820 if( GetPosition() != pin->GetPosition() )
1821 return true;
1822
1823 if( GetNumber() != pin->GetNumber() )
1824 return true;
1825
1826 if( GetName() != pin->GetName() )
1827 return true;
1828
1829 // For power input pins, visibility changes affect IsGlobalPower() which changes
1830 // connectivity semantics. Hidden power pins create implicit global net connections.
1831 // Also check if a pin changed type to/from PT_POWER_IN.
1833 {
1834 if( IsVisible() != pin->IsVisible() || GetType() != pin->GetType() )
1835 return true;
1836 }
1837
1838 // Similarly, changing to/from PT_NC affects whether or not the pin participates
1839 // in the connectivity graph.
1841 {
1842 if( GetType() != pin->GetType() )
1843 return true;
1844 }
1845
1846 return false;
1847}
1848
1849
1851{
1853}
1854
1855
1857{
1858 if( const SYMBOL* parentSymbol = GetParentSymbol() )
1859 {
1860 if( parentSymbol->IsLocked() )
1861 return true;
1862 }
1863
1864 return SCH_ITEM::IsLocked();
1865}
1866
1867
1869{
1870 if( m_libPin )
1871 return m_libPin->GetMenuImage();
1872
1874}
1875
1876
1877wxString SCH_PIN::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, ALT* aAlt ) const
1878{
1879 return getItemDescription( aAlt );
1880}
1881
1882
1883wxString SCH_PIN::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1884{
1885 if( m_libPin )
1886 {
1887 SCH_PIN::ALT localStorage;
1888 SCH_PIN::ALT* alt = nullptr;
1889
1890 if( !m_alt.IsEmpty() )
1891 {
1892 localStorage = m_libPin->GetAlt( m_alt );
1893 alt = &localStorage;
1894 }
1895
1896 wxString itemDesc = m_libPin ? m_libPin->GetItemDescription( aUnitsProvider, alt )
1897 : wxString( wxS( "Undefined library pin." ) );
1898
1899 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( GetParentSymbol() );
1900
1901 return wxString::Format( "Symbol %s %s",
1903 itemDesc );
1904 }
1905
1906 return getItemDescription( nullptr );
1907}
1908
1909
1910wxString SCH_PIN::getItemDescription( ALT* aAlt ) const
1911{
1912 wxString name = UnescapeString( aAlt ? aAlt->m_Name : GetShownName() );
1913 wxString electricalTypeName = ElectricalPinTypeGetText( aAlt ? aAlt->m_Type : m_type );
1914 wxString pinShapeName = PinShapeGetText( aAlt ? aAlt->m_Shape : m_shape );
1915
1916 if( IsVisible() )
1917 {
1918 if ( !name.IsEmpty() )
1919 {
1920 return wxString::Format( _( "Pin %s [%s, %s, %s]" ),
1922 name,
1923 electricalTypeName,
1924 pinShapeName );
1925 }
1926 else
1927 {
1928 return wxString::Format( _( "Pin %s [%s, %s]" ),
1930 electricalTypeName,
1931 pinShapeName );
1932 }
1933 }
1934 else
1935 {
1936 if( !name.IsEmpty() )
1937 {
1938 return wxString::Format( _( "Hidden pin %s [%s, %s, %s]" ),
1940 name,
1941 electricalTypeName,
1942 pinShapeName );
1943 }
1944 else
1945 {
1946 return wxString::Format( _( "Hidden pin %s [%s, %s]" ),
1948 electricalTypeName,
1949 pinShapeName );
1950 }
1951 }
1952}
1953
1954
1955namespace
1956{
1957struct PIN_COMPARISON_VIEW
1958{
1959 int unit;
1960 int bodyStyle;
1961 bool isPrivate;
1962 VECTOR2I position;
1963 const wxString& number;
1964 std::optional<int> length;
1965 PIN_ORIENTATION orientation;
1966 GRAPHIC_PINSHAPE shape;
1967 ELECTRICAL_PINTYPE type;
1968 std::optional<bool> hidden;
1969 std::optional<int> numberTextSize;
1970 std::optional<int> nameTextSize;
1971 const std::map<wxString, PIN_ALTERNATE>& alternates;
1972
1973 int Compare( const PIN_COMPARISON_VIEW& aOther, int aCompareFlags ) const
1974 {
1975 if( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::UNIT )
1976 {
1977 if( unit != aOther.unit )
1978 return unit - aOther.unit;
1979
1980 if( bodyStyle != aOther.bodyStyle )
1981 return bodyStyle - aOther.bodyStyle;
1982 }
1983
1984 if( isPrivate != aOther.isPrivate )
1985 return isPrivate ? 1 : -1;
1986
1987 if( number != aOther.number )
1988 return StrNumCmp( number, aOther.number );
1989
1990 if( position.x != aOther.position.x )
1991 return position.x - aOther.position.x;
1992
1993 if( position.y != aOther.position.y )
1994 return position.y - aOther.position.y;
1995
1996 if( length != aOther.length )
1997 return length.value_or( 0 ) - aOther.length.value_or( 0 );
1998
1999 if( orientation != aOther.orientation )
2000 return static_cast<int>( orientation ) - static_cast<int>( aOther.orientation );
2001
2002 if( shape != aOther.shape )
2003 return static_cast<int>( shape ) - static_cast<int>( aOther.shape );
2004
2005 if( type != aOther.type )
2006 return static_cast<int>( type ) - static_cast<int>( aOther.type );
2007
2008 if( ( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::PIN_VISIBILITIES ) && hidden != aOther.hidden )
2009 return hidden.value_or( false ) - aOther.hidden.value_or( false );
2010
2011 if( numberTextSize != aOther.numberTextSize )
2012 return numberTextSize.value_or( 0 ) - aOther.numberTextSize.value_or( 0 );
2013
2014 if( nameTextSize != aOther.nameTextSize )
2015 return nameTextSize.value_or( 0 ) - aOther.nameTextSize.value_or( 0 );
2016
2017 if( !( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::PIN_ALT_DEFS ) )
2018 return 0;
2019
2020 if( alternates.size() != aOther.alternates.size() )
2021 return static_cast<int>( alternates.size() - aOther.alternates.size() );
2022
2023 auto lhsItem = alternates.begin();
2024 auto rhsItem = aOther.alternates.begin();
2025
2026 while( lhsItem != alternates.end() )
2027 {
2028 const PIN_ALTERNATE& lhsAlt = lhsItem->second;
2029 const PIN_ALTERNATE& rhsAlt = rhsItem->second;
2030
2031 int retv = lhsAlt.m_Name.Cmp( rhsAlt.m_Name );
2032
2033 if( retv )
2034 return retv;
2035
2036 if( lhsAlt.m_Type != rhsAlt.m_Type )
2037 return static_cast<int>( lhsAlt.m_Type ) - static_cast<int>( rhsAlt.m_Type );
2038
2039 if( lhsAlt.m_Shape != rhsAlt.m_Shape )
2040 return static_cast<int>( lhsAlt.m_Shape ) - static_cast<int>( rhsAlt.m_Shape );
2041
2042 ++lhsItem;
2043 ++rhsItem;
2044 }
2045
2046 return 0;
2047 }
2048};
2049
2050PIN_COMPARISON_VIEW pinComparisonView( const PIN_COMPARISON_DATA& aData )
2051{
2052 return { aData.unit, aData.bodyStyle, aData.isPrivate, aData.position, aData.number,
2053 aData.length, aData.orientation, aData.shape, aData.type, aData.hidden,
2054 aData.numberTextSize, aData.nameTextSize, aData.alternates };
2055}
2056}
2057
2058int PIN_COMPARISON_DATA::Compare( const PIN_COMPARISON_DATA& aOther, int aCompareFlags ) const
2059{
2060 return pinComparisonView( *this ).Compare( pinComparisonView( aOther ), aCompareFlags );
2061}
2062
2069
2070
2071int SCH_PIN::compare( const SCH_ITEM& aOther, int aCompareFlags ) const
2072{
2073 // Ignore the UUID here
2074 // And the position, which we'll do after the number.
2075 int retv = SCH_ITEM::compare( aOther, aCompareFlags & ~( COMPARE_FLAGS::UUID | COMPARE_FLAGS::POSITION ) );
2076
2077 if( retv )
2078 return retv;
2079
2080 const SCH_PIN* tmp = static_cast<const SCH_PIN*>( &aOther );
2081
2082 wxCHECK( tmp, -1 );
2083
2084 if( dynamic_cast<const LIB_SYMBOL*>( GetParentSymbol() ) )
2085 {
2086 const PIN_COMPARISON_VIEW lhs{ GetUnit(), GetBodyStyle(), IsPrivate(), m_position, m_number,
2089 const PIN_COMPARISON_VIEW rhs{ tmp->GetUnit(), tmp->GetBodyStyle(), tmp->IsPrivate(), tmp->m_position,
2090 tmp->m_number, tmp->m_length, tmp->m_orientation, tmp->m_shape, tmp->m_type,
2091 tmp->m_hidden, tmp->m_numTextSize, tmp->m_nameTextSize, tmp->m_alternates };
2092 return lhs.Compare( rhs, aCompareFlags );
2093 }
2094
2095 if( m_number != tmp->m_number )
2096 {
2097 // StrNumCmp: sort the same as the pads in the footprint file
2098 return StrNumCmp( m_number, tmp->m_number );
2099 }
2100
2101 if( m_position.x != tmp->m_position.x )
2102 return m_position.x - tmp->m_position.x;
2103
2104 if( m_position.y != tmp->m_position.y )
2105 return m_position.y - tmp->m_position.y;
2106
2107 if( dynamic_cast<const SCH_SYMBOL*>( GetParentSymbol() ) )
2108 {
2109 if( m_libPin && !tmp->m_libPin )
2110 return 1;
2111 else if( !m_libPin && tmp->m_libPin )
2112 return -1;
2113 else if( m_libPin )
2114 retv = m_libPin->compare( *tmp->m_libPin, aCompareFlags );
2115
2116 if( retv )
2117 return retv;
2118
2119 retv = m_alt.Cmp( tmp->m_alt );
2120
2121 if( retv )
2122 return retv;
2123 }
2124
2125 return 0;
2126}
2127
2128
2129bool SCH_PIN::operator==( const SCH_ITEM& aOther ) const
2130{
2131 if( Type() != aOther.Type() )
2132 return false;
2133
2134 return *this == static_cast<const SCH_PIN&>( aOther );
2135}
2136
2137
2138bool SCH_PIN::operator==( const SCH_PIN& aPin ) const
2139{
2140 // Compare local positions below. SCH_ITEM's position compare uses global coordinates
2141 if( SCH_ITEM::compare( aPin, -1 & ~( COMPARE_FLAGS::UUID | COMPARE_FLAGS::POSITION ) ) != 0 )
2142 return false;
2143
2144 if( m_libPin && aPin.m_libPin )
2145 {
2146 // Both have a libPin; pins are children of a SCH_SYMBOL.
2147 if( !m_libPin->operator==( *aPin.m_libPin ) )
2148 return false;
2149
2150 if( m_alt != aPin.m_alt )
2151 return false;
2152 }
2153 else if( m_libPin != aPin.m_libPin )
2154 {
2155 // One has a libPin but the other doesn't.
2156 return false;
2157 }
2158 else
2159 {
2160 // Both libPins are nullptr; pins are children of a LIB_SYMBOL. Alternates are valid here.
2161 if( m_alternates != aPin.m_alternates )
2162 return false;
2163 }
2164
2165 if( GetName() != aPin.GetName() )
2166 return false;
2167
2168 if( GetNumber() != aPin.GetNumber() )
2169 return false;
2170
2171 // Don't use GetPosition(); it will return the global coordinates rather than the local ones
2172 if( m_position != aPin.m_position )
2173 return false;
2174
2175 if( GetLength() != aPin.GetLength() )
2176 return false;
2177
2178 if( GetOrientation() != aPin.GetOrientation() )
2179 return false;
2180
2181 if( GetShape() != aPin.GetShape() )
2182 return false;
2183
2184 if( GetType() != aPin.GetType() ) // Electrical type
2185 return false;
2186
2187 if( IsVisible() != aPin.IsVisible() )
2188 return false;
2189
2190 if( GetNumberTextSize() != aPin.GetNumberTextSize() )
2191 return false;
2192
2193 if( GetNameTextSize() != aPin.GetNameTextSize() )
2194 return false;
2195
2196 return true;
2197}
2198
2199
2200double SCH_PIN::Similarity( const SCH_ITEM& aOther ) const
2201{
2202 if( aOther.m_Uuid == m_Uuid )
2203 return 1.0;
2204
2205 if( aOther.Type() != SCH_PIN_T )
2206 return 0.0;
2207
2208 const SCH_PIN* other = static_cast<const SCH_PIN*>( &aOther );
2209
2210 if( m_libPin && !other->m_libPin )
2211 return 0.0;
2212 else if( !m_libPin && other->m_libPin )
2213 return 0.0;
2214 else if( m_libPin )
2215 return m_libPin->Similarity( *other->m_libPin );
2216
2217 double similarity = SimilarityBase( aOther );
2218
2219 if( m_name != other->m_name )
2220 similarity *= 0.9;
2221
2222 if( m_number != other->m_number )
2223 similarity *= 0.9;
2224
2225 if( m_position != other->m_position )
2226 similarity *= 0.9;
2227
2228 if( m_length != other->m_length )
2229 similarity *= 0.9;
2230
2231 if( m_orientation != other->m_orientation )
2232 similarity *= 0.9;
2233
2234 if( m_shape != other->m_shape )
2235 similarity *= 0.9;
2236
2237 if( m_type != other->m_type )
2238 similarity *= 0.9;
2239
2240 if( m_hidden != other->m_hidden )
2241 similarity *= 0.9;
2242
2243 if( m_numTextSize != other->m_numTextSize )
2244 similarity *= 0.9;
2245
2246 if( m_nameTextSize != other->m_nameTextSize )
2247 similarity *= 0.9;
2248
2249 if( m_alternates.size() != other->m_alternates.size() )
2250 similarity *= 0.9;
2251
2252 return similarity;
2253}
2254
2255
2256std::ostream& SCH_PIN::operator<<( std::ostream& aStream )
2257{
2258 aStream << "SCH_PIN:" << std::endl
2259 << " Name: \"" << m_name << "\"" << std::endl
2260 << " Number: \"" << m_number << "\"" << std::endl
2261 << " Position: " << m_position << std::endl
2262 << " Length: " << GetLength() << std::endl
2263 << " Orientation: " << PinOrientationName( m_orientation ) << std::endl
2264 << " Shape: " << PinShapeGetText( m_shape ) << std::endl
2265 << " Type: " << ElectricalPinTypeGetText( m_type ) << std::endl
2266 << " Name Text Size: " << GetNameTextSize() << std::endl
2267 << " Number Text Size: " << GetNumberTextSize() << std::endl;
2268
2269 return aStream;
2270}
2271
2272
2273#if defined(DEBUG)
2274
2275void SCH_PIN::Show( int nestLevel, std::ostream& os ) const
2276{
2277 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str()
2278 << " num=\"" << m_number.mb_str()
2279 << '"' << "/>\n";
2280}
2281
2282#endif
2283
2284
2285void SCH_PIN::CalcEdit( const VECTOR2I& aPosition )
2286{
2287 if( IsMoving() )
2288 SetPosition( aPosition );
2289}
2290
2291
2292static struct SCH_PIN_DESC
2293{
2295 {
2296 auto& pinTypeEnum = ENUM_MAP<ELECTRICAL_PINTYPE>::Instance();
2297
2298 if( pinTypeEnum.Choices().GetCount() == 0 )
2299 {
2300 pinTypeEnum.Map( ELECTRICAL_PINTYPE::PT_INPUT, _HKI( "Input" ) )
2301 .Map( ELECTRICAL_PINTYPE::PT_OUTPUT, _HKI( "Output" ) )
2302 .Map( ELECTRICAL_PINTYPE::PT_BIDI, _HKI( "Bidirectional" ) )
2303 .Map( ELECTRICAL_PINTYPE::PT_TRISTATE, _HKI( "Tri-state" ) )
2304 .Map( ELECTRICAL_PINTYPE::PT_PASSIVE, _HKI( "Passive" ) )
2305 .Map( ELECTRICAL_PINTYPE::PT_NIC, _HKI( "Free" ) )
2306 .Map( ELECTRICAL_PINTYPE::PT_UNSPECIFIED, _HKI( "Unspecified" ) )
2307 .Map( ELECTRICAL_PINTYPE::PT_POWER_IN, _HKI( "Power input" ) )
2308 .Map( ELECTRICAL_PINTYPE::PT_POWER_OUT, _HKI( "Power output" ) )
2309 .Map( ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR, _HKI( "Open collector" ) )
2310 .Map( ELECTRICAL_PINTYPE::PT_OPENEMITTER, _HKI( "Open emitter" ) )
2311 .Map( ELECTRICAL_PINTYPE::PT_NC, _HKI( "Unconnected" ) );
2312 }
2313
2314 auto& pinShapeEnum = ENUM_MAP<GRAPHIC_PINSHAPE>::Instance();
2315
2316 if( pinShapeEnum.Choices().GetCount() == 0 )
2317 {
2318 pinShapeEnum.Map( GRAPHIC_PINSHAPE::LINE, _HKI( "Line" ) )
2319 .Map( GRAPHIC_PINSHAPE::INVERTED, _HKI( "Inverted" ) )
2320 .Map( GRAPHIC_PINSHAPE::CLOCK, _HKI( "Clock" ) )
2321 .Map( GRAPHIC_PINSHAPE::INVERTED_CLOCK, _HKI( "Inverted clock" ) )
2322 .Map( GRAPHIC_PINSHAPE::INPUT_LOW, _HKI( "Input low" ) )
2323 .Map( GRAPHIC_PINSHAPE::CLOCK_LOW, _HKI( "Clock low" ) )
2324 .Map( GRAPHIC_PINSHAPE::OUTPUT_LOW, _HKI( "Output low" ) )
2325 .Map( GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK, _HKI( "Falling edge clock" ) )
2326 .Map( GRAPHIC_PINSHAPE::NONLOGIC, _HKI( "NonLogic" ) );
2327 }
2328
2329 auto& orientationEnum = ENUM_MAP<PIN_ORIENTATION>::Instance();
2330
2331 if( orientationEnum.Choices().GetCount() == 0 )
2332 {
2333 orientationEnum.Map( PIN_ORIENTATION::PIN_RIGHT, _HKI( "Right" ) )
2334 .Map( PIN_ORIENTATION::PIN_LEFT, _HKI( "Left" ) )
2335 .Map( PIN_ORIENTATION::PIN_UP, _HKI( "Up" ) )
2336 .Map( PIN_ORIENTATION::PIN_DOWN, _HKI( "Down" ) );
2337 }
2338
2339 auto isSymbolEditor =
2340 []( INSPECTABLE* aItem ) -> bool
2341 {
2342 if( SCH_PIN* pin = dynamic_cast<SCH_PIN*>( aItem ) )
2343 return dynamic_cast<LIB_SYMBOL*>( pin->GetParentSymbol() ) != nullptr;
2344
2345 return false;
2346 };
2347
2352
2353 // Lock state is inherited from parent symbol (no independent locking of child items)
2354 propMgr.Mask( TYPE_HASH( SCH_PIN ), TYPE_HASH( SCH_ITEM ), _HKI( "Locked" ) );
2355
2356 propMgr.AddProperty( new PROPERTY<SCH_PIN, wxString>( _HKI( "Pin Name" ),
2358 .SetWriteableFunc( isSymbolEditor );
2359
2360 propMgr.AddProperty( new PROPERTY<SCH_PIN, wxString>( _HKI( "Pin Number" ),
2362 .SetWriteableFunc( isSymbolEditor );
2363
2364 propMgr.AddProperty( new PROPERTY_ENUM<SCH_PIN, ELECTRICAL_PINTYPE>( _HKI( "Electrical Type" ),
2366 .SetWriteableFunc( isSymbolEditor );
2367
2368 propMgr.AddProperty( new PROPERTY_ENUM<SCH_PIN, GRAPHIC_PINSHAPE>( _HKI( "Graphic Style" ),
2370 .SetWriteableFunc( isSymbolEditor );
2371
2372 propMgr.AddProperty( new PROPERTY<SCH_PIN, int>( _HKI( "Position X" ),
2374 .SetAvailableFunc( isSymbolEditor );
2375
2376 propMgr.AddProperty( new PROPERTY<SCH_PIN, int>( _HKI( "Position Y" ),
2378 .SetAvailableFunc( isSymbolEditor );
2379
2380 propMgr.AddProperty( new PROPERTY_ENUM<SCH_PIN, PIN_ORIENTATION>( _HKI( "Orientation" ),
2382 .SetWriteableFunc( isSymbolEditor );
2383
2384 propMgr.AddProperty( new PROPERTY<SCH_PIN, int>( _HKI( "Length" ),
2387 .SetWriteableFunc( isSymbolEditor );
2388
2389 propMgr.AddProperty( new PROPERTY<SCH_PIN, int>( _HKI( "Name Text Size" ),
2392 .SetAvailableFunc( isSymbolEditor );
2393
2394 propMgr.AddProperty( new PROPERTY<SCH_PIN, int>( _HKI( "Number Text Size" ),
2397 .SetAvailableFunc( isSymbolEditor );
2398
2399 propMgr.AddProperty( new PROPERTY<SCH_PIN, bool>( _HKI( "Visible" ),
2401 .SetAvailableFunc( isSymbolEditor );
2402
2403 }
2405
2406
const char * name
KICOMMON_API types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICOMMON_API KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
Definition api_enums.cpp:55
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:130
BITMAPS
A list of all bitmap identifiers.
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:982
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:553
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:165
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition box2.h:308
static const COLOR4D WHITE
Definition color4d.h:403
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:400
The base class for create windows for drawing purpose.
const KIID m_Uuid
Definition eda_item.h:599
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
EDA_ITEM_FLAGS m_flags
Definition eda_item.h:608
virtual bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const
Compare the item against the search criteria in aSearchData.
Definition eda_item.h:484
EDA_ITEM * GetParent() const
Definition eda_item.h:112
EDA_ITEM * m_parent
Owner.
Definition eda_item.h:609
static bool Replace(const EDA_SEARCH_DATA &aSearchData, wxString &aText)
Perform a text replace on aText using the find and replace criteria in aSearchData on items that supp...
Definition eda_item.cpp:396
bool IsMoving() const
Definition eda_item.h:132
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:84
static ENUM_MAP< T > & Instance()
Definition property.h:783
Class that other classes need to inherit from, in order to be inspectable.
Definition inspectable.h:39
FONT is an abstract base class for both outline and stroke fonts.
Definition font.h:94
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
Definition font.cpp:143
VECTOR2I StringBoundaryLimits(const wxString &aText, const VECTOR2I &aSize, int aThickness, bool aBold, bool aItalic, const METRICS &aFontMetrics) const
Compute the boundary limits of aText (the bounding box of all shapes).
Definition font.cpp:439
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
std::shared_ptr< wxString > m_text
Definition color4d.h:397
COLOR4D & Desaturate()
Removes color (in HSL model)
Definition color4d.cpp:530
COLOR4D Mix(const COLOR4D &aColor, double aFactor) const
Return a color that is mixed with the input by a factor.
Definition color4d.h:293
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
const wxString & GetDefaultFont() const
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
virtual const COLOR4D & GetBackgroundColor() const =0
Return current background color settings.
Definition kiid.h:46
wxString AsString() const
Definition kiid.cpp:264
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition lib_id.cpp:65
Define a library symbol object.
Definition lib_symbol.h:114
const std::vector< ASSOCIATED_FOOTPRINT > & GetEffectiveAssociatedFootprints() const
Definition lib_symbol.h:300
const PIN_MAP_SET & GetEffectivePinMaps() const
Definition lib_symbol.h:285
Definition line.h:32
A pin layout helper is a class that manages the layout of the parts of a pin on a schematic symbol:
BOX2I GetPinBoundingBox(bool aIncludeLabelsOnInvisiblePins, bool aIncludeNameAndNumber, bool aIncludeElectricalType)
Get the bounding box of the pin itself.
const PIN_MAP * FindByName(const wxString &aName) const
Definition pin_map.cpp:133
A named pin map.
Definition pin_map.h:65
const wxString & GetPadNumber(const wxString &aPinNumber) const
Definition pin_map.cpp:85
bool HasEntry(const wxString &aPinNumber) const
Definition pin_map.cpp:79
Base plotter engine class.
Definition plotter.h:136
virtual void Circle(const VECTOR2I &pos, int diametre, FILL_T fill, int width)=0
void MoveTo(const VECTOR2I &pos)
Definition plotter.h:310
void FinishTo(const VECTOR2I &pos)
Definition plotter.h:320
RENDER_SETTINGS * RenderSettings()
Definition plotter.h:167
bool GetColorMode() const
Definition plotter.h:164
virtual void SetCurrentLineWidth(int width, void *aData=nullptr)=0
Set the line width for the next drawing.
void LineTo(const VECTOR2I &pos)
Definition plotter.h:315
virtual void PlotText(const VECTOR2I &aPos, const COLOR4D &aColor, const wxString &aText, const TEXT_ATTRIBUTES &aAttributes, KIFONT::FONT *aFont=nullptr, const KIFONT::METRICS &aFontMetrics=KIFONT::METRICS::Default(), void *aData=nullptr)
Definition plotter.cpp:617
virtual void SetColor(const COLOR4D &color)=0
PROPERTY_BASE & SetAvailableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Set a callback function to determine whether an object provides this property.
Definition property.h:263
PROPERTY_BASE & SetWriteableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Definition property.h:293
Provide class metadata.
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.
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
void AppendInfoToMsgPanel(std::vector< MSG_PANEL_ITEM > &aList) const
Adds information about the connection object to aList.
Schematic editor (Eeschema) main window.
SCH_SHEET_PATH & GetCurrentSheet() const
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:139
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:170
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 MatchesNetName(const EDA_SEARCH_DATA &aSearchData, const SCH_SHEET_PATH *aSheet) const
Match aSearchData against the connection of this item on aSheet.
Definition sch_item.cpp:676
int m_unit
Definition sch_item.h:839
SCH_ITEM & operator=(const SCH_ITEM &aPin)
Definition sch_item.cpp:91
int m_bodyStyle
Definition sch_item.h:840
SCH_RENDER_SETTINGS * getRenderSettings(PLOTTER *aPlotter) const
Definition sch_item.cpp:46
const SYMBOL * GetParentSymbol() const
Definition sch_item.cpp:350
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:302
int GetBodyStyle() const
Definition sch_item.h:253
bool IsLocked() const override
Definition sch_item.cpp:179
friend class LIB_SYMBOL
Definition sch_item.h:817
@ PIN_ALT_DEFS
Definition sch_item.h:755
@ PIN_VISIBILITIES
Definition sch_item.h:754
int GetUnit() const
Definition sch_item.h:243
bool IsPrivate() const
Definition sch_item.h:259
bool IsConnectivityDirty() const
Definition sch_item.h:630
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:65
SCH_CONNECTION * Connection(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve the connection associated with this object in the given sheet.
Definition sch_item.cpp:580
wxString ResolveText(const wxString &aText, const SCH_SHEET_PATH *aPath, int aDepth=0) const
Definition sch_item.cpp:464
virtual int compare(const SCH_ITEM &aOther, int aCompareFlags=~COMPARE_FLAGS::UNIT) const
Provide the draw object specific comparison called by the == and < operators.
Definition sch_item.cpp:935
const KIFONT::METRICS & GetFontMetrics() const
int GetEffectivePenWidth(const SCH_RENDER_SETTINGS *aSettings) const
SCH_LAYER_ID m_layer
Definition sch_item.h:838
double SimilarityBase(const SCH_ITEM &aItem) const
Calculate the boilerplate similarity for all LIB_ITEMs without preventing the use above of a pure vir...
Definition sch_item.h:398
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW=true) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
Definition sch_pin.cpp:1597
std::ostream & operator<<(std::ostream &aStream)
Definition sch_pin.cpp:2256
void SetAlt(const wxString &aAlt)
Set the name of the alternate pin.
Definition sch_pin.cpp:560
void PlotPinTexts(PLOTTER *aPlotter, const VECTOR2I &aPinPos, PIN_ORIENTATION aPinOrient, int aTextInside, bool aDrawPinNum, bool aDrawPinName, bool aDimmed) const
Plot the pin name and number.
Definition sch_pin.cpp:1082
VECTOR2I GetLocalPosition() const
Definition sch_pin.h:317
int GetNumberTextSize() const
Definition sch_pin.cpp:882
int GetLength() const
Definition sch_pin.cpp:421
std::optional< bool > m_hidden
Definition sch_pin.h:496
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition sch_pin.cpp:628
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_pin.cpp:1625
std::unique_ptr< PIN_LAYOUT_CACHE > m_layoutCache
The layout cache for this pin.
Definition sch_pin.h:518
void MirrorVerticallyPin(int aCenter)
Definition sch_pin.cpp:1546
void validateExtentsCache(KIFONT::FONT *aFont, int aSize, const wxString &aText, EXTENTS_CACHE *aCache) const
Definition sch_pin.cpp:1768
const BOX2I ViewBBox() const override
The view bounds of text that shows a net name must match the drawing, so this reads connectivity insi...
Definition sch_pin.cpp:1755
std::vector< int > ViewGetLayers() const override
Return the layers the item is drawn on (which may be more than its "home" layer)
Definition sch_pin.cpp:1761
const std::map< wxString, ALT > & GetAlternates() const
Definition sch_pin.h:219
void CalcEdit(const VECTOR2I &aPosition) override
Calculate the attributes of an item at aPosition when it is being edited.
Definition sch_pin.cpp:2285
void SetNumber(const wxString &aNumber)
Definition sch_pin.cpp:842
std::optional< int > m_nameTextSize
Definition sch_pin.h:500
PIN_ORIENTATION PinDrawOrient(const TRANSFORM &aTransform) const
Return the pin real orientation (PIN_UP, PIN_DOWN, PIN_RIGHT, PIN_LEFT), according to its orientation...
Definition sch_pin.cpp:1431
void SetVisible(bool aVisible)
Definition sch_pin.h:134
int GetX() const
Definition sch_pin.h:321
void ChangeLength(int aLength)
Change the length of a pin and adjust its position based on orientation.
Definition sch_pin.cpp:1492
void SetX(int aX)
Definition sch_pin.h:322
bool HasConnectivityChanges(const SCH_ITEM *aItem, const SCH_SHEET_PATH *aInstance=nullptr) const override
Check if aItem has connectivity changes against this object.
Definition sch_pin.cpp:1808
SCH_PIN & operator=(const SCH_PIN &aPin)
Definition sch_pin.cpp:249
SCH_PIN * m_libPin
Definition sch_pin.h:485
std::optional< wxString > GetSmallestLogicalNumber() const
Return the smallest logical pin number if this pin uses stacked notation and it is valid.
Definition sch_pin.cpp:727
void Move(const VECTOR2I &aOffset) override
Move the item by aMoveVector to a new position.
Definition sch_pin.cpp:1520
std::map< const SCH_SHEET_PATH, std::pair< wxString, bool > > m_net_name_map
Definition sch_pin.h:522
PIN_ORIENTATION m_orientation
Definition sch_pin.h:493
void SetOrientation(PIN_ORIENTATION aOrientation)
Definition sch_pin.h:113
void SetName(const wxString &aName)
Definition sch_pin.cpp:545
bool IsGlobalPower() const
Return whether this pin forms a global power connection: i.e., is part of a power symbol and of type ...
Definition sch_pin.cpp:481
bool SetIsDangling(bool aIsDangling)
Definition sch_pin.cpp:597
wxString getItemDescription(ALT *aAlt) const
Definition sch_pin.cpp:1910
bool IsVisible() const
Definition sch_pin.cpp:513
bool ConnectionPropagatesTo(const EDA_ITEM *aItem) const override
Return true if this item should propagate connection info to aItem.
Definition sch_pin.cpp:1850
bool IsLocked() const override
Definition sch_pin.cpp:1856
void swapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
Definition sch_pin.cpp:273
std::optional< int > m_numTextSize
Definition sch_pin.h:499
VECTOR2I GetPinRoot() const
Definition sch_pin.cpp:908
bool IsLocalPower() const
Local power pin is the same except that it is sheet-local and it does not support the legacy hidden p...
Definition sch_pin.cpp:500
ELECTRICAL_PINTYPE m_type
Definition sch_pin.h:495
PAD_RESOLUTION
Outcome of pin-to-pad resolution (issue #2282).
Definition sch_pin.h:175
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
Definition sch_pin.cpp:1559
SCH_PIN * GetLibPin() const
Definition sch_pin.h:109
void SetPosition(const VECTOR2I &aPos) override
Definition sch_pin.h:318
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_pin.cpp:2200
bool m_isDangling
Definition sch_pin.h:511
wxString GetElectricalTypeName() const
Definition sch_pin.cpp:474
std::vector< wxString > GetStackedPinNumbers(bool *aValid=nullptr) const
Definition sch_pin.cpp:714
std::map< wxString, ALT > m_alternates
Definition sch_pin.h:488
const wxString & GetName() const
Definition sch_pin.cpp:527
int GetStackedPinCount(bool *aValid=nullptr) const
Return the count of logical pins represented by this pin's stacked notation.
Definition sch_pin.cpp:720
bool operator==(const SCH_ITEM &aPin) const override
Definition sch_pin.cpp:2129
void SetLength(int aLength)
Definition sch_pin.h:119
bool IsDangling() const override
Definition sch_pin.cpp:588
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_pin.cpp:1604
void MirrorHorizontally(int aCenter) override
These transforms have effect only if the pin has a LIB_SYMBOL as parent.
Definition sch_pin.cpp:1539
std::recursive_mutex m_netmap_mutex
The name that this pin connection will drive onto a net.
Definition sch_pin.h:521
PIN_ORIENTATION GetOrientation() const
Definition sch_pin.cpp:386
wxString GetClass() const override
Return the class name.
Definition sch_pin.h:94
void SetNumberTextSize(int aSize)
Definition sch_pin.cpp:896
void SetShape(GRAPHIC_PINSHAPE aShape)
Definition sch_pin.h:116
void RotatePin(const VECTOR2I &aCenter, bool aRotateCCW=true)
Definition sch_pin.cpp:1566
VECTOR2I GetPosition() const override
Definition sch_pin.cpp:378
bool StackedTextSideFlipped(const TRANSFORM &aTransform) const
Return true when aTransform maps the side the stacked number block is drawn on (above horizontal pins...
Definition sch_pin.cpp:1466
wxString GetCanonicalElectricalTypeName() const
Definition sch_pin.cpp:467
bool Replace(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) override
Perform a text replace using the find and replace criteria in aSearchData on items that support text ...
Definition sch_pin.cpp:646
int GetNameTextSize() const
Definition sch_pin.cpp:856
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
Definition sch_pin.cpp:1883
VECTOR2I m_position
Definition sch_pin.h:491
GRAPHIC_PINSHAPE m_shape
Definition sch_pin.h:494
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
Definition sch_pin.cpp:333
int compare(const SCH_ITEM &aOther, int aCompareFlags=0) const override
The pin specific sort order is as follows:
Definition sch_pin.cpp:2071
const wxString & GetShownName() const
Definition sch_pin.cpp:697
PIN_ALTERNATE ALT
Definition sch_pin.h:63
void MirrorHorizontallyPin(int aCenter)
These transforms have always effects.
Definition sch_pin.cpp:1526
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
Definition sch_pin.cpp:667
PIN_LAYOUT_CACHE & GetLayoutCache() const
Get the layout cache associated with this pin.
Definition sch_pin.cpp:1799
wxString m_name
Definition sch_pin.h:497
wxString m_alt
Definition sch_pin.h:501
void SetType(ELECTRICAL_PINTYPE aType)
Definition sch_pin.cpp:455
const wxString & GetBaseName() const
Get the name without any alternates.
Definition sch_pin.cpp:536
void ClearDefaultNetName(const SCH_SHEET_PATH *aPath)
Definition sch_pin.cpp:1672
PIN_COMPARISON_DATA ComparisonData() const
Definition sch_pin.cpp:2063
void SetY(int aY)
Definition sch_pin.h:324
SCH_PIN(LIB_SYMBOL *aParentSymbol)
Definition sch_pin.cpp:139
wxString GetEffectivePadNumber(const SCH_SHEET_PATH &aSheet, const wxString &aVariantName, const LIB_ID &aFootprintLibId, const std::set< wxString > *aFootprintPadNumbers, PAD_RESOLUTION *aState=nullptr) const
Resolve the footprint pad number this symbol pin lands on (issue #2282).
Definition sch_pin.cpp:748
const wxString & GetShownNumber() const
Definition sch_pin.cpp:708
bool IsStacked(const SCH_PIN *aPin) const
Definition sch_pin.cpp:605
const wxString & GetNumber() const
Definition sch_pin.h:144
wxString m_number
Definition sch_pin.h:498
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition sch_pin.cpp:1483
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition sch_pin.h:280
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Definition sch_pin.cpp:296
static bool HasIdentityPad(const wxString &aPinNumber, const std::set< wxString > &aPads)
Definition sch_pin.cpp:819
wxString GetSmallestStackedPadNumber() const
Return the pin number to be used for deterministic operations such as auto‑generated net names.
Definition sch_pin.cpp:739
wxString GetDefaultNetName(const SCH_SHEET_PATH &aPath, bool aForceNoConnect=false)
Definition sch_pin.cpp:1683
std::optional< int > m_length
Definition sch_pin.h:492
GRAPHIC_PINSHAPE GetShape() const
Definition sch_pin.cpp:400
void PlotPinType(PLOTTER *aPlotter, const VECTOR2I &aPosition, PIN_ORIENTATION aOrientation, bool aDimmed) const
Definition sch_pin.cpp:931
int GetY() const
Definition sch_pin.h:323
bool IsPower() const
Check if the pin is either a global or local power pin.
Definition sch_pin.cpp:507
ELECTRICAL_PINTYPE GetType() const
Definition sch_pin.cpp:435
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition sch_pin.cpp:1868
void SetNameTextSize(int aSize)
Definition sch_pin.cpp:870
VECTOR2I TransformCoordinate(const VECTOR2I &aPoint) const
const KIGFX::COLOR4D & GetBackgroundColor() const override
Return current background color settings.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Schematic symbol object.
Definition sch_symbol.h:73
std::vector< const SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
const wxString GetValue(const SCH_SHEET_PATH *aPath, RESOLUTION_CONTEXT aContext, const wxString &aVariantName=wxEmptyString) const override
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
A base class for LIB_SYMBOL and SCH_SYMBOL.
Definition symbol.h:60
virtual bool IsGlobalPower() const =0
virtual bool IsLocalPower() const =0
virtual const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const =0
int GetPinNameOffset() const
Definition symbol.h:163
virtual bool GetShowPinNames() const
Definition symbol.h:169
virtual bool GetShowPinNumbers() const
Definition symbol.h:175
EDA_ORIENTATION m_Angle
GR_TEXT_H_ALIGN_T m_Halign
GR_TEXT_V_ALIGN_T m_Valign
for transforming drawing coordinates for a wxDC device context.
Definition transform.h:42
VECTOR2I TransformCoordinate(const VECTOR2I &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition transform.cpp:40
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
@ FOR_NETNAME
Definition common.h:92
@ RESOLVED
Definition common.h:95
#define DEFAULT_PINNUM_SIZE
The default pin number size when creating pins(can be changed in preference menu)
#define DEFAULT_PINNAME_SIZE
The default pin name size when creating pins(can be changed in preference menu)
#define DEFAULT_PIN_LENGTH
The default pin len value when creating pins(can be changed in preference menu)
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:450
static constexpr EDA_ANGLE ANGLE_VERTICAL
Definition eda_angle.h:445
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition eda_angle.h:444
@ NO_FILL
Definition eda_fill.h:30
#define STRUCT_DELETED
flag indication structures to be erased
#define SKIP_STRUCT
flag indicating that the structure should be ignored
#define SHOW_ELEC_TYPE
Show pin electrical type.
int GetPenSizeForNormal(int aTextSize)
Definition gr_text.cpp:57
const wxChar *const traceStackedPins
Flag to enable debug output for stacked pins handling in symbol/pin code.
@ LAYER_DANGLING
Definition layer_ids.h:499
@ LAYER_PINNUM
Definition layer_ids.h:480
@ LAYER_DEVICE
Definition layer_ids.h:488
@ LAYER_PINNAM
Definition layer_ids.h:481
@ LAYER_PIN
Definition layer_ids.h:492
@ LAYER_OP_CURRENTS
Definition layer_ids.h:524
@ LAYER_SELECTION_SHADOWS
Definition layer_ids.h:517
wxString RenderPinNetName(const PIN_NAME_FACT &aPin, const PIN_NAME_REFERENCE &aReference, bool aForceNoConnect)
Render a non-power pin name from unescaped values; an absent reference uses the symbol UUID.
KICOMMON_API int UnpackDistance(const types::Distance &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackCustomProperties(google::protobuf::RepeatedPtrField< types::CustomProperty > *aOutput, const EDA_ITEM &aItem)
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackDistance(types::Distance &aOutput, int aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackVector2(types::Vector2 &aOutput, const VECTOR2I &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void UnpackCustomProperties(const google::protobuf::RepeatedPtrField< types::CustomProperty > &aInput, EDA_ITEM &aItem)
#define _HKI(x)
Definition page_info.cpp:40
see class PGM_BASE
static int externalPinDecoSize(const SCHEMATIC_SETTINGS *aSettings, const SCH_PIN &aPin)
static int internalPinDecoSize(const SCHEMATIC_SETTINGS *aSettings, const SCH_PIN &aPin)
wxString PinShapeGetText(GRAPHIC_PINSHAPE shape)
Definition pin_type.cpp:231
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
Definition pin_type.h:32
@ PT_INPUT
usual pin input: must be connected
Definition pin_type.h:33
@ PT_NC
not connected (must be left open)
Definition pin_type.h:46
@ PT_OUTPUT
usual output
Definition pin_type.h:34
@ PT_TRISTATE
tri state bus pin
Definition pin_type.h:36
@ PT_NIC
not internally connected (may be connected to anything)
Definition pin_type.h:40
@ PT_BIDI
input or output (like port for a microprocessor)
Definition pin_type.h:35
@ PT_OPENEMITTER
pin type open emitter
Definition pin_type.h:45
@ PT_POWER_OUT
output of a regulator: intended to be connected to power input pins
Definition pin_type.h:43
@ PT_OPENCOLLECTOR
pin type open collector
Definition pin_type.h:44
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
Definition pin_type.h:42
@ PT_UNSPECIFIED
unknown electrical properties: creates always a warning when connected
Definition pin_type.h:41
@ PT_PASSIVE
pin for passive symbols: must be connected, and can be connected to any pin.
Definition pin_type.h:39
BITMAPS ElectricalPinTypeGetBitmap(ELECTRICAL_PINTYPE)
Definition pin_type.cpp:217
wxString ElectricalPinTypeGetText(ELECTRICAL_PINTYPE)
Definition pin_type.cpp:203
wxString PinOrientationName(PIN_ORIENTATION aOrientation)
Definition pin_type.cpp:259
PIN_ORIENTATION
The symbol library pin object orientations.
Definition pin_type.h:101
@ PIN_UP
The pin extends upwards from the connection point: Probably on the bottom side of the symbol.
Definition pin_type.h:123
@ PIN_RIGHT
The pin extends rightwards from the connection point.
Definition pin_type.h:107
@ PIN_LEFT
The pin extends leftwards from the connection point: Probably on the right side of the symbol.
Definition pin_type.h:114
@ PIN_DOWN
The pin extends downwards from the connection: Probably on the top side of the symbol.
Definition pin_type.h:131
GRAPHIC_PINSHAPE
Definition pin_type.h:80
#define TYPE_HASH(x)
Macro to generate unique identifier for a type.
Definition property.h:74
#define ENUM_TO_WXANY(type)
Definition property.h:890
@ PT_COORD
Coordinate expressed in distance units (mm/inch)
Definition property.h:65
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition property.h:63
#define REGISTER_TYPE(x)
Helper macro to map type hashes to names.
wxString FormatStackedPinForDisplay(const wxString &aPinNumber, int aPinLength, int aTextSize, KIFONT::FONT *aFont, const KIFONT::METRICS &aFontMetrics)
Break a stacked pin number of the form "[A,B,C]" into one number per line when it is too wide to sit ...
Definition sch_pin.cpp:51
static int externalPinDecoSize(const RENDER_SETTINGS *aSettings, const SCH_PIN &aPin)
Utility for getting the size of the 'external' pin decorators (as a radius) i.e.
Definition sch_pin.cpp:128
#define PIN_TEXT_MARGIN
Definition sch_pin.cpp:109
static int internalPinDecoSize(const RENDER_SETTINGS *aSettings, const SCH_PIN &aPin)
Utility for getting the size of the 'internal' pin decorators (as a radius) i.e.
Definition sch_pin.cpp:114
static struct SCH_PIN_DESC _SCH_PIN_DESC
wxString FormatStackedPinForDisplay(const wxString &aPinNumber, int aPinLength, int aTextSize, KIFONT::FONT *aFont, const KIFONT::METRICS &aFontMetrics)
Break a stacked pin number of the form "[A,B,C]" into one number per line when it is too wide to sit ...
Definition sch_pin.cpp:51
#define TARGET_PIN_RADIUS
Definition sch_pin.h:48
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
T * GetAppSettings(const char *aFilename)
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
std::vector< wxString > ExpandStackedPinNotation(const wxString &aPinName, bool *aValid)
Expand stacked pin notation like [1,2,3], [1-4], [A1-A4], or [AA1-AA3,AB4,CD12-CD14] into individual ...
wxString UnescapeString(const wxString &aSource)
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
std::vector< wxString > SplitStackedPinDisplayItems(const wxString &aInner)
Split the inner part of a stacked notation string (the text between the brackets) into its individual...
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
int CountStackedPinNotation(const wxString &aPinName, bool *aValid)
Count the number of pins represented by stacked pin notation.
@ CTX_NETNAME
A first-class footprint choice on a LIB_SYMBOL, tied to a named pin map.
Definition pin_map.h:159
GRAPHIC_PINSHAPE m_Shape
ELECTRICAL_PINTYPE m_Type
Owned library-pin inputs; no parent, layout cache or schematic pointers.
std::map< wxString, PIN_ALTERNATE > alternates
ELECTRICAL_PINTYPE type
PIN_ORIENTATION orientation
std::optional< int > numberTextSize
std::optional< int > nameTextSize
std::optional< int > length
GRAPHIC_PINSHAPE shape
int Compare(const PIN_COMPARISON_DATA &aOther, int aCompareFlags) const
Definition sch_pin.cpp:2058
std::optional< bool > hidden
One symbol-pin to footprint-pad mapping inside a PIN_MAP.
Definition pin_map.h:42
Per-instance override of the active pin map and a sparse delta on top.
Definition pin_map.h:200
std::vector< PIN_MAP_ENTRY > m_Edits
Definition pin_map.h:203
PIN_MAP_OVERRIDE_MODE m_Mode
Definition pin_map.h:201
KIFONT::FONT * m_Font
Definition sch_pin.h:456
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
KIBIS top(path, &reporter)
KIBIS_PIN * pin
int radius
VECTOR2I end
wxString result
Test unit parsing edge cases and error handling.
GR_TEXT_H_ALIGN_T
This is API surface mapped to common.types.HorizontalAlignment.
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
GR_TEXT_V_ALIGN_T
This is API surface mapped to common.types.VertialAlignment.
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
wxLogTrace helper definitions.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition trigo.cpp:227
@ SCH_PIN_T
Definition typeinfo.h:149
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708
VECTOR2< double > VECTOR2D
Definition vector2d.h:707