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, you may find one here:
22 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
23 * or you may search the http://www.gnu.org website for the version 2 license,
24 * or you may write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26 */
27
28#include "sch_pin.h"
29
30#include <base_units.h>
31#include <pgm_base.h>
32#include <pin_layout_cache.h>
33#include <plotters/plotter.h>
34#include <sch_draw_panel.h>
35#include <sch_edit_frame.h>
36#include <symbol_edit_frame.h>
39#include <trigo.h>
40#include <string_utils.h>
41
42wxString FormatStackedPinForDisplay( const wxString& aPinNumber, int aPinLength, int aTextSize, KIFONT::FONT* aFont,
43 const KIFONT::METRICS& aFontMetrics )
44{
45 // Check if this is stacked pin notation: [A,B,C]
46 if( !aPinNumber.StartsWith( "[" ) || !aPinNumber.EndsWith( "]" ) )
47 return aPinNumber;
48
49 const int minPinTextWidth = schIUScale.MilsToIU( 50 );
50 const int maxPinTextWidth = std::max( aPinLength, minPinTextWidth );
51
52 VECTOR2D fontSize( aTextSize, aTextSize );
53 int penWidth = GetPenSizeForNormal( aTextSize );
54 VECTOR2I textExtents = aFont->StringBoundaryLimits( aPinNumber, fontSize, penWidth, false, false, aFontMetrics );
55
56 if( textExtents.x <= maxPinTextWidth )
57 return aPinNumber; // Fits already
58
59 // Strip brackets and split by comma
60 wxString inner = aPinNumber.Mid( 1, aPinNumber.Length() - 2 );
61 wxArrayString parts;
62 wxStringSplit( inner, parts, ',' );
63
64 if( parts.empty() )
65 return aPinNumber; // malformed; fallback
66
67 // Build multi-line representation inside braces, each line trimmed
68 wxString result = "[";
69
70 for( size_t i = 0; i < parts.size(); ++i )
71 {
72 wxString line = parts[i];
73 line.Trim( true ).Trim( false );
74
75 if( i > 0 )
76 result += "\n";
77
78 result += line;
79 }
80
81 result += "]";
82 return result;
83}
84
85
86// small margin in internal units between the pin text and the pin line
87#define PIN_TEXT_MARGIN 4
88
92static int internalPinDecoSize( const RENDER_SETTINGS* aSettings, const SCH_PIN &aPin )
93{
94 const SCH_RENDER_SETTINGS* settings = static_cast<const SCH_RENDER_SETTINGS*>( aSettings );
95
96 if( settings && settings->m_PinSymbolSize )
97 return settings->m_PinSymbolSize;
98
99 return aPin.GetNameTextSize() != 0 ? aPin.GetNameTextSize() / 2 : aPin.GetNumberTextSize() / 2;
100}
101
102
106static int externalPinDecoSize( const RENDER_SETTINGS* aSettings, const SCH_PIN &aPin )
107{
108 const SCH_RENDER_SETTINGS* settings = static_cast<const SCH_RENDER_SETTINGS*>( aSettings );
109
110 if( settings && settings->m_PinSymbolSize )
111 return settings->m_PinSymbolSize;
112
113 return aPin.GetNumberTextSize() / 2;
114}
115
116
117SCH_PIN::SCH_PIN( LIB_SYMBOL* aParentSymbol ) :
118 SCH_ITEM( aParentSymbol, SCH_PIN_T, 0, 0 ),
119 m_libPin( nullptr ),
120 m_position( { 0, 0 } ),
121 m_length( schIUScale.MilsToIU( DEFAULT_PIN_LENGTH ) ),
122 m_orientation( PIN_ORIENTATION::PIN_RIGHT ),
123 m_shape( GRAPHIC_PINSHAPE::LINE ),
125 m_hidden( false ),
126 m_numTextSize( schIUScale.MilsToIU( DEFAULT_PINNUM_SIZE ) ),
127 m_nameTextSize( schIUScale.MilsToIU( DEFAULT_PINNAME_SIZE ) ),
128 m_isDangling( true ),
129 m_layoutCache( std::make_unique<PIN_LAYOUT_CACHE>( *this ) )
130{
132 {
133 m_length = schIUScale.MilsToIU( cfg->m_Defaults.pin_length );
134 m_numTextSize = schIUScale.MilsToIU( cfg->m_Defaults.pin_num_size );
135 m_nameTextSize = schIUScale.MilsToIU( cfg->m_Defaults.pin_name_size );
136 }
137
138 m_layer = LAYER_DEVICE;
139}
140
141
142SCH_PIN::SCH_PIN( LIB_SYMBOL* aParentSymbol, const wxString& aName, const wxString& aNumber,
143 PIN_ORIENTATION aOrientation, ELECTRICAL_PINTYPE aPinType, int aLength,
144 int aNameTextSize, int aNumTextSize, int aBodyStyle, const VECTOR2I& aPos,
145 int aUnit ) :
146 SCH_ITEM( aParentSymbol, SCH_PIN_T, aUnit, aBodyStyle ),
147 m_libPin( nullptr ),
148 m_position( aPos ),
149 m_length( aLength ),
150 m_orientation( aOrientation ),
152 m_type( aPinType ),
153 m_hidden( false ),
154 m_numTextSize( aNumTextSize ),
155 m_nameTextSize( aNameTextSize ),
156 m_isDangling( true ),
157 m_layoutCache( std::make_unique<PIN_LAYOUT_CACHE>( *this ) )
158{
159 SetName( aName );
160 SetNumber( aNumber );
161
163}
164
165
166SCH_PIN::SCH_PIN( SCH_SYMBOL* aParentSymbol, SCH_PIN* aLibPin ) :
167 SCH_ITEM( aParentSymbol, SCH_PIN_T, 0, 0 ),
168 m_libPin( aLibPin ),
172 m_isDangling( true ),
173 m_layoutCache( std::make_unique<PIN_LAYOUT_CACHE>( *this ) )
174{
175 wxASSERT( aParentSymbol );
176
177 SetName( m_libPin->GetName() );
178 SetNumber( m_libPin->GetNumber() );
179 m_position = m_libPin->GetPosition();
180
182}
183
184
185SCH_PIN::SCH_PIN( SCH_SYMBOL* aParentSymbol, const wxString& aNumber, const wxString& aAlt,
186 const KIID& aUuid ) :
187 SCH_ITEM( aParentSymbol, SCH_PIN_T ),
188 m_libPin( nullptr ),
192 m_number( aNumber ),
193 m_alt( aAlt ),
194 m_isDangling( true ),
195 m_layoutCache( std::make_unique<PIN_LAYOUT_CACHE>( *this ) )
196{
197 wxASSERT( aParentSymbol );
198
199 const_cast<KIID&>( m_Uuid ) = aUuid;
201}
202
203
204SCH_PIN::SCH_PIN( const SCH_PIN& aPin ) :
205 SCH_ITEM( aPin ),
206 m_libPin( aPin.m_libPin ),
208 m_position( aPin.m_position ),
209 m_length( aPin.m_length ),
211 m_shape( aPin.m_shape ),
212 m_type( aPin.m_type ),
213 m_hidden( aPin.m_hidden ),
216 m_alt( aPin.m_alt ),
218 m_layoutCache( std::make_unique<PIN_LAYOUT_CACHE>( *this ) )
219{
220 SetName( aPin.m_name );
221 SetNumber( aPin.m_number );
222
223 m_layer = aPin.m_layer;
224}
225
226
230
231
233{
234 SCH_ITEM::operator=( aPin );
235
236 m_libPin = aPin.m_libPin;
238 m_alt = aPin.m_alt;
239 m_name = aPin.m_name;
240 m_number = aPin.m_number;
241 m_position = aPin.m_position;
242 m_length = aPin.m_length;
244 m_shape = aPin.m_shape;
245 m_type = aPin.m_type;
246 m_hidden = aPin.m_hidden;
250
251 return *this;
252}
253
254
256{
257 if( const SCH_SYMBOL* symbol = dynamic_cast<const SCH_SYMBOL*>( GetParentSymbol() ) )
258 return symbol->GetTransform().TransformCoordinate( m_position ) + symbol->GetPosition();
259 else
260 return m_position;
261}
262
264{
266 {
267 if( !m_libPin )
269
270 return m_libPin->GetOrientation();
271 }
272
273 return m_orientation;
274}
275
276
278{
279 if( !m_alt.IsEmpty() )
280 {
281 if( !m_libPin )
283
284 return m_libPin->GetAlt( m_alt ).m_Shape;
285 }
287 {
288 if( !m_libPin )
290
291 return m_libPin->GetShape();
292 }
293
294 return m_shape;
295}
296
297
299{
300 if( !m_length.has_value() )
301 {
302 if( !m_libPin )
303 return 0;
304
305 return m_libPin->GetLength();
306 }
307
308 return m_length.value();
309}
310
311
313{
314 if( !m_alt.IsEmpty() )
315 {
316 if( !m_libPin )
318
319 return m_libPin->GetAlt( m_alt ).m_Type;
320 }
322 {
323 if( !m_libPin )
325
326 return m_libPin->GetType();
327 }
328
329 return m_type;
330}
331
333{
334 if( aType == m_type )
335 return;
336
337 m_type = aType;
339}
340
341
343{
345 return ::GetCanonicalElectricalTypeName( m_type );
346
347 if( !m_libPin )
348 return ::GetCanonicalElectricalTypeName( ELECTRICAL_PINTYPE::PT_UNSPECIFIED );
349
350 return m_libPin->GetCanonicalElectricalTypeName();
351}
352
353
355{
358
359 if( !m_libPin )
361
362 return m_libPin->GetElectricalTypeName();
363}
364
365
367{
369 && ( !IsVisible() || GetParentSymbol()->IsGlobalPower() );
370}
371
372
378
379
381{
382 return IsLocalPower() || IsGlobalPower();
383}
384
385
387{
388 if( !m_hidden.has_value() )
389 {
390 if( !m_libPin )
391 return true;
392
393 return m_libPin->IsVisible();
394 }
395
396 return !m_hidden.value();
397}
398
399
400const wxString& SCH_PIN::GetName() const
401{
402 if( !m_alt.IsEmpty() )
403 return m_alt;
404
405 return GetBaseName();
406}
407
408
409const wxString& SCH_PIN::GetBaseName() const
410{
411 if( m_libPin )
412 return m_libPin->GetBaseName();
413
414 return m_name;
415}
416
417
418void SCH_PIN::SetName( const wxString& aName )
419{
420 if( m_name == aName )
421 return;
422
423 m_name = aName;
424
425 // pin name string does not support spaces
426 m_name.Replace( wxT( " " ), wxT( "_" ) );
427
429}
430
431
432void SCH_PIN::SetAlt( const wxString& aAlt )
433{
434 // Do not set the alternate pin definition to the default pin name. This breaks the library
435 // symbol comparison for the ERC and the library diff tool. It also incorrectly causes the
436 // schematic symbol pin alternate to be set.
437 if( aAlt.IsEmpty() || aAlt == GetBaseName() )
438 {
439 m_alt = wxEmptyString;
440 return;
441 }
442
443 if( !m_libPin )
444 {
445 wxFAIL_MSG( wxString::Format( wxS( "Pin '%s' has no corresponding lib_pin" ), m_number ) );
446 m_alt = wxEmptyString;
447 return;
448 }
449
450 if( !m_libPin->GetAlternates().contains( aAlt ) )
451 {
452 wxFAIL_MSG( wxString::Format( wxS( "Pin '%s' has no alterate '%s'" ), m_number, aAlt ) );
453 m_alt = wxEmptyString;
454 return;
455 }
456
457 m_alt = aAlt;
458}
459
461{
463 return false;
464
465 return m_isDangling;
466}
467
468
469void SCH_PIN::SetIsDangling( bool aIsDangling )
470{
471 m_isDangling = aIsDangling;
472}
473
474
475bool SCH_PIN::IsStacked( const SCH_PIN* aPin ) const
476{
477 const auto isPassiveOrNic = []( ELECTRICAL_PINTYPE t )
478 {
480 };
481
482 const bool sameParent = m_parent == aPin->GetParent();
483 const bool samePos = GetPosition() == aPin->GetPosition();
484 const bool sameName = GetName() == aPin->GetName();
485 const bool typeCompat = GetType() == aPin->GetType()
486 || isPassiveOrNic( GetType() )
487 || isPassiveOrNic( aPin->GetType() );
488
489 wxLogTrace( "KICAD_STACKED_PINS",
490 wxString::Format( "IsStacked: this='%s/%s' other='%s/%s' sameParent=%d samePos=%d sameName=%d typeCompat=%d",
491 GetName(), GetNumber(), aPin->GetName(), aPin->GetNumber(), sameParent,
492 samePos, sameName, typeCompat ) );
493
494 return sameParent && samePos && sameName && typeCompat;
495}
496
497
498bool SCH_PIN::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
499{
500 const SCH_SEARCH_DATA& schSearchData =
501 dynamic_cast<const SCH_SEARCH_DATA&>( aSearchData );
502
503 if( schSearchData.searchAllPins
504 && ( EDA_ITEM::Matches( GetName(), aSearchData )
505 || EDA_ITEM::Matches( GetNumber(), aSearchData ) ) )
506 {
507 return true;
508 }
509
510 SCH_CONNECTION* connection = nullptr;
511 SCH_SHEET_PATH* sheetPath = reinterpret_cast<SCH_SHEET_PATH*>( aAuxData );
512
513 if( schSearchData.searchNetNames && sheetPath && ( connection = Connection( sheetPath ) ) )
514 {
515 wxString netName = connection->GetNetName();
516
517 if( EDA_ITEM::Matches( netName, aSearchData ) )
518 return true;
519 }
520
521 return false;
522}
523
524
525bool SCH_PIN::Replace( const EDA_SEARCH_DATA& aSearchData, void* aAuxData )
526{
527 bool isReplaced = false;
528
529 if( dynamic_cast<LIB_SYMBOL*>( GetParentSymbol() ) )
530 {
531 isReplaced |= EDA_ITEM::Replace( aSearchData, m_name );
532 isReplaced |= EDA_ITEM::Replace( aSearchData, m_number );
533 }
534 else
535 {
536 /* TODO: waiting on a way to override pins in the schematic...
537 isReplaced |= EDA_ITEM::Replace( aSearchData, m_name );
538 isReplaced |= EDA_ITEM::Replace( aSearchData, m_number );
539 */
540 }
541
542 return isReplaced;
543}
544
545
546bool SCH_PIN::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
547{
548 // When looking for an "exact" hit aAccuracy will be 0 which works poorly if the pin has
549 // no pin number or name. Give it a floor.
550 if( Schematic() )
551 aAccuracy = std::max( aAccuracy, Schematic()->Settings().m_PinSymbolSize / 4 );
552
553 BOX2I rect = GetBoundingBox( false, true, m_flags & SHOW_ELEC_TYPE );
554
555 return rect.Inflate( aAccuracy ).Contains( aPosition );
556}
557
558
559bool SCH_PIN::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
560{
562 return false;
563
564 BOX2I sel = aRect;
565
566 if ( aAccuracy )
567 sel.Inflate( aAccuracy );
568
569 if( aContained )
570 return sel.Contains( GetBoundingBox( false, false, false ) );
571
572 return sel.Intersects( GetBoundingBox( false, true, m_flags & SHOW_ELEC_TYPE ) );
573}
574
575
576wxString SCH_PIN::GetShownName() const
577{
578 if( !m_alt.IsEmpty() )
579 return m_alt;
580 else if( m_libPin )
581 return m_libPin->GetShownName();
582
583 return m_name;
584}
585
586
588{
589 return m_number;
590}
591
592
593std::vector<wxString> SCH_PIN::GetStackedPinNumbers( bool* aValid ) const
594{
595 wxString shown = GetShownNumber();
596 wxLogTrace( "KICAD_STACKED_PINS",
597 wxString::Format( "GetStackedPinNumbers: shown='%s'", shown ) );
598
599 std::vector<wxString> numbers = ExpandStackedPinNotation( shown, aValid );
600
601 // Log the expansion for debugging
602 wxLogTrace( "KICAD_STACKED_PINS",
603 wxString::Format( "Expanded '%s' to %zu pins", shown, numbers.size() ) );
604 for( const wxString& num : numbers )
605 {
606 wxLogTrace( "KICAD_STACKED_PINS", wxString::Format( " -> '%s'", num ) );
607 }
608
609 return numbers;
610}
611
612std::optional<wxString> SCH_PIN::GetSmallestLogicalNumber() const
613{
614 bool valid = false;
615 auto numbers = GetStackedPinNumbers( &valid );
616
617 if( valid && !numbers.empty() )
618 return numbers.front(); // Already in ascending order
619
620 return std::nullopt;
621}
622
623
625{
626 if( auto smallest = GetSmallestLogicalNumber() )
627 return *smallest;
628
629 return GetShownNumber();
630}
631
632
633void SCH_PIN::SetNumber( const wxString& aNumber )
634{
635 if( m_number == aNumber )
636 return;
637
638 m_number = aNumber;
639 // pin number string does not support spaces
640 m_number.Replace( wxT( " " ), wxT( "_" ) );
641
643}
644
645
647{
648 if( !m_nameTextSize.has_value() )
649 {
650 if( !m_libPin )
651 return schIUScale.MilsToIU( DEFAULT_PINNAME_SIZE );
652
653 return m_libPin->GetNameTextSize();
654 }
655
656 return m_nameTextSize.value();
657}
658
659
661{
662 if( aSize == m_nameTextSize )
663 return;
664
665 m_nameTextSize = aSize;
667}
668
669
671{
672 if( !m_numTextSize.has_value() )
673 {
674 if( !m_libPin )
675 return schIUScale.MilsToIU( DEFAULT_PINNUM_SIZE );
676
677 return m_libPin->GetNumberTextSize();
678 }
679
680 return m_numTextSize.value();
681}
682
683
685{
686 if( aSize == m_numTextSize )
687 return;
688
689 m_numTextSize = aSize;
691}
692
693
695{
696 if( const SCH_SYMBOL* symbol = dynamic_cast<const SCH_SYMBOL*>( GetParentSymbol() ) )
697 {
698 const TRANSFORM& t = symbol->GetTransform();
699
700 if( !m_libPin )
701 return GetPosition();
702
703 return t.TransformCoordinate( m_libPin->GetPinRoot() ) + symbol->GetPosition();
704 }
705
706 switch( GetOrientation() )
707 {
708 default:
713 }
714}
715
716
717void SCH_PIN::PlotPinType( PLOTTER *aPlotter, const VECTOR2I &aPosition,
718 PIN_ORIENTATION aOrientation, bool aDimmed ) const
719{
720 int MapX1, MapY1, x1, y1;
721 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
722 COLOR4D color = renderSettings->GetLayerColor( LAYER_PIN );
723 COLOR4D bg = renderSettings->GetBackgroundColor();
724 int penWidth = GetEffectivePenWidth( renderSettings );
725 int pinLength = GetLength();
726
727 if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
728 bg = COLOR4D::WHITE;
729
730 if( aDimmed )
731 {
732 color.Desaturate( );
733 color = color.Mix( bg, 0.5f );
734 }
735
736 aPlotter->SetColor( color );
737 aPlotter->SetCurrentLineWidth( penWidth );
738
739 MapX1 = MapY1 = 0;
740 x1 = aPosition.x; y1 = aPosition.y;
741
742 switch( aOrientation )
743 {
744 case PIN_ORIENTATION::PIN_UP: y1 = aPosition.y - pinLength; MapY1 = 1; break;
745 case PIN_ORIENTATION::PIN_DOWN: y1 = aPosition.y + pinLength; MapY1 = -1; break;
746 case PIN_ORIENTATION::PIN_LEFT: x1 = aPosition.x - pinLength; MapX1 = 1; break;
747 case PIN_ORIENTATION::PIN_RIGHT: x1 = aPosition.x + pinLength; MapX1 = -1; break;
748 case PIN_ORIENTATION::INHERIT: wxFAIL_MSG( wxS( "aOrientation must be resolved!" ) ); break;
749 }
750
752 {
753 const int radius = externalPinDecoSize( aPlotter->RenderSettings(), *this );
754 aPlotter->Circle( VECTOR2I( MapX1 * radius + x1, MapY1 * radius + y1 ), radius * 2,
755 FILL_T::NO_FILL, penWidth );
756
757 aPlotter->MoveTo( VECTOR2I( MapX1 * radius * 2 + x1, MapY1 * radius * 2 + y1 ) );
758 aPlotter->FinishTo( aPosition );
759 }
761 {
762 const int deco_size = internalPinDecoSize( aPlotter->RenderSettings(), *this );
763 if( MapY1 == 0 ) /* MapX1 = +- 1 */
764 {
765 aPlotter->MoveTo( VECTOR2I( x1, y1 + deco_size ) );
766 aPlotter->LineTo( VECTOR2I( x1 + MapX1 * deco_size * 2, y1 ) );
767 aPlotter->FinishTo( VECTOR2I( x1, y1 - deco_size ) );
768 }
769 else /* MapX1 = 0 */
770 {
771 aPlotter->MoveTo( VECTOR2I( x1 + deco_size, y1 ) );
772 aPlotter->LineTo( VECTOR2I( x1, y1 + MapY1 * deco_size * 2 ) );
773 aPlotter->FinishTo( VECTOR2I( x1 - deco_size, y1 ) );
774 }
775
776 aPlotter->MoveTo( VECTOR2I( MapX1 * deco_size * 2 + x1, MapY1 * deco_size * 2 + y1 ) );
777 aPlotter->FinishTo( aPosition );
778 }
779 else
780 {
781 aPlotter->MoveTo( VECTOR2I( x1, y1 ) );
782 aPlotter->FinishTo( aPosition );
783 }
784
788 {
789 const int deco_size = internalPinDecoSize( aPlotter->RenderSettings(), *this );
790 if( MapY1 == 0 ) /* MapX1 = +- 1 */
791 {
792 aPlotter->MoveTo( VECTOR2I( x1, y1 + deco_size ) );
793 aPlotter->LineTo( VECTOR2I( x1 - MapX1 * deco_size * 2, y1 ) );
794 aPlotter->FinishTo( VECTOR2I( x1, y1 - deco_size ) );
795 }
796 else /* MapX1 = 0 */
797 {
798 aPlotter->MoveTo( VECTOR2I( x1 + deco_size, y1 ) );
799 aPlotter->LineTo( VECTOR2I( x1, y1 - MapY1 * deco_size * 2 ) );
800 aPlotter->FinishTo( VECTOR2I( x1 - deco_size, y1 ) );
801 }
802 }
803
805 || m_shape == GRAPHIC_PINSHAPE::CLOCK_LOW ) /* IEEE symbol "Active Low Input" */
806 {
807 const int deco_size = externalPinDecoSize( aPlotter->RenderSettings(), *this );
808
809 if( MapY1 == 0 ) /* MapX1 = +- 1 */
810 {
811 aPlotter->MoveTo( VECTOR2I( x1 + MapX1 * deco_size * 2, y1 ) );
812 aPlotter->LineTo( VECTOR2I( x1 + MapX1 * deco_size * 2, y1 - deco_size * 2 ) );
813 aPlotter->FinishTo( VECTOR2I( x1, y1 ) );
814 }
815 else /* MapX1 = 0 */
816 {
817 aPlotter->MoveTo( VECTOR2I( x1, y1 + MapY1 * deco_size * 2 ) );
818 aPlotter->LineTo( VECTOR2I( x1 - deco_size * 2, y1 + MapY1 * deco_size * 2 ) );
819 aPlotter->FinishTo( VECTOR2I( x1, y1 ) );
820 }
821 }
822
823 if( m_shape == GRAPHIC_PINSHAPE::OUTPUT_LOW ) /* IEEE symbol "Active Low Output" */
824 {
825 const int symbol_size = externalPinDecoSize( aPlotter->RenderSettings(), *this );
826
827 if( MapY1 == 0 ) /* MapX1 = +- 1 */
828 {
829 aPlotter->MoveTo( VECTOR2I( x1, y1 - symbol_size * 2 ) );
830 aPlotter->FinishTo( VECTOR2I( x1 + MapX1 * symbol_size * 2, y1 ) );
831 }
832 else /* MapX1 = 0 */
833 {
834 aPlotter->MoveTo( VECTOR2I( x1 - symbol_size * 2, y1 ) );
835 aPlotter->FinishTo( VECTOR2I( x1, y1 + MapY1 * symbol_size * 2 ) );
836 }
837 }
838 else if( m_shape == GRAPHIC_PINSHAPE::NONLOGIC ) /* NonLogic pin symbol */
839 {
840 const int deco_size = externalPinDecoSize( aPlotter->RenderSettings(), *this );
841 aPlotter->MoveTo( VECTOR2I( x1 - ( MapX1 + MapY1 ) * deco_size,
842 y1 - ( MapY1 - MapX1 ) * deco_size ) );
843 aPlotter->FinishTo( VECTOR2I( x1 + ( MapX1 + MapY1 ) * deco_size,
844 y1 + ( MapY1 - MapX1 ) * deco_size ) );
845 aPlotter->MoveTo( VECTOR2I( x1 - ( MapX1 - MapY1 ) * deco_size,
846 y1 - ( MapY1 + MapX1 ) * deco_size ) );
847 aPlotter->FinishTo( VECTOR2I( x1 + ( MapX1 - MapY1 ) * deco_size,
848 y1 + ( MapY1 + MapX1 ) * deco_size ) );
849 }
850
851 if( m_type == ELECTRICAL_PINTYPE::PT_NC ) // Draw a N.C. symbol
852 {
853 const int deco_size = TARGET_PIN_RADIUS;
854 const int ex1 = aPosition.x;
855 const int ey1 = aPosition.y;
856 aPlotter->MoveTo( VECTOR2I( ex1 - deco_size, ey1 - deco_size ) );
857 aPlotter->FinishTo( VECTOR2I( ex1 + deco_size, ey1 + deco_size ) );
858 aPlotter->MoveTo( VECTOR2I( ex1 + deco_size, ey1 - deco_size ) );
859 aPlotter->FinishTo( VECTOR2I( ex1 - deco_size, ey1 + deco_size ) );
860 }
861}
862
863
864void SCH_PIN::PlotPinTexts( PLOTTER *aPlotter, const VECTOR2I &aPinPos, PIN_ORIENTATION aPinOrient,
865 int aTextInside, bool aDrawPinNum, bool aDrawPinName,
866 bool aDimmed ) const
867{
868 RENDER_SETTINGS* settings = aPlotter->RenderSettings();
869 KIFONT::FONT* font = KIFONT::FONT::GetFont( settings->GetDefaultFont(), false, false );
870 wxString name = GetShownName();
871 wxString number = GetShownNumber();
872
873 // Apply stacked pin display formatting (reuse helper from pin_layout_cache)
874 if( aDrawPinNum && !number.IsEmpty() )
875 {
876 const KIFONT::METRICS& metrics = GetFontMetrics();
877 number = FormatStackedPinForDisplay( number, GetLength(), GetNumberTextSize(), font, metrics );
878 }
879
880 if( name.IsEmpty() || m_nameTextSize == 0 )
881 aDrawPinName = false;
882 if( number.IsEmpty() || m_numTextSize == 0 )
883 aDrawPinNum = false;
884 if( !aDrawPinNum && !aDrawPinName )
885 return;
886
887 int namePenWidth = settings->GetDefaultPenWidth();
888 int numPenWidth = settings->GetDefaultPenWidth();
889 int name_offset = schIUScale.MilsToIU( PIN_TEXT_MARGIN ) + namePenWidth;
890 int num_offset = schIUScale.MilsToIU( PIN_TEXT_MARGIN ) + numPenWidth;
891
892 COLOR4D nameColor = settings->GetLayerColor( LAYER_PINNAM );
893 COLOR4D numColor = settings->GetLayerColor( LAYER_PINNUM );
894 COLOR4D bg = settings->GetBackgroundColor();
895 if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
896 bg = COLOR4D::WHITE;
897 if( aDimmed )
898 {
899 nameColor.Desaturate();
900 numColor.Desaturate();
901 nameColor = nameColor.Mix( bg, 0.5f );
902 numColor = numColor.Mix( bg, 0.5f );
903 }
904
905 int x1 = aPinPos.x;
906 int y1 = aPinPos.y;
907 switch( aPinOrient )
908 {
909 case PIN_ORIENTATION::PIN_UP: y1 -= GetLength(); break;
910 case PIN_ORIENTATION::PIN_DOWN: y1 += GetLength(); break;
911 case PIN_ORIENTATION::PIN_LEFT: x1 -= GetLength(); break;
912 case PIN_ORIENTATION::PIN_RIGHT: x1 += GetLength(); break;
913 default: break;
914 }
915
916 auto plotSimpleText = [&]( int x, int y, const EDA_ANGLE& angle, GR_TEXT_H_ALIGN_T hJustify,
917 GR_TEXT_V_ALIGN_T vJustify, const wxString& txt, int size,
918 int penWidth, const COLOR4D& col )
919 {
920 TEXT_ATTRIBUTES attrs;
921 attrs.m_StrokeWidth = penWidth;
922 attrs.m_Angle = angle;
923 attrs.m_Size = VECTOR2I( size, size );
924 attrs.m_Halign = hJustify;
925 attrs.m_Valign = vJustify;
926 attrs.m_Multiline = false; // we'll manage multi-line manually
927 aPlotter->PlotText( VECTOR2I( x, y ), col, txt, attrs, font, GetFontMetrics() );
928 };
929
930 auto plotMultiLineWithBraces = [&]( int anchorX, int anchorY, bool vertical, bool /*numberBlock*/ )
931 {
932 // If not multi-line formatted, just plot single line centered.
933 if( !number.StartsWith( "[" ) || !number.EndsWith( "]" ) || !number.Contains( "\n" ) )
934 {
935 plotSimpleText( anchorX, anchorY, vertical ? ANGLE_VERTICAL : ANGLE_HORIZONTAL,
937 GetNumberTextSize(), numPenWidth, numColor );
938 return;
939 }
940
941 wxString content = number.Mid( 1, number.Length() - 2 );
942 wxArrayString lines;
943 wxStringSplit( content, lines, '\n' );
944
945 if( lines.size() <= 1 )
946 {
947 plotSimpleText( anchorX, anchorY, vertical ? ANGLE_VERTICAL : ANGLE_HORIZONTAL,
949 GetNumberTextSize(), numPenWidth, numColor );
950 return;
951 }
952
953 int textSize = GetNumberTextSize();
954 int lineSpacing = KiROUND( textSize * 1.3 );
955 const KIFONT::METRICS& metrics = GetFontMetrics();
956
957 // Measure line widths for brace spacing
958 int maxLineWidth = 0;
959 for( const wxString& rawLine : lines )
960 {
961 wxString trimmed = rawLine; trimmed.Trim(true).Trim(false);
962 VECTOR2I ext = font->StringBoundaryLimits( trimmed, VECTOR2D( textSize, textSize ),
963 GetPenSizeForNormal( textSize ), false, false, metrics );
964 if( ext.x > maxLineWidth )
965 maxLineWidth = ext.x;
966 }
967
968 // Determine starting position
969 int startX = anchorX;
970 int startY = anchorY;
971
972 if( vertical )
973 {
974 int totalWidth = ( (int) lines.size() - 1 ) * lineSpacing;
975 startX -= totalWidth;
976 }
977 else
978 {
979 int totalHeight = ( (int) lines.size() - 1 ) * lineSpacing;
980 startY -= totalHeight;
981 }
982
983 for( size_t i = 0; i < lines.size(); ++i )
984 {
985 wxString l = lines[i]; l.Trim( true ).Trim( false );
986 int lx = startX + ( vertical ? (int) i * lineSpacing : 0 );
987 int ly = startY + ( vertical ? 0 : (int) i * lineSpacing );
988 plotSimpleText( lx, ly, vertical ? ANGLE_VERTICAL : ANGLE_HORIZONTAL,
990 textSize, numPenWidth, numColor );
991 }
992
993 // Now draw braces emulating SCH_PAINTER brace geometry
994 auto plotBrace = [&]( const VECTOR2I& top, const VECTOR2I& bottom, bool leftOrTop, bool isVerticalText )
995 {
996 // Build 4 small segments approximating curly brace
997 VECTOR2I mid = ( top + bottom ) / 2;
998 int braceWidth = textSize / 3; // same scale as painter
999 VECTOR2I p1 = top;
1000 VECTOR2I p5 = bottom;
1001 VECTOR2I p2 = top;
1002 VECTOR2I p3 = mid;
1003 VECTOR2I p4 = bottom;
1004 int offset = leftOrTop ? -braceWidth : braceWidth;
1005
1006 if( isVerticalText )
1007 {
1008 // Text vertical => brace extends in Y (horizontal brace lines across X axis set)
1009 // For vertical orientation we offset Y for p2/p3/p4
1010 p2.y += offset / 2;
1011 p3.y += offset;
1012 p4.y += offset / 2;
1013 }
1014 else
1015 {
1016 // Horizontal text => brace extends in X
1017 p2.x += offset / 2;
1018 p3.x += offset;
1019 p4.x += offset / 2;
1020 }
1021
1022 aPlotter->MoveTo( p1 ); aPlotter->FinishTo( p2 );
1023 aPlotter->MoveTo( p2 ); aPlotter->FinishTo( p3 );
1024 aPlotter->MoveTo( p3 ); aPlotter->FinishTo( p4 );
1025 aPlotter->MoveTo( p4 ); aPlotter->FinishTo( p5 );
1026 };
1027
1028 aPlotter->SetCurrentLineWidth( numPenWidth );
1029 int braceWidth = textSize / 3;
1030 int extraHeight = textSize / 3; // extend beyond text block
1031
1032 if( vertical )
1033 {
1034 // Lines spaced horizontally, braces horizontal (above & below)
1035 int totalWidth = ( (int) lines.size() - 1 ) * lineSpacing;
1036 VECTOR2I braceStart( startX - 2 * extraHeight, anchorY );
1037 VECTOR2I braceEnd( startX + totalWidth + extraHeight, anchorY );
1038 int braceSpacing = maxLineWidth / 2 + braceWidth;
1039
1040 VECTOR2I topStart = braceStart; topStart.y -= braceSpacing;
1041 VECTOR2I topEnd = braceEnd; topEnd.y -= braceSpacing;
1042 VECTOR2I bottomStart = braceStart; bottomStart.y += braceSpacing;
1043 VECTOR2I bottomEnd = braceEnd; bottomEnd.y += braceSpacing;
1044
1045 plotBrace( topStart, topEnd, true, true ); // leftOrTop=true
1046 plotBrace( bottomStart, bottomEnd, false, true );
1047 }
1048 else
1049 {
1050 // Lines spaced vertically, braces vertical (left & right)
1051 int totalHeight = ( (int) lines.size() - 1 ) * lineSpacing;
1052 VECTOR2I braceStart( anchorX, startY - 2 * extraHeight );
1053 VECTOR2I braceEnd( anchorX, startY + totalHeight + extraHeight );
1054 int braceSpacing = maxLineWidth / 2 + braceWidth;
1055
1056 VECTOR2I leftTop = braceStart; leftTop.x -= braceSpacing;
1057 VECTOR2I leftBot = braceEnd; leftBot.x -= braceSpacing;
1058 VECTOR2I rightTop = braceStart; rightTop.x += braceSpacing;
1059 VECTOR2I rightBot = braceEnd; rightBot.x += braceSpacing;
1060
1061 plotBrace( leftTop, leftBot, true, false );
1062 plotBrace( rightTop, rightBot, false, false );
1063 }
1064 };
1065
1066 // Logic largely mirrors original single-line placement but calls multi-line path for numbers
1067 if( aTextInside )
1068 {
1069 if( ( aPinOrient == PIN_ORIENTATION::PIN_LEFT ) || ( aPinOrient == PIN_ORIENTATION::PIN_RIGHT ) )
1070 {
1071 if( aDrawPinName )
1072 {
1073 if( aPinOrient == PIN_ORIENTATION::PIN_RIGHT )
1074 plotSimpleText( x1 + aTextInside, y1, ANGLE_HORIZONTAL, GR_TEXT_H_ALIGN_LEFT,
1075 GR_TEXT_V_ALIGN_CENTER, name, GetNameTextSize(), namePenWidth, nameColor );
1076 else
1077 plotSimpleText( x1 - aTextInside, y1, ANGLE_HORIZONTAL, GR_TEXT_H_ALIGN_RIGHT,
1078 GR_TEXT_V_ALIGN_CENTER, name, GetNameTextSize(), namePenWidth, nameColor );
1079 }
1080 if( aDrawPinNum )
1081 plotMultiLineWithBraces( ( x1 + aPinPos.x ) / 2, y1 - num_offset, false, true );
1082 }
1083 else
1084 {
1085 if( aPinOrient == PIN_ORIENTATION::PIN_DOWN )
1086 {
1087 if( aDrawPinName )
1088 plotSimpleText( x1, y1 + aTextInside, ANGLE_VERTICAL, GR_TEXT_H_ALIGN_RIGHT,
1089 GR_TEXT_V_ALIGN_CENTER, name, GetNameTextSize(), namePenWidth, nameColor );
1090 if( aDrawPinNum )
1091 plotMultiLineWithBraces( x1 - num_offset, ( y1 + aPinPos.y ) / 2, true, true );
1092 }
1093 else // PIN_UP
1094 {
1095 if( aDrawPinName )
1096 plotSimpleText( x1, y1 - aTextInside, ANGLE_VERTICAL, GR_TEXT_H_ALIGN_LEFT,
1097 GR_TEXT_V_ALIGN_CENTER, name, GetNameTextSize(), namePenWidth, nameColor );
1098 if( aDrawPinNum )
1099 plotMultiLineWithBraces( x1 - num_offset, ( y1 + aPinPos.y ) / 2, true, true );
1100 }
1101 }
1102 }
1103 else
1104 {
1105 if( ( aPinOrient == PIN_ORIENTATION::PIN_LEFT ) || ( aPinOrient == PIN_ORIENTATION::PIN_RIGHT ) )
1106 {
1107 if( aDrawPinName && aDrawPinNum )
1108 {
1109 plotSimpleText( ( x1 + aPinPos.x ) / 2, y1 - name_offset, ANGLE_HORIZONTAL,
1111 GetNameTextSize(), namePenWidth, nameColor );
1112 plotMultiLineWithBraces( ( x1 + aPinPos.x ) / 2, y1 + num_offset, false, true );
1113 }
1114 else if( aDrawPinName )
1115 {
1116 plotSimpleText( ( x1 + aPinPos.x ) / 2, y1 - name_offset, ANGLE_HORIZONTAL,
1118 GetNameTextSize(), namePenWidth, nameColor );
1119 }
1120 else if( aDrawPinNum )
1121 {
1122 plotMultiLineWithBraces( ( x1 + aPinPos.x ) / 2, y1 - name_offset, false, true );
1123 }
1124 }
1125 else
1126 {
1127 if( aDrawPinName && aDrawPinNum )
1128 {
1129 plotSimpleText( x1 - name_offset, ( y1 + aPinPos.y ) / 2, ANGLE_VERTICAL,
1131 GetNameTextSize(), namePenWidth, nameColor );
1132 plotMultiLineWithBraces( x1 + num_offset, ( y1 + aPinPos.y ) / 2, true, true );
1133 }
1134 else if( aDrawPinName )
1135 {
1136 plotSimpleText( x1 - name_offset, ( y1 + aPinPos.y ) / 2, ANGLE_VERTICAL,
1138 GetNameTextSize(), namePenWidth, nameColor );
1139 }
1140 else if( aDrawPinNum )
1141 {
1142 plotMultiLineWithBraces( x1 - num_offset, ( y1 + aPinPos.y ) / 2, true, true );
1143 }
1144 }
1145 }
1146}
1147
1148
1150{
1151 PIN_ORIENTATION orient;
1152 VECTOR2I end; // position of pin end starting at 0,0 according to its orientation, length = 1
1153
1154 switch( GetOrientation() )
1155 {
1156 default:
1157 case PIN_ORIENTATION::PIN_RIGHT: end.x = 1; break;
1158 case PIN_ORIENTATION::PIN_UP: end.y = -1; break;
1159 case PIN_ORIENTATION::PIN_DOWN: end.y = 1; break;
1160 case PIN_ORIENTATION::PIN_LEFT: end.x = -1; break;
1161 }
1162
1163 // = pos of end point, according to the symbol orientation.
1164 end = aTransform.TransformCoordinate( end );
1165 orient = PIN_ORIENTATION::PIN_UP;
1166
1167 if( end.x == 0 )
1168 {
1169 if( end.y > 0 )
1171 }
1172 else
1173 {
1175
1176 if( end.x < 0 )
1178 }
1179
1180 return orient;
1181}
1182
1183
1185{
1186 //return new SCH_PIN( *this );
1187 SCH_ITEM* newPin = new SCH_PIN( *this );
1188 wxASSERT( newPin->GetUnit() == m_unit && newPin->GetBodyStyle() == m_bodyStyle );
1189 return newPin;
1190}
1191
1192
1193void SCH_PIN::ChangeLength( int aLength )
1194{
1195 int lengthChange = GetLength() - aLength;
1196 int offsetX = 0;
1197 int offsetY = 0;
1198
1199 switch( m_orientation )
1200 {
1201 default:
1203 offsetX = lengthChange;
1204 break;
1206 offsetX = -1 * lengthChange;
1207 break;
1209 offsetY = -1 * lengthChange;
1210 break;
1212 offsetY = lengthChange;
1213 break;
1214 }
1215
1216 m_position += VECTOR2I( offsetX, offsetY );
1217 m_length = aLength;
1218}
1219
1220
1221void SCH_PIN::Move( const VECTOR2I& aOffset )
1222{
1223 m_position += aOffset;
1224}
1225
1226
1228{
1229 m_position.x -= aCenter;
1230 m_position.x *= -1;
1231 m_position.x += aCenter;
1232
1237}
1238
1239
1241{
1242 if( dynamic_cast<LIB_SYMBOL*>( GetParentSymbol() ) )
1243 MirrorHorizontallyPin( aCenter );
1244}
1245
1246
1248{
1249 m_position.y -= aCenter;
1250 m_position.y *= -1;
1251 m_position.y += aCenter;
1252
1257}
1258
1259
1260void SCH_PIN::MirrorVertically( int aCenter )
1261{
1262 if( dynamic_cast<LIB_SYMBOL*>( GetParentSymbol() ) )
1263 MirrorVerticallyPin( aCenter );
1264}
1265
1266
1267void SCH_PIN::RotatePin( const VECTOR2I& aCenter, bool aRotateCCW )
1268{
1269 if( aRotateCCW )
1270 {
1271 RotatePoint( m_position, aCenter, ANGLE_90 );
1272
1273 switch( GetOrientation() )
1274 {
1275 default:
1280 }
1281 }
1282 else
1283 {
1284 RotatePoint( m_position, aCenter, -ANGLE_90 );
1285
1286 switch( GetOrientation() )
1287 {
1288 default:
1293 }
1294 }
1295}
1296
1297
1298void SCH_PIN::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
1299{
1300 if( dynamic_cast<LIB_SYMBOL*>( GetParentSymbol() ) )
1301 RotatePin( aCenter, aRotateCCW );
1302}
1303
1304
1305void SCH_PIN::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
1306 int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
1307{
1308 if( aBackground )
1309 return;
1310
1311 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
1312
1313 if( !IsVisible() && !renderSettings->m_ShowHiddenPins )
1314 return;
1315
1316 const SYMBOL* part = GetParentSymbol();
1317 PIN_ORIENTATION orient = PinDrawOrient( renderSettings->m_Transform );
1318 VECTOR2I pos = renderSettings->TransformCoordinate( m_position ) + aOffset;
1319
1320 PlotPinType( aPlotter, pos, orient, aDimmed );
1321 PlotPinTexts( aPlotter, pos, orient, part->GetPinNameOffset(), part->GetShowPinNumbers(),
1322 part->GetShowPinNames(), aDimmed );
1323}
1324
1325
1326void SCH_PIN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1327{
1328 wxString msg;
1329 SYMBOL* symbol = GetParentSymbol();
1330
1331 aList.emplace_back( _( "Type" ), _( "Pin" ) );
1332
1333 SCH_ITEM::GetMsgPanelInfo( aFrame, aList );
1334
1335 aList.emplace_back( _( "Name" ), UnescapeString( GetShownName() ) );
1336 aList.emplace_back( _( "Number" ), GetShownNumber() );
1337 aList.emplace_back( _( "Type" ), ElectricalPinTypeGetText( GetType() ) );
1338 aList.emplace_back( _( "Style" ), PinShapeGetText( GetShape() ) );
1339
1340 aList.emplace_back( _( "Visible" ), IsVisible() ? _( "Yes" ) : _( "No" ) );
1341
1342 // Display pin length
1343 aList.emplace_back( _( "Length" ), aFrame->MessageTextFromValue( GetLength(), true ) );
1344
1345 aList.emplace_back( _( "Orientation" ), PinOrientationName( GetOrientation() ) );
1346
1347 if( dynamic_cast<LIB_SYMBOL*>( symbol ) )
1348 {
1349 aList.emplace_back( _( "Pos X" ), aFrame->MessageTextFromValue( GetPosition().x, true ) );
1350 aList.emplace_back( _( "Pos Y" ), aFrame->MessageTextFromValue( GetPosition().y, true ) );
1351 }
1352 else if( SCH_SYMBOL* schsymbol = dynamic_cast<SCH_SYMBOL*>( symbol ) )
1353 {
1354 SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( aFrame );
1355 SCH_SHEET_PATH* currentSheet = schframe ? &schframe->GetCurrentSheet() : nullptr;
1356
1357 // Don't use GetShownText(); we want to see the variable references here
1358 aList.emplace_back( symbol->GetRef( currentSheet ),
1359 UnescapeString( schsymbol->GetField( FIELD_T::VALUE )->GetText() ) );
1360 }
1361
1362#if defined(DEBUG)
1363 if( !IsConnectivityDirty() && dynamic_cast<SCH_EDIT_FRAME*>( aFrame ) )
1364 {
1365 SCH_CONNECTION* conn = Connection();
1366
1367 if( conn )
1368 conn->AppendInfoToMsgPanel( aList );
1369 }
1370#endif
1371}
1372
1373
1375{
1376 std::lock_guard<std::recursive_mutex> lock( m_netmap_mutex );
1377
1378 if( aPath )
1379 m_net_name_map.erase( *aPath );
1380 else
1381 m_net_name_map.clear();
1382}
1383
1384
1385wxString SCH_PIN::GetDefaultNetName( const SCH_SHEET_PATH& aPath, bool aForceNoConnect )
1386{
1387 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( GetParentSymbol() );
1388
1389 // Need to check for parent as power symbol to make sure we aren't dealing
1390 // with legacy global power pins on non-power symbols
1391 if( IsGlobalPower() || IsLocalPower() )
1392 {
1393 SYMBOL* parent = GetLibPin()->GetParentSymbol();
1394
1395 if( parent->IsGlobalPower() || parent->IsLocalPower() )
1396 {
1397 return EscapeString( symbol->GetValue( true, &aPath, false ), CTX_NETNAME );
1398 }
1399 else
1400 {
1401 wxString tmp = m_libPin ? m_libPin->GetName() : wxString( "??" );
1402
1403 return EscapeString( tmp, CTX_NETNAME );
1404 }
1405 }
1406
1407 std::lock_guard<std::recursive_mutex> lock( m_netmap_mutex );
1408
1409 auto it = m_net_name_map.find( aPath );
1410
1411 if( it != m_net_name_map.end() )
1412 {
1413 if( it->second.second == aForceNoConnect )
1414 return it->second.first;
1415 }
1416
1417 wxString name = "Net-(";
1418 bool unconnected = false;
1419
1420 if( aForceNoConnect || GetType() == ELECTRICAL_PINTYPE::PT_NC )
1421 {
1422 unconnected = true;
1423 name = ( "unconnected-(" );
1424 }
1425
1426 bool annotated = true;
1427
1428 std::vector<SCH_PIN*> pins = symbol->GetPins( &aPath );
1429 bool has_multiple = false;
1430
1431 for( SCH_PIN* pin : pins )
1432 {
1433 if( pin->GetShownName() == GetShownName()
1434 && pin->GetShownNumber() != GetShownNumber()
1435 && unconnected == ( pin->GetType() == ELECTRICAL_PINTYPE::PT_NC ) )
1436 {
1437 has_multiple = true;
1438 break;
1439 }
1440 }
1441
1442 wxString libPinShownName = m_libPin ? m_libPin->GetShownName() : wxString( "??" );
1443 wxString libPinShownNumber = m_libPin ? m_libPin->GetShownNumber() : wxString( "??" );
1444 wxString effectivePadNumber = m_libPin ? m_libPin->GetEffectivePadNumber() : libPinShownNumber;
1445
1446 if( effectivePadNumber != libPinShownNumber )
1447 {
1448 wxLogTrace( "KICAD_STACKED_PINS",
1449 wxString::Format( "GetDefaultNetName: stacked pin shown='%s' -> using smallest logical='%s'",
1450 libPinShownNumber, effectivePadNumber ) );
1451 }
1452
1453 // Use timestamp for unannotated symbols
1454 if( symbol->GetRef( &aPath, false ).Last() == '?' )
1455 {
1457
1458 wxString libPinNumber = m_libPin ? m_libPin->GetNumber() : wxString( "??" );
1459 // Apply same smallest-logical substitution for unannotated symbols
1460 if( effectivePadNumber != libPinShownNumber && !effectivePadNumber.IsEmpty() )
1461 libPinNumber = effectivePadNumber;
1462
1463 name << "-Pad" << libPinNumber << ")";
1464 annotated = false;
1465 }
1466 else if( !libPinShownName.IsEmpty() && ( libPinShownName != libPinShownNumber ) )
1467 {
1468 // Pin names might not be unique between different units so we must have the
1469 // unit token in the reference designator
1470 name << symbol->GetRef( &aPath, true );
1471 name << "-" << EscapeString( libPinShownName, CTX_NETNAME );
1472
1473 if( unconnected || has_multiple )
1474 {
1475 // Use effective (possibly de-stacked) pad number in net name
1476 name << "-Pad" << EscapeString( effectivePadNumber, CTX_NETNAME );
1477 }
1478
1479 name << ")";
1480 }
1481 else
1482 {
1483 // Pin numbers are unique, so we skip the unit token
1484 name << symbol->GetRef( &aPath, false );
1485 name << "-Pad" << EscapeString( effectivePadNumber, CTX_NETNAME ) << ")";
1486 }
1487
1488 if( annotated )
1489 m_net_name_map[ aPath ] = std::make_pair( name, aForceNoConnect );
1490
1491 return name;
1492}
1493
1494
1496{
1497 return GetBoundingBox( false, true, m_flags & SHOW_ELEC_TYPE );
1498}
1499
1500
1506
1507
1508void SCH_PIN::validateExtentsCache( KIFONT::FONT* aFont, int aSize, const wxString& aText,
1509 EXTENTS_CACHE* aCache ) const
1510{
1511 if( aCache->m_Font == aFont
1512 && aCache->m_FontSize == aSize
1513 && aCache->m_Extents != VECTOR2I() )
1514 {
1515 return;
1516 }
1517
1518 aCache->m_Font = aFont;
1519 aCache->m_FontSize = aSize;
1520
1521 VECTOR2D fontSize( aSize, aSize );
1522 int penWidth = GetPenSizeForNormal( aSize );
1523
1524 aCache->m_Extents = aFont->StringBoundaryLimits( aText, fontSize, penWidth, false, false,
1525 GetFontMetrics() );
1526}
1527
1528
1529BOX2I SCH_PIN::GetBoundingBox( bool aIncludeLabelsOnInvisiblePins, bool aIncludeNameAndNumber,
1530 bool aIncludeElectricalType ) const
1531{
1532 // Just defer to the cache
1533 return m_layoutCache->GetPinBoundingBox( aIncludeLabelsOnInvisiblePins, aIncludeNameAndNumber,
1534 aIncludeElectricalType );
1535}
1536
1537
1539 const SCH_SHEET_PATH* aInstance ) const
1540{
1541 // Do not compare to ourself.
1542 if( aItem == this )
1543 return false;
1544
1545 const SCH_PIN* pin = dynamic_cast<const SCH_PIN*>( aItem );
1546
1547 // Don't compare against a different SCH_ITEM.
1548 wxCHECK( pin, false );
1549
1550 if( GetPosition() != pin->GetPosition() )
1551 return true;
1552
1553 if( GetNumber() != pin->GetNumber() )
1554 return true;
1555
1556 return GetName() != pin->GetName();
1557}
1558
1559
1561{
1562 if( !m_libPin )
1563 return false;
1564
1565 // Reciprocal checking is done in CONNECTION_GRAPH anyway
1566 return m_libPin->GetType() != ELECTRICAL_PINTYPE::PT_NC;
1567}
1568
1569
1571{
1572 if( m_libPin )
1573 return m_libPin->GetMenuImage();
1574
1576}
1577
1578
1579wxString SCH_PIN::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, ALT* aAlt ) const
1580{
1581 return getItemDescription( aAlt );
1582}
1583
1584
1585wxString SCH_PIN::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1586{
1587 if( m_libPin )
1588 {
1589 SCH_PIN::ALT localStorage;
1590 SCH_PIN::ALT* alt = nullptr;
1591
1592 if( !m_alt.IsEmpty() )
1593 {
1594 localStorage = m_libPin->GetAlt( m_alt );
1595 alt = &localStorage;
1596 }
1597
1598 wxString itemDesc = m_libPin ? m_libPin->GetItemDescription( aUnitsProvider, alt )
1599 : wxString( wxS( "Undefined library pin." ) );
1600
1601 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( GetParentSymbol() );
1602
1603 return wxString::Format( "Symbol %s %s",
1605 itemDesc );
1606 }
1607
1608 return getItemDescription( nullptr );
1609}
1610
1611
1612wxString SCH_PIN::getItemDescription( ALT* aAlt ) const
1613{
1614 wxString name = UnescapeString( aAlt ? aAlt->m_Name : GetShownName() );
1615 wxString electricalTypeName = ElectricalPinTypeGetText( aAlt ? aAlt->m_Type : m_type );
1616 wxString pinShapeName = PinShapeGetText( aAlt ? aAlt->m_Shape : m_shape );
1617
1618 if( IsVisible() )
1619 {
1620 if ( !name.IsEmpty() )
1621 {
1622 return wxString::Format( _( "Pin %s [%s, %s, %s]" ),
1624 name,
1625 electricalTypeName,
1626 pinShapeName );
1627 }
1628 else
1629 {
1630 return wxString::Format( _( "Pin %s [%s, %s]" ),
1632 electricalTypeName,
1633 pinShapeName );
1634 }
1635 }
1636 else
1637 {
1638 if( !name.IsEmpty() )
1639 {
1640 return wxString::Format( _( "Hidden pin %s [%s, %s, %s]" ),
1642 name,
1643 electricalTypeName,
1644 pinShapeName );
1645 }
1646 else
1647 {
1648 return wxString::Format( _( "Hidden pin %s [%s, %s]" ),
1650 electricalTypeName,
1651 pinShapeName );
1652 }
1653 }
1654}
1655
1656
1657int SCH_PIN::compare( const SCH_ITEM& aOther, int aCompareFlags ) const
1658{
1659 // Ignore the UUID here
1660 // And the position, which we'll do after the number.
1661 int retv = SCH_ITEM::compare( aOther, aCompareFlags | SCH_ITEM::COMPARE_FLAGS::EQUALITY
1663
1664 if( retv )
1665 return retv;
1666
1667 const SCH_PIN* tmp = static_cast<const SCH_PIN*>( &aOther );
1668
1669 wxCHECK( tmp, -1 );
1670
1671 if( m_number != tmp->m_number )
1672 {
1673 // StrNumCmp: sort the same as the pads in the footprint file
1674 return StrNumCmp( m_number, tmp->m_number ) < 0;
1675 }
1676
1677 if( m_position.x != tmp->m_position.x )
1678 return m_position.x - tmp->m_position.x;
1679
1680 if( m_position.y != tmp->m_position.y )
1681 return m_position.y - tmp->m_position.y;
1682
1683 if( dynamic_cast<const SCH_SYMBOL*>( GetParentSymbol() ) )
1684 {
1685 if( ( m_libPin == nullptr ) || ( tmp->m_libPin == nullptr ) )
1686 return -1;
1687
1688 retv = m_libPin->compare( *tmp->m_libPin );
1689
1690 if( retv )
1691 return retv;
1692
1693 retv = m_alt.Cmp( tmp->m_alt );
1694
1695 if( retv )
1696 return retv;
1697 }
1698
1699 if( dynamic_cast<const LIB_SYMBOL*>( GetParentSymbol() ) )
1700 {
1701 if( m_length != tmp->m_length )
1702 return m_length.value_or( 0 ) - tmp->m_length.value_or( 0 );
1703
1704 if( m_orientation != tmp->m_orientation )
1705 return static_cast<int>( m_orientation ) - static_cast<int>( tmp->m_orientation );
1706
1707 if( m_shape != tmp->m_shape )
1708 return static_cast<int>( m_shape ) - static_cast<int>( tmp->m_shape );
1709
1710 if( m_type != tmp->m_type )
1711 return static_cast<int>( m_type ) - static_cast<int>( tmp->m_type );
1712
1713 if( m_hidden != tmp->m_hidden )
1714 return m_hidden.value_or( false ) - tmp->m_hidden.value_or( false );
1715
1716 if( m_numTextSize != tmp->m_numTextSize )
1717 return m_numTextSize.value_or( 0 ) - tmp->m_numTextSize.value_or( 0 );
1718
1719 if( m_nameTextSize != tmp->m_nameTextSize )
1720 return m_nameTextSize.value_or( 0 ) - tmp->m_nameTextSize.value_or( 0 );
1721
1722 if( m_alternates.size() != tmp->m_alternates.size() )
1723 return static_cast<int>( m_alternates.size() - tmp->m_alternates.size() );
1724
1725 auto lhsItem = m_alternates.begin();
1726 auto rhsItem = tmp->m_alternates.begin();
1727
1728 while( lhsItem != m_alternates.end() )
1729 {
1730 const ALT& lhsAlt = lhsItem->second;
1731 const ALT& rhsAlt = rhsItem->second;
1732
1733 retv = lhsAlt.m_Name.Cmp( rhsAlt.m_Name );
1734
1735 if( retv )
1736 return retv;
1737
1738 if( lhsAlt.m_Type != rhsAlt.m_Type )
1739 return static_cast<int>( lhsAlt.m_Type ) - static_cast<int>( rhsAlt.m_Type );
1740
1741 if( lhsAlt.m_Shape != rhsAlt.m_Shape )
1742 return static_cast<int>( lhsAlt.m_Shape ) - static_cast<int>( rhsAlt.m_Shape );
1743
1744 ++lhsItem;
1745 ++rhsItem;
1746 }
1747 }
1748
1749 return 0;
1750}
1751
1752
1753double SCH_PIN::Similarity( const SCH_ITEM& aOther ) const
1754{
1755 if( aOther.m_Uuid == m_Uuid )
1756 return 1.0;
1757
1758 if( aOther.Type() != SCH_PIN_T )
1759 return 0.0;
1760
1761 const SCH_PIN* other = static_cast<const SCH_PIN*>( &aOther );
1762
1763 if( m_libPin )
1764 {
1765 if( m_number != other->m_number )
1766 return 0.0;
1767
1768 if( m_position != other->m_position )
1769 return 0.0;
1770
1771 return m_libPin->Similarity( *other->m_libPin );
1772 }
1773
1774 double similarity = SimilarityBase( aOther );
1775
1776 if( m_name != other->m_name )
1777 similarity *= 0.9;
1778
1779 if( m_number != other->m_number )
1780 similarity *= 0.9;
1781
1782 if( m_position != other->m_position )
1783 similarity *= 0.9;
1784
1785 if( m_length != other->m_length )
1786 similarity *= 0.9;
1787
1788 if( m_orientation != other->m_orientation )
1789 similarity *= 0.9;
1790
1791 if( m_shape != other->m_shape )
1792 similarity *= 0.9;
1793
1794 if( m_type != other->m_type )
1795 similarity *= 0.9;
1796
1797 if( m_hidden != other->m_hidden )
1798 similarity *= 0.9;
1799
1800 if( m_numTextSize != other->m_numTextSize )
1801 similarity *= 0.9;
1802
1803 if( m_nameTextSize != other->m_nameTextSize )
1804 similarity *= 0.9;
1805
1806 if( m_alternates.size() != other->m_alternates.size() )
1807 similarity *= 0.9;
1808
1809 return similarity;
1810}
1811
1812
1813std::ostream& SCH_PIN::operator<<( std::ostream& aStream )
1814{
1815 aStream << "SCH_PIN:" << std::endl
1816 << " Name: \"" << m_name << "\"" << std::endl
1817 << " Number: \"" << m_number << "\"" << std::endl
1818 << " Position: " << m_position << std::endl
1819 << " Length: " << GetLength() << std::endl
1820 << " Orientation: " << PinOrientationName( m_orientation ) << std::endl
1821 << " Shape: " << PinShapeGetText( m_shape ) << std::endl
1822 << " Type: " << ElectricalPinTypeGetText( m_type ) << std::endl
1823 << " Name Text Size: " << GetNameTextSize() << std::endl
1824 << " Number Text Size: " << GetNumberTextSize() << std::endl;
1825
1826 return aStream;
1827}
1828
1829
1830#if defined(DEBUG)
1831
1832void SCH_PIN::Show( int nestLevel, std::ostream& os ) const
1833{
1834 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str()
1835 << " num=\"" << m_number.mb_str()
1836 << '"' << "/>\n";
1837}
1838
1839#endif
1840
1841
1842void SCH_PIN::CalcEdit( const VECTOR2I& aPosition )
1843{
1844 if( IsMoving() )
1845 SetPosition( aPosition );
1846}
1847
1848
1849static struct SCH_PIN_DESC
1850{
1852 {
1853 auto& pinTypeEnum = ENUM_MAP<ELECTRICAL_PINTYPE>::Instance();
1854
1855 if( pinTypeEnum.Choices().GetCount() == 0 )
1856 {
1857 pinTypeEnum.Map( ELECTRICAL_PINTYPE::PT_INPUT, _HKI( "Input" ) )
1858 .Map( ELECTRICAL_PINTYPE::PT_OUTPUT, _HKI( "Output" ) )
1859 .Map( ELECTRICAL_PINTYPE::PT_BIDI, _HKI( "Bidirectional" ) )
1860 .Map( ELECTRICAL_PINTYPE::PT_TRISTATE, _HKI( "Tri-state" ) )
1861 .Map( ELECTRICAL_PINTYPE::PT_PASSIVE, _HKI( "Passive" ) )
1862 .Map( ELECTRICAL_PINTYPE::PT_NIC, _HKI( "Free" ) )
1863 .Map( ELECTRICAL_PINTYPE::PT_UNSPECIFIED, _HKI( "Unspecified" ) )
1864 .Map( ELECTRICAL_PINTYPE::PT_POWER_IN, _HKI( "Power input" ) )
1865 .Map( ELECTRICAL_PINTYPE::PT_POWER_OUT, _HKI( "Power output" ) )
1866 .Map( ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR, _HKI( "Open collector" ) )
1867 .Map( ELECTRICAL_PINTYPE::PT_OPENEMITTER, _HKI( "Open emitter" ) )
1868 .Map( ELECTRICAL_PINTYPE::PT_NC, _HKI( "Unconnected" ) );
1869 }
1870
1871 auto& pinShapeEnum = ENUM_MAP<GRAPHIC_PINSHAPE>::Instance();
1872
1873 if( pinShapeEnum.Choices().GetCount() == 0 )
1874 {
1875 pinShapeEnum.Map( GRAPHIC_PINSHAPE::LINE, _HKI( "Line" ) )
1876 .Map( GRAPHIC_PINSHAPE::INVERTED, _HKI( "Inverted" ) )
1877 .Map( GRAPHIC_PINSHAPE::CLOCK, _HKI( "Clock" ) )
1878 .Map( GRAPHIC_PINSHAPE::INVERTED_CLOCK, _HKI( "Inverted clock" ) )
1879 .Map( GRAPHIC_PINSHAPE::INPUT_LOW, _HKI( "Input low" ) )
1880 .Map( GRAPHIC_PINSHAPE::CLOCK_LOW, _HKI( "Clock low" ) )
1881 .Map( GRAPHIC_PINSHAPE::OUTPUT_LOW, _HKI( "Output low" ) )
1882 .Map( GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK, _HKI( "Falling edge clock" ) )
1883 .Map( GRAPHIC_PINSHAPE::NONLOGIC, _HKI( "NonLogic" ) );
1884 }
1885
1886 auto& orientationEnum = ENUM_MAP<PIN_ORIENTATION>::Instance();
1887
1888 if( orientationEnum.Choices().GetCount() == 0 )
1889 {
1890 orientationEnum.Map( PIN_ORIENTATION::PIN_RIGHT, _( "Right" ) )
1891 .Map( PIN_ORIENTATION::PIN_LEFT, _( "Left" ) )
1892 .Map( PIN_ORIENTATION::PIN_UP, _( "Up" ) )
1893 .Map( PIN_ORIENTATION::PIN_DOWN, _( "Down" ) );
1894 }
1895
1896 auto isSymbolEditor =
1897 []( INSPECTABLE* aItem ) -> bool
1898 {
1899 if( SCH_PIN* pin = dynamic_cast<SCH_PIN*>( aItem ) )
1900 return dynamic_cast<LIB_SYMBOL*>( pin->GetParentSymbol() ) != nullptr;
1901
1902 return false;
1903 };
1904
1909
1910 propMgr.AddProperty( new PROPERTY<SCH_PIN, wxString>( _HKI( "Pin Name" ),
1912 .SetWriteableFunc( isSymbolEditor );
1913
1914 propMgr.AddProperty( new PROPERTY<SCH_PIN, wxString>( _HKI( "Pin Number" ),
1916 .SetWriteableFunc( isSymbolEditor );
1917
1918 propMgr.AddProperty( new PROPERTY_ENUM<SCH_PIN, ELECTRICAL_PINTYPE>( _HKI( "Electrical Type" ),
1920 .SetWriteableFunc( isSymbolEditor );
1921
1922 propMgr.AddProperty( new PROPERTY_ENUM<SCH_PIN, GRAPHIC_PINSHAPE>( _HKI( "Graphic Style" ),
1924 .SetWriteableFunc( isSymbolEditor );
1925
1926 propMgr.AddProperty( new PROPERTY<SCH_PIN, int>( _HKI( "Position X" ),
1928 .SetAvailableFunc( isSymbolEditor );
1929
1930 propMgr.AddProperty( new PROPERTY<SCH_PIN, int>( _HKI( "Position Y" ),
1932 .SetAvailableFunc( isSymbolEditor );
1933
1934 propMgr.AddProperty( new PROPERTY_ENUM<SCH_PIN, PIN_ORIENTATION>( _HKI( "Orientation" ),
1936 .SetWriteableFunc( isSymbolEditor );
1937
1938 propMgr.AddProperty( new PROPERTY<SCH_PIN, int>( _HKI( "Length" ),
1941 .SetWriteableFunc( isSymbolEditor );
1942
1943 propMgr.AddProperty( new PROPERTY<SCH_PIN, int>( _HKI( "Name Text Size" ),
1946 .SetAvailableFunc( isSymbolEditor );
1947
1948 propMgr.AddProperty( new PROPERTY<SCH_PIN, int>( _HKI( "Number Text Size" ),
1951 .SetAvailableFunc( isSymbolEditor );
1952
1953 propMgr.AddProperty( new PROPERTY<SCH_PIN, bool>( _HKI( "Visible" ),
1955 .SetAvailableFunc( isSymbolEditor );
1956
1957 }
1959
1960
int color
const char * name
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:114
BITMAPS
A list of all bitmap identifiers.
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:558
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:168
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition box2.h:311
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:516
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
EDA_ITEM_FLAGS m_flags
Definition eda_item.h:527
virtual bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const
Compare the item against the search criteria in aSearchData.
Definition eda_item.h:401
EDA_ITEM * GetParent() const
Definition eda_item.h:112
EDA_ITEM * m_parent
Owner.
Definition eda_item.h:528
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:236
bool IsMoving() const
Definition eda_item.h:125
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:39
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:97
static ENUM_MAP< T > & Instance()
Definition property.h:699
Class that other classes need to inherit from, in order to be inspectable.
Definition inspectable.h:37
FONT is an abstract base class for both outline and stroke fonts.
Definition font.h:131
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:147
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:427
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:104
COLOR4D & Desaturate()
Removes color (in HSL model)
Definition color4d.cpp:511
COLOR4D Mix(const COLOR4D &aColor, double aFactor) const
Return a color that is mixed with the input by a factor.
Definition color4d.h:295
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:49
wxString AsString() const
Definition kiid.cpp:246
Define a library symbol object.
Definition lib_symbol.h:85
Definition line.h:36
A pin layout helper is a class that manages the layout of the parts of a pin on a schematic symbol:
Base plotter engine class.
Definition plotter.h:121
virtual void Circle(const VECTOR2I &pos, int diametre, FILL_T fill, int width)=0
void MoveTo(const VECTOR2I &pos)
Definition plotter.h:262
void FinishTo(const VECTOR2I &pos)
Definition plotter.h:272
RENDER_SETTINGS * RenderSettings()
Definition plotter.h:152
bool GetColorMode() const
Definition plotter.h:149
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:267
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:695
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:259
PROPERTY_BASE & SetWriteableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Definition property.h:284
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.
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
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:167
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:637
int m_unit
Definition sch_item.h:740
SCH_ITEM & operator=(const SCH_ITEM &aPin)
Definition sch_item.cpp:75
int m_bodyStyle
Definition sch_item.h:741
SCH_RENDER_SETTINGS * getRenderSettings(PLOTTER *aPlotter) const
Definition sch_item.h:688
const SYMBOL * GetParentSymbol() const
Definition sch_item.cpp:223
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:217
int GetBodyStyle() const
Definition sch_item.h:244
friend class LIB_SYMBOL
Definition sch_item.h:759
@ SKIP_TST_POS
Definition sch_item.h:671
int GetUnit() const
Definition sch_item.h:238
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:541
bool IsConnectivityDirty() const
Definition sch_item.h:554
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:51
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:323
const KIFONT::METRICS & GetFontMetrics() const
Definition sch_item.cpp:593
int GetEffectivePenWidth(const SCH_RENDER_SETTINGS *aSettings) const
Definition sch_item.cpp:602
SCH_LAYER_ID m_layer
Definition sch_item.h:739
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:346
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW=true) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
Definition sch_pin.cpp:1298
std::ostream & operator<<(std::ostream &aStream)
Definition sch_pin.cpp:1813
void SetAlt(const wxString &aAlt)
Set the name of the alternate pin.
Definition sch_pin.cpp:432
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:864
int GetNumberTextSize() const
Definition sch_pin.cpp:670
int GetLength() const
Definition sch_pin.cpp:298
std::optional< bool > m_hidden
Definition sch_pin.h:386
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition sch_pin.cpp:498
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:1326
std::unique_ptr< PIN_LAYOUT_CACHE > m_layoutCache
The layout cache for this pin.
Definition sch_pin.h:402
void MirrorVerticallyPin(int aCenter)
Definition sch_pin.cpp:1247
void validateExtentsCache(KIFONT::FONT *aFont, int aSize, const wxString &aText, EXTENTS_CACHE *aCache) const
Definition sch_pin.cpp:1508
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition sch_pin.cpp:1495
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:1501
void CalcEdit(const VECTOR2I &aPosition) override
Calculate the attributes of an item at aPosition when it is being edited.
Definition sch_pin.cpp:1842
void SetNumber(const wxString &aNumber)
Definition sch_pin.cpp:633
std::optional< int > m_nameTextSize
Definition sch_pin.h:390
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:1149
void SetVisible(bool aVisible)
Definition sch_pin.h:114
int GetX() const
Definition sch_pin.h:241
void ChangeLength(int aLength)
Change the length of a pin and adjust its position based on orientation.
Definition sch_pin.cpp:1193
void SetX(int aX)
Definition sch_pin.h:242
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:1538
SCH_PIN & operator=(const SCH_PIN &aPin)
Definition sch_pin.cpp:232
wxString GetShownNumber() const
Definition sch_pin.cpp:587
SCH_PIN * m_libPin
Definition sch_pin.h:375
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:612
void Move(const VECTOR2I &aOffset) override
Move the item by aMoveVector to a new position.
Definition sch_pin.cpp:1221
std::map< const SCH_SHEET_PATH, std::pair< wxString, bool > > m_net_name_map
Definition sch_pin.h:406
PIN_ORIENTATION m_orientation
Definition sch_pin.h:383
void SetOrientation(PIN_ORIENTATION aOrientation)
Definition sch_pin.h:93
void SetName(const wxString &aName)
Definition sch_pin.cpp:418
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:366
wxString getItemDescription(ALT *aAlt) const
Definition sch_pin.cpp:1612
bool IsVisible() const
Definition sch_pin.cpp:386
bool ConnectionPropagatesTo(const EDA_ITEM *aItem) const override
Return true if this item should propagate connection info to aItem.
Definition sch_pin.cpp:1560
std::optional< int > m_numTextSize
Definition sch_pin.h:389
VECTOR2I GetPinRoot() const
Definition sch_pin.cpp:694
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:373
ELECTRICAL_PINTYPE m_type
Definition sch_pin.h:385
wxString GetEffectivePadNumber() const
Return the pin number to be used for deterministic operations such as auto‑generated net names.
Definition sch_pin.cpp:624
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
Definition sch_pin.cpp:1260
SCH_PIN * GetLibPin() const
Definition sch_pin.h:89
void SetPosition(const VECTOR2I &aPos) override
Definition sch_pin.h:238
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:1753
bool m_isDangling
Definition sch_pin.h:395
void SetIsDangling(bool aIsDangling)
Definition sch_pin.cpp:469
wxString GetElectricalTypeName() const
Definition sch_pin.cpp:354
std::vector< wxString > GetStackedPinNumbers(bool *aValid=nullptr) const
Definition sch_pin.cpp:593
std::map< wxString, ALT > m_alternates
Definition sch_pin.h:378
const wxString & GetName() const
Definition sch_pin.cpp:400
bool IsDangling() const override
Definition sch_pin.cpp:460
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:1305
void MirrorHorizontally(int aCenter) override
These transforms have effect only if the pin has a LIB_SYMBOL as parent.
Definition sch_pin.cpp:1240
std::recursive_mutex m_netmap_mutex
The name that this pin connection will drive onto a net.
Definition sch_pin.h:405
PIN_ORIENTATION GetOrientation() const
Definition sch_pin.cpp:263
wxString GetClass() const override
Return the class name.
Definition sch_pin.h:74
void SetNumberTextSize(int aSize)
Definition sch_pin.cpp:684
void SetShape(GRAPHIC_PINSHAPE aShape)
Definition sch_pin.h:96
void RotatePin(const VECTOR2I &aCenter, bool aRotateCCW=true)
Definition sch_pin.cpp:1267
VECTOR2I GetPosition() const override
Definition sch_pin.cpp:255
wxString GetCanonicalElectricalTypeName() const
Definition sch_pin.cpp:342
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:525
int GetNameTextSize() const
Definition sch_pin.cpp:646
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
Definition sch_pin.cpp:1585
VECTOR2I m_position
Definition sch_pin.h:381
GRAPHIC_PINSHAPE m_shape
Definition sch_pin.h:384
int compare(const SCH_ITEM &aOther, int aCompareFlags=0) const override
The pin specific sort order is as follows:
Definition sch_pin.cpp:1657
wxString GetShownName() const
Definition sch_pin.cpp:576
void MirrorHorizontallyPin(int aCenter)
These transforms have always effects.
Definition sch_pin.cpp:1227
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:546
wxString m_name
Definition sch_pin.h:387
wxString m_alt
Definition sch_pin.h:391
void SetType(ELECTRICAL_PINTYPE aType)
Definition sch_pin.cpp:332
const wxString & GetBaseName() const
Get the name without any alternates.
Definition sch_pin.cpp:409
void ClearDefaultNetName(const SCH_SHEET_PATH *aPath)
Definition sch_pin.cpp:1374
void SetY(int aY)
Definition sch_pin.h:244
SCH_PIN(LIB_SYMBOL *aParentSymbol)
Definition sch_pin.cpp:117
bool IsStacked(const SCH_PIN *aPin) const
Definition sch_pin.cpp:475
const wxString & GetNumber() const
Definition sch_pin.h:124
wxString m_number
Definition sch_pin.h:388
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition sch_pin.cpp:1184
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition sch_pin.h:202
wxString GetDefaultNetName(const SCH_SHEET_PATH &aPath, bool aForceNoConnect=false)
Definition sch_pin.cpp:1385
std::optional< int > m_length
Definition sch_pin.h:382
GRAPHIC_PINSHAPE GetShape() const
Definition sch_pin.cpp:277
void PlotPinType(PLOTTER *aPlotter, const VECTOR2I &aPosition, PIN_ORIENTATION aOrientation, bool aDimmed) const
Definition sch_pin.cpp:717
int GetY() const
Definition sch_pin.h:243
bool IsPower() const
Check if the pin is either a global or local power pin.
Definition sch_pin.cpp:380
ELECTRICAL_PINTYPE GetType() const
Definition sch_pin.cpp:312
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition sch_pin.cpp:1570
void SetNameTextSize(int aSize)
Definition sch_pin.cpp:660
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
const wxString GetValue(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText) const override
std::vector< SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
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:63
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:158
virtual bool GetShowPinNames() const
Definition symbol.h:164
virtual bool GetShowPinNumbers() const
Definition symbol.h:170
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:46
VECTOR2I TransformCoordinate(const VECTOR2I &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition transform.cpp:44
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:57
int GetPenSizeForNormal(int aTextSize)
Definition gr_text.cpp:61
@ LAYER_DANGLING
Definition layer_ids.h:476
@ LAYER_PINNUM
Definition layer_ids.h:457
@ LAYER_DEVICE
Definition layer_ids.h:465
@ LAYER_PINNAM
Definition layer_ids.h:458
@ LAYER_PIN
Definition layer_ids.h:469
@ LAYER_OP_CURRENTS
Definition layer_ids.h:500
@ LAYER_SELECTION_SHADOWS
Definition layer_ids.h:493
STL namespace.
#define _HKI(x)
Definition page_info.cpp:44
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:42
wxString PinShapeGetText(GRAPHIC_PINSHAPE shape)
Definition pin_type.cpp:240
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
Definition pin_type.h:36
@ PT_INPUT
usual pin input: must be connected
Definition pin_type.h:37
@ PT_NC
not connected (must be left open)
Definition pin_type.h:50
@ PT_OUTPUT
usual output
Definition pin_type.h:38
@ PT_TRISTATE
tri state bus pin
Definition pin_type.h:40
@ PT_NIC
not internally connected (may be connected to anything)
Definition pin_type.h:44
@ PT_BIDI
input or output (like port for a microprocessor)
Definition pin_type.h:39
@ PT_OPENEMITTER
pin type open emitter
Definition pin_type.h:49
@ PT_POWER_OUT
output of a regulator: intended to be connected to power input pins
Definition pin_type.h:47
@ PT_OPENCOLLECTOR
pin type open collector
Definition pin_type.h:48
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
Definition pin_type.h:46
@ PT_UNSPECIFIED
unknown electrical properties: creates always a warning when connected
Definition pin_type.h:45
@ PT_PASSIVE
pin for passive symbols: must be connected, and can be connected to any pin.
Definition pin_type.h:43
BITMAPS ElectricalPinTypeGetBitmap(ELECTRICAL_PINTYPE)
Definition pin_type.cpp:226
wxString ElectricalPinTypeGetText(ELECTRICAL_PINTYPE)
Definition pin_type.cpp:212
wxString PinOrientationName(PIN_ORIENTATION aOrientation)
Definition pin_type.cpp:268
PIN_ORIENTATION
The symbol library pin object orientations.
Definition pin_type.h:105
@ PIN_UP
The pin extends upwards from the connection point: Probably on the bottom side of the symbol.
Definition pin_type.h:127
@ PIN_RIGHT
The pin extends rightwards from the connection point.
Definition pin_type.h:111
@ PIN_LEFT
The pin extends leftwards from the connection point: Probably on the right side of the symbol.
Definition pin_type.h:118
@ PIN_DOWN
The pin extends downwards from the connection: Probably on the top side of the symbol.
Definition pin_type.h:135
GRAPHIC_PINSHAPE
Definition pin_type.h:84
#define TYPE_HASH(x)
Definition property.h:73
#define ENUM_TO_WXANY(type)
Macro to define read-only fields (no setter method available)
Definition property.h:801
@ PT_COORD
Coordinate expressed in distance units (mm/inch)
Definition property.h:64
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition property.h:62
#define REGISTER_TYPE(x)
wxString FormatStackedPinForDisplay(const wxString &aPinNumber, int aPinLength, int aTextSize, KIFONT::FONT *aFont, const KIFONT::METRICS &aFontMetrics)
Definition sch_pin.cpp:42
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:106
#define PIN_TEXT_MARGIN
Definition sch_pin.cpp:87
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:92
static struct SCH_PIN_DESC _SCH_PIN_DESC
#define TARGET_PIN_RADIUS
Definition sch_pin.h:37
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.
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_NETNAME
wxString m_Name
Definition sch_pin.h:45
GRAPHIC_PINSHAPE m_Shape
Definition sch_pin.h:46
ELECTRICAL_PINTYPE m_Type
Definition sch_pin.h:47
KIFONT::FONT * m_Font
Definition sch_pin.h:345
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
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
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:229
@ SCH_PIN_T
Definition typeinfo.h:155
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694