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