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