KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_label.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 The KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <advanced_config.h>
27#include <base_units.h>
28#include <increment.h>
29#include <pgm_base.h>
30#include <sch_edit_frame.h>
31#include <sch_plotter.h>
32#include <widgets/msgpanel.h>
33#include <bitmaps.h>
34#include <string_utils.h>
36#include <schematic.h>
37#include <sch_screen.h>
38#include <sch_sheet.h>
39#include <sch_sheet_pin.h>
41#include <sch_painter.h>
42#include <default_values.h>
43#include <wx/debug.h>
44#include <wx/log.h>
48#include <core/kicad_algo.h>
49#include <core/mirror.h>
50#include <algorithm>
51#include <trigo.h>
52#include <sch_label.h>
53#include <sch_rule_area.h>
54#include <magic_enum.hpp>
55#include <api/api_utils.h>
56#include <api/schematic/schematic_types.pb.h>
57
58
59/* Coding polygons for global symbol graphic shapes.
60 * the first parml is the number of corners
61 * others are the corners coordinates in reduced units
62 * the real coordinate is the reduced coordinate * text half size
63 */
64static int TemplateIN_HN[] = { 6, 0, 0, -1, -1, -2, -1, -2, 1, -1, 1, 0, 0 };
65static int TemplateIN_HI[] = { 6, 0, 0, 1, 1, 2, 1, 2, -1, 1, -1, 0, 0 };
66static int TemplateIN_UP[] = { 6, 0, 0, 1, -1, 1, -2, -1, -2, -1, -1, 0, 0 };
67static int TemplateIN_BOTTOM[] = { 6, 0, 0, 1, 1, 1, 2, -1, 2, -1, 1, 0, 0 };
68
69static int TemplateOUT_HN[] = { 6, -2, 0, -1, 1, 0, 1, 0, -1, -1, -1, -2, 0 };
70static int TemplateOUT_HI[] = { 6, 2, 0, 1, -1, 0, -1, 0, 1, 1, 1, 2, 0 };
71static int TemplateOUT_UP[] = { 6, 0, -2, 1, -1, 1, 0, -1, 0, -1, -1, 0, -2 };
72static int TemplateOUT_BOTTOM[] = { 6, 0, 2, 1, 1, 1, 0, -1, 0, -1, 1, 0, 2 };
73
74static int TemplateUNSPC_HN[] = { 5, 0, -1, -2, -1, -2, 1, 0, 1, 0, -1 };
75static int TemplateUNSPC_HI[] = { 5, 0, -1, 2, -1, 2, 1, 0, 1, 0, -1 };
76static int TemplateUNSPC_UP[] = { 5, 1, 0, 1, -2, -1, -2, -1, 0, 1, 0 };
77static int TemplateUNSPC_BOTTOM[] = { 5, 1, 0, 1, 2, -1, 2, -1, 0, 1, 0 };
78
79static int TemplateBIDI_HN[] = { 5, 0, 0, -1, -1, -2, 0, -1, 1, 0, 0 };
80static int TemplateBIDI_HI[] = { 5, 0, 0, 1, -1, 2, 0, 1, 1, 0, 0 };
81static int TemplateBIDI_UP[] = { 5, 0, 0, -1, -1, 0, -2, 1, -1, 0, 0 };
82static int TemplateBIDI_BOTTOM[] = { 5, 0, 0, -1, 1, 0, 2, 1, 1, 0, 0 };
83
84static int Template3STATE_HN[] = { 5, 0, 0, -1, -1, -2, 0, -1, 1, 0, 0 };
85static int Template3STATE_HI[] = { 5, 0, 0, 1, -1, 2, 0, 1, 1, 0, 0 };
86static int Template3STATE_UP[] = { 5, 0, 0, -1, -1, 0, -2, 1, -1, 0, 0 };
87static int Template3STATE_BOTTOM[] = { 5, 0, 0, -1, 1, 0, 2, 1, 1, 0, 0 };
88
97
98
100{
101 switch( aType )
102 {
103 case LABEL_FLAG_SHAPE::L_INPUT: return _( "Input" );
104 case LABEL_FLAG_SHAPE::L_OUTPUT: return _( "Output" );
105 case LABEL_FLAG_SHAPE::L_BIDI: return _( "Bidirectional" );
106 case LABEL_FLAG_SHAPE::L_TRISTATE: return _( "Tri-State" );
107 case LABEL_FLAG_SHAPE::L_UNSPECIFIED: return _( "Passive" );
108 default: return wxT( "???" );
109 }
110}
111
112
114{
115 SPIN newSpin = m_spin;
116
117 switch( m_spin )
118 {
119 case SPIN_STYLE::LEFT: newSpin = SPIN_STYLE::BOTTOM; break;
120 case SPIN_STYLE::BOTTOM: newSpin = SPIN_STYLE::RIGHT; break;
121 case SPIN_STYLE::RIGHT: newSpin = SPIN_STYLE::UP; break;
122 case SPIN_STYLE::UP: newSpin = SPIN_STYLE::LEFT; break;
123 }
124
125 return SPIN_STYLE( newSpin );
126}
127
128
130{
131 SPIN newSpin = m_spin;
132
133 switch( m_spin )
134 {
135 case SPIN_STYLE::UP: newSpin = SPIN_STYLE::BOTTOM; break;
136 case SPIN_STYLE::BOTTOM: newSpin = SPIN_STYLE::UP; break;
137 case SPIN_STYLE::LEFT: break;
138 case SPIN_STYLE::RIGHT: break;
139 }
140
141 return SPIN_STYLE( newSpin );
142}
143
144
146{
147 SPIN newSpin = m_spin;
148
149 switch( m_spin )
150 {
151 case SPIN_STYLE::LEFT: newSpin = SPIN_STYLE::RIGHT; break;
152 case SPIN_STYLE::RIGHT: newSpin = SPIN_STYLE::LEFT; break;
153 case SPIN_STYLE::UP: break;
154 case SPIN_STYLE::BOTTOM: break;
155 }
156
157 return SPIN_STYLE( newSpin );
158}
159
160
161unsigned SPIN_STYLE::CCWRotationsTo( const SPIN_STYLE& aOther ) const
162{
163 return ( ( (int) m_spin - (int) aOther.m_spin ) % 4 + 4 ) % 4;
164}
165
166
167SCH_LABEL_BASE::SCH_LABEL_BASE( const VECTOR2I& aPos, const wxString& aText, KICAD_T aType ) :
168 SCH_TEXT( aPos, aText, LAYER_NOTES, aType ),
171 m_isDangling( true ),
174{
175 SetMultilineAllowed( false );
176
177 if( !HasTextVars() )
179}
180
181
183 SCH_TEXT( aLabel ),
184 m_shape( aLabel.m_shape ),
186 m_isDangling( aLabel.m_isDangling ),
190{
191 SetMultilineAllowed( false );
192
193 m_fields = aLabel.m_fields;
194
195 for( SCH_FIELD& field : m_fields )
196 field.SetParent( this );
197}
198
199
201{
202 SCH_TEXT::operator=( aLabel );
203
204 m_fields = aLabel.m_fields;
205
206 for( SCH_FIELD& field : m_fields )
207 field.SetParent( this );
208
209 m_shape = aLabel.m_shape;
211 m_isDangling = aLabel.m_isDangling;
215
216 return *this;
217}
218
219
220const wxString SCH_LABEL_BASE::GetDefaultFieldName( const wxString& aName, bool aUseDefaultName )
221{
222 if( aName == wxT( "Intersheetrefs" ) )
223 return _( "Sheet References" );
224 else if( aName == wxT( "Netclass" ) )
225 return _( "Net Class" );
226 else if( aName.IsEmpty() && aUseDefaultName )
227 return _( "Field" );
228 else
229 return aName;
230}
231
232
237
238
239bool SCH_LABEL_BASE::IsType( const std::vector<KICAD_T>& aScanTypes ) const
240{
241 static const std::vector<KICAD_T> wireAndPinTypes = { SCH_ITEM_LOCATE_WIRE_T, SCH_PIN_T };
242 static const std::vector<KICAD_T> busTypes = { SCH_ITEM_LOCATE_BUS_T };
243
244 if( SCH_TEXT::IsType( aScanTypes ) )
245 return true;
246
247 for( KICAD_T scanType : aScanTypes )
248 {
249 if( scanType == SCH_LABEL_LOCATE_ANY_T )
250 return true;
251 }
252
253 wxCHECK_MSG( Schematic(), false, wxT( "No parent SCHEMATIC set for SCH_LABEL!" ) );
254
255 // Ensure m_connected_items for Schematic()->CurrentSheet() exists.
256 // Can be not the case when "this" is living in clipboard
257 if( m_connected_items.find( Schematic()->CurrentSheet() ) == m_connected_items.end() )
258 return false;
259
260 const SCH_ITEM_VEC& item_set = m_connected_items.at( Schematic()->CurrentSheet() );
261
262 for( KICAD_T scanType : aScanTypes )
263 {
264 if( scanType == SCH_LABEL_LOCATE_WIRE_T )
265 {
266 for( SCH_ITEM* connection : item_set )
267 {
268 if( connection->IsType( wireAndPinTypes ) )
269 return true;
270 }
271 }
272
273 if ( scanType == SCH_LABEL_LOCATE_BUS_T )
274 {
275 for( SCH_ITEM* connection : item_set )
276 {
277 if( connection->IsType( busTypes ) )
278 return true;
279 }
280 }
281 }
282
283 return false;
284}
285
286
288{
289 SCH_TEXT::swapData( aItem );
290
291 SCH_LABEL_BASE* label = static_cast<SCH_LABEL_BASE*>( aItem );
292
293 m_fields.swap( label->m_fields );
294 std::swap( m_fieldsAutoplaced, label->m_fieldsAutoplaced );
295
296 for( SCH_FIELD& field : m_fields )
297 field.SetParent( this );
298
299 for( SCH_FIELD& field : label->m_fields )
300 field.SetParent( label );
301
302 std::swap( m_shape, label->m_shape );
303 std::swap( m_connectionType, label->m_connectionType );
304 std::swap( m_isDangling, label->m_isDangling );
305 std::swap( m_lastResolvedColor, label->m_lastResolvedColor );
306}
307
308
318
319
321{
322 m_shape = (LABEL_FLAG_SHAPE) aShape;
323
324 static bool s_inUpdate = false;
325
326 if( s_inUpdate )
327 return;
328
329 s_inUpdate = true;
330
331 if( Type() == SCH_HIER_LABEL_T )
332 {
333 SCH_HIERLABEL* label = static_cast<SCH_HIERLABEL*>( this );
334 SCH_SCREEN* screen = dynamic_cast<SCH_SCREEN*>( label->GetParent() );
335
336 if( screen )
337 {
338 const wxString& text = label->GetText();
339
340 for( SCH_ITEM* item : screen->Items().OfType( SCH_HIER_LABEL_T ) )
341 {
342 SCH_HIERLABEL* other = static_cast<SCH_HIERLABEL*>( item );
343
344 if( other != label && other->GetText() == text )
345 other->SetLabelShape( aShape );
346 }
347
348 for( const SCH_SHEET_PATH& sheetPath : screen->GetClientSheetPaths() )
349 {
350 SCH_SHEET* sheet = sheetPath.Last();
351
352 if( sheet )
353 {
354 for( SCH_SHEET_PIN* pin : sheet->GetPins() )
355 {
356 if( pin->GetText() == text )
357 pin->SetLabelShape( aShape );
358 }
359 }
360 }
361 }
362 }
363 else if( Type() == SCH_SHEET_PIN_T )
364 {
365 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( this );
366 SCH_SHEET* parent = pin->GetParent();
367
368 if( parent )
369 {
370 const wxString& text = pin->GetText();
371 SCH_SCREEN* screen = parent->GetScreen();
372
373 if( screen )
374 {
375 for( SCH_ITEM* item : screen->Items().OfType( SCH_HIER_LABEL_T ) )
376 {
377 SCH_HIERLABEL* hlabel = static_cast<SCH_HIERLABEL*>( item );
378
379 if( hlabel->GetText() == text )
380 hlabel->SetLabelShape( aShape );
381 }
382 }
383
384 for( SCH_SHEET_PIN* other : parent->GetPins() )
385 {
386 if( other != pin && other->GetText() == text )
387 other->SetLabelShape( aShape );
388 }
389 }
390 }
391
392 s_inUpdate = false;
393}
394
395
397{
398 // Assume "Right" and Left" mean which side of the anchor the text will be on
399 // Thus we want to left justify text up against the anchor if we are on the right
400 switch( aSpinStyle )
401 {
402 default:
403 wxFAIL_MSG( "Bad spin style" );
405
406 case SPIN_STYLE::RIGHT: // Horiz Normal Orientation
409 break;
410
411 case SPIN_STYLE::UP: // Vert Orientation UP
414 break;
415
416 case SPIN_STYLE::LEFT: // Horiz Orientation - Right justified
419 break;
420
421 case SPIN_STYLE::BOTTOM: // Vert Orientation BOTTOM
424 break;
425 }
426
428}
429
430
432{
434 {
436 return SPIN_STYLE::BOTTOM;
437 else
438 return SPIN_STYLE::UP;
439 }
440 else
441 {
443 return SPIN_STYLE::LEFT;
444 else
445 return SPIN_STYLE::RIGHT;
446 }
447}
448
449
451{
452 VECTOR2I text_offset;
453
454 // add an offset to x (or y) position to aid readability of text on a wire or line
455 int dist = GetTextOffset( aSettings ) + GetPenWidth();
456
457 switch( GetSpinStyle() )
458 {
459 case SPIN_STYLE::UP:
460 case SPIN_STYLE::BOTTOM: text_offset.x = -dist; break; // Vert Orientation
461 default:
462 case SPIN_STYLE::LEFT:
463 case SPIN_STYLE::RIGHT: text_offset.y = -dist; break; // Horiz Orientation
464 }
465
466 return text_offset;
467}
468
469
470void SCH_LABEL_BASE::SetPosition( const VECTOR2I& aPosition )
471{
472 VECTOR2I offset = aPosition - GetTextPos();
473 Move( offset );
474}
475
476
477void SCH_LABEL_BASE::Move( const VECTOR2I& aMoveVector )
478{
479 SCH_TEXT::Move( aMoveVector );
480
481 for( SCH_FIELD& field : m_fields )
482 field.Offset( aMoveVector );
483}
484
485
486void SCH_LABEL_BASE::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
487{
488 VECTOR2I pt = GetTextPos();
489 RotatePoint( pt, aCenter, aRotateCCW ? ANGLE_90 : ANGLE_270 );
490 VECTOR2I offset = pt - GetTextPos();
491
492 Rotate90( !aRotateCCW );
493
494 SetTextPos( GetTextPos() + offset );
495
496 for( SCH_FIELD& field : m_fields )
497 field.SetTextPos( field.GetTextPos() + offset );
498}
499
500
501void SCH_LABEL_BASE::Rotate90( bool aClockwise )
502{
503 SCH_TEXT::Rotate90( aClockwise );
504
506 {
508 }
509 else
510 {
511 for( SCH_FIELD& field : m_fields )
512 field.Rotate( GetPosition(), !aClockwise );
513 }
514}
515
516
517void SCH_LABEL_BASE::MirrorSpinStyle( bool aLeftRight )
518{
519 SCH_TEXT::MirrorSpinStyle( aLeftRight );
520
521 for( SCH_FIELD& field : m_fields )
522 {
523 if( ( aLeftRight && field.GetTextAngle().IsHorizontal() )
524 || ( !aLeftRight && field.GetTextAngle().IsVertical() ) )
525 {
526 if( field.GetHorizJustify() == GR_TEXT_H_ALIGN_LEFT )
527 field.SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
528 else
529 field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
530 }
531
532 VECTOR2I pos = field.GetTextPos();
534
535 if( aLeftRight )
536 pos.x = GetPosition().x + delta.x;
537 else
538 pos.y = GetPosition().y + delta.y;
539
540 field.SetTextPos( pos );
541 }
542}
543
544
546{
547 VECTOR2I old_pos = GetPosition();
549
550 for( SCH_FIELD& field : m_fields )
551 {
552 if( field.GetTextAngle() == ANGLE_HORIZONTAL )
553 field.FlipHJustify();
554
555 VECTOR2I pos = field.GetTextPos();
556 VECTOR2I delta = old_pos - pos;
557 pos.x = GetPosition().x + delta.x;
558
559 field.SetPosition( pos );
560 }
561}
562
563
565{
566 VECTOR2I old_pos = GetPosition();
568
569 for( SCH_FIELD& field : m_fields )
570 {
571 if( field.GetTextAngle() == ANGLE_VERTICAL )
572 field.FlipHJustify();
573
574 VECTOR2I pos = field.GetTextPos();
575 VECTOR2I delta = old_pos - pos;
576 pos.y = GetPosition().y + delta.y;
577
578 field.SetPosition( pos );
579 }
580}
581
582
583bool SCH_LABEL_BASE::IncrementLabel( int aIncrement )
584{
585 wxString text = GetText();
586
587 if( IncrementString( text, aIncrement ) )
588 {
589 SetText( text );
590 return true;
591 }
592
593 return false;
594}
595
596
597bool SCH_LABEL_BASE::operator==( const SCH_ITEM& aOther ) const
598{
599 const SCH_LABEL_BASE* other = dynamic_cast<const SCH_LABEL_BASE*>( &aOther );
600
601 if( !other )
602 return false;
603
604 if( m_shape != other->m_shape )
605 return false;
606
607 if( m_connectionType != other->m_connectionType )
608 return false;
609
610 if( m_fields.size() != other->m_fields.size() )
611 return false;
612
613 for( size_t ii = 0; ii < m_fields.size(); ++ii )
614 {
615 if( !( m_fields[ii] == other->m_fields[ii] ) )
616 return false;
617 }
618
619 return SCH_TEXT::operator==( aOther );
620}
621
622
623double SCH_LABEL_BASE::Similarity( const SCH_ITEM& aOther ) const
624{
625 const SCH_LABEL_BASE* other = dynamic_cast<const SCH_LABEL_BASE*>( &aOther );
626
627 if( !other )
628 return 0.0;
629
630 if( m_Uuid == other->m_Uuid )
631 return 1.0;
632
633 double similarity = SCH_TEXT::Similarity( aOther );
634
635 if( typeid( *this ) != typeid( aOther ) )
636 similarity *= 0.9;
637
638 if( m_shape == other->m_shape )
639 similarity *= 0.9;
640
641 if( m_connectionType == other->m_connectionType )
642 similarity *= 0.9;
643
644 for( size_t ii = 0; ii < m_fields.size(); ++ii )
645 {
646 if( ii >= other->m_fields.size() )
647 break;
648
649 similarity *= m_fields[ii].Similarity( other->m_fields[ii] );
650 }
651
652 int diff = std::abs( int( m_fields.size() ) - int( other->m_fields.size() ) );
653
654 similarity *= std::pow( 0.9, diff );
655
656 return similarity;
657}
658
659
661{
662 int margin = GetTextOffset() * 2;
663 int labelLen = GetBodyBoundingBox( nullptr ).GetSizeMax();
664 int accumulated = GetTextHeight() / 2;
665
666 if( Type() == SCH_GLOBAL_LABEL_T )
667 accumulated += margin + GetPenWidth() + margin;
668
669 for( SCH_FIELD& field : m_fields )
670 {
671 VECTOR2I offset( 0, 0 );
672
673 switch( GetSpinStyle() )
674 {
675 default:
676 case SPIN_STYLE::LEFT:
677 field.SetTextAngle( ANGLE_HORIZONTAL );
678 field.SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
679
680 if( field.GetId() == FIELD_T::INTERSHEET_REFS )
681 offset.x = - ( labelLen + margin );
682 else
683 offset.y = accumulated + field.GetTextHeight() / 2;
684
685 break;
686
687 case SPIN_STYLE::UP:
688 field.SetTextAngle( ANGLE_VERTICAL );
689 field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
690
691 if( field.GetId() == FIELD_T::INTERSHEET_REFS )
692 offset.y = - ( labelLen + margin );
693 else
694 offset.x = accumulated + field.GetTextHeight() / 2;
695
696 break;
697
699 field.SetTextAngle( ANGLE_HORIZONTAL );
700 field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
701
702 if( field.GetId() == FIELD_T::INTERSHEET_REFS )
703 offset.x = labelLen + margin;
704 else
705 offset.y = accumulated + field.GetTextHeight() / 2;
706
707 break;
708
710 field.SetTextAngle( ANGLE_VERTICAL );
711 field.SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
712
713 if( field.GetId() == FIELD_T::INTERSHEET_REFS )
714 offset.y = labelLen + margin;
715 else
716 offset.x = accumulated + field.GetTextHeight() / 2;
717
718 break;
719 }
720
721 field.SetTextPos( GetTextPos() + offset );
722
723 if( field.GetId() == FIELD_T::INTERSHEET_REFS )
724 accumulated += field.GetTextHeight() + margin;
725 }
726
727 if( aAlgo == AUTOPLACE_AUTO || aAlgo == AUTOPLACE_MANUAL )
728 m_fieldsAutoplaced = aAlgo;
729}
730
731
733 std::vector<std::pair<wxString, wxString>>* pages )
734{
735 wxCHECK( pages, /* void */ );
736
737 if( Schematic() )
738 {
739 wxString resolvedLabel = GetShownText( &Schematic()->CurrentSheet(), false );
740 auto it = Schematic()->GetPageRefsMap().find( resolvedLabel );
741
742 if( it != Schematic()->GetPageRefsMap().end() )
743 {
744 std::vector<int> pageListCopy;
745
746 pageListCopy.insert( pageListCopy.end(), it->second.begin(), it->second.end() );
747
748 if( !Schematic()->Settings().m_IntersheetRefsListOwnPage )
749 {
750 int currentPage = Schematic()->CurrentSheet().GetVirtualPageNumber();
751 std::erase( pageListCopy, currentPage );
752
753 if( pageListCopy.empty() )
754 return;
755 }
756
757 std::sort( pageListCopy.begin(), pageListCopy.end() );
758
759 std::map<int, wxString> sheetPages = Schematic()->GetVirtualPageToSheetPagesMap();
760 std::map<int, wxString> sheetNames = Schematic()->GetVirtualPageToSheetNamesMap();
761
762 for( int pageNum : pageListCopy )
763 pages->push_back( { sheetPages[ pageNum ], sheetNames[ pageNum ] } );
764 }
765 }
766}
767
768
769void SCH_LABEL_BASE::GetContextualTextVars( wxArrayString* aVars ) const
770{
771 for( const SCH_FIELD& field : m_fields )
772 {
773 if( field.IsMandatory() )
774 aVars->push_back( field.GetCanonicalName().Upper() );
775 else
776 aVars->push_back( field.GetName() );
777 }
778
779 aVars->push_back( wxT( "OP" ) );
780 aVars->push_back( wxT( "CONNECTION_TYPE" ) );
781 aVars->push_back( wxT( "SHORT_NET_NAME" ) );
782 aVars->push_back( wxT( "NET_NAME" ) );
783 aVars->push_back( wxT( "NET_CLASS" ) );
784}
785
786
787bool SCH_LABEL_BASE::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token,
788 int aDepth ) const
789{
790 static wxRegEx operatingPoint( wxT( "^"
791 "OP"
792 "(.([0-9])?([a-zA-Z]*))?"
793 "$" ) );
794
795 wxCHECK( aPath, false );
796
797 SCHEMATIC* schematic = Schematic();
798
799 if( !schematic )
800 return false;
801
802 if( operatingPoint.Matches( *token ) )
803 {
804 int precision = 3;
805 wxString precisionStr( operatingPoint.GetMatch( *token, 2 ) );
806 wxString range( operatingPoint.GetMatch( *token, 3 ) );
807
808 if( !precisionStr.IsEmpty() )
809 precision = precisionStr[0] - '0';
810
811 if( range.IsEmpty() )
812 range = wxS( "~V" );
813
814 const SCH_CONNECTION* connection = Connection();
815 *token = wxS( "?" );
816
817 if( connection )
818 *token = schematic->GetOperatingPoint( connection->Name( false ), precision, range );
819
820 return true;
821 }
822
823 if( token->Contains( ':' ) )
824 {
825 if( schematic->ResolveCrossReference( token, aDepth + 1 ) )
826 return true;
827 }
828
830 && token->IsSameAs( wxT( "CONNECTION_TYPE" ) ) )
831 {
832 const SCH_LABEL_BASE* label = static_cast<const SCH_LABEL_BASE*>( this );
833 *token = getElectricalTypeLabel( label->GetShape() );
834 return true;
835 }
836 else if( token->IsSameAs( wxT( "SHORT_NET_NAME" ) ) )
837 {
838 const SCH_CONNECTION* connection = Connection();
839 *token = wxEmptyString;
840
841 if( connection )
842 *token = connection->LocalName();
843
844 return true;
845 }
846 else if( token->IsSameAs( wxT( "NET_NAME" ) ) )
847 {
848 const SCH_CONNECTION* connection = Connection();
849 *token = wxEmptyString;
850
851 if( connection )
852 *token = connection->Name();
853
854 return true;
855 }
856 else if( token->IsSameAs( wxT( "NET_CLASS" ) ) )
857 {
858 const SCH_CONNECTION* connection = Connection();
859 *token = wxEmptyString;
860
861 if( connection )
862 *token = GetEffectiveNetClass()->GetName();
863
864 return true;
865 }
866 else if( Type() == SCH_DIRECTIVE_LABEL_T && token->IsSameAs( wxT( "EXCLUDE_FROM_BOM" ) ) )
867 {
868 const SCH_DIRECTIVE_LABEL* directive = static_cast<const SCH_DIRECTIVE_LABEL*>( this );
869 *token = wxEmptyString;
870
871 for( SCH_RULE_AREA* ruleArea : directive->GetConnectedRuleAreas() )
872 {
873 if( ruleArea->GetExcludedFromBOM() )
874 *token = _( "Excluded from BOM" );
875 }
876
877 return true;
878 }
879 else if( Type() == SCH_DIRECTIVE_LABEL_T && token->IsSameAs( wxT( "EXCLUDE_FROM_BOARD" ) ) )
880 {
881 const SCH_DIRECTIVE_LABEL* directive = static_cast<const SCH_DIRECTIVE_LABEL*>( this );
882 *token = wxEmptyString;
883
884 for( SCH_RULE_AREA* ruleArea : directive->GetConnectedRuleAreas() )
885 {
886 if( ruleArea->GetExcludedFromBoard() )
887 *token = _( "Excluded from board" );
888 }
889
890 return true;
891 }
892 else if( Type() == SCH_DIRECTIVE_LABEL_T && token->IsSameAs( wxT( "EXCLUDE_FROM_SIM" ) ) )
893 {
894 const SCH_DIRECTIVE_LABEL* directive = static_cast<const SCH_DIRECTIVE_LABEL*>( this );
895 *token = wxEmptyString;
896
897 for( SCH_RULE_AREA* ruleArea : directive->GetConnectedRuleAreas() )
898 {
899 if( ruleArea->GetExcludedFromSim() )
900 *token = _( "Excluded from simulation" );
901 }
902
903 return true;
904 }
905 else if( Type() == SCH_DIRECTIVE_LABEL_T && token->IsSameAs( wxT( "DNP" ) ) )
906 {
907 const SCH_DIRECTIVE_LABEL* directive = static_cast<const SCH_DIRECTIVE_LABEL*>( this );
908 *token = wxEmptyString;
909
910 for( SCH_RULE_AREA* ruleArea : directive->GetConnectedRuleAreas() )
911 {
912 if( ruleArea->GetDNP() )
913 *token = _( "DNP" );
914 }
915
916 return true;
917 }
918
919 for( const SCH_FIELD& field : m_fields)
920 {
921 if( token->IsSameAs( field.GetName() ) )
922 {
923 *token = field.GetShownText( false, aDepth + 1 );
924 return true;
925 }
926 }
927
928 // See if parent can resolve it (these will recurse to ancestors)
929
930 if( Type() == SCH_SHEET_PIN_T && m_parent )
931 {
932 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( m_parent );
933
934 SCH_SHEET_PATH path = *aPath;
935 path.push_back( sheet );
936
937 if( sheet->ResolveTextVar( &path, token, aDepth + 1 ) )
938 return true;
939 }
940 else
941 {
942 // aPath->Last() can be null when loading schematic, i.e. when all sheets are not yet loaded
943 if( aPath->Last() && aPath->Last()->ResolveTextVar( aPath, token, aDepth + 1 ) )
944 return true;
945 }
946
947 return false;
948}
949
950
952{
953 return !HasTextVars();
954}
955
956
958{
960}
961
962
970
971
972wxString SCH_LABEL_BASE::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraText,
973 int aDepth ) const
974{
975 std::function<bool( wxString* )> textResolver =
976 [&]( wxString* token ) -> bool
977 {
978 return ResolveTextVar( aPath, token, aDepth + 1 );
979 };
980
981 wxString text = EDA_TEXT::GetShownText( aAllowExtraText, aDepth );
982
983 if( HasTextVars() )
984 {
985 if( aDepth < ADVANCED_CFG::GetCfg().m_ResolveTextRecursionDepth )
986 text = ExpandTextVars( text, &textResolver );
987 }
988
989 if( text.Contains( wxT( "@{" ) ) )
991
992 return text;
993}
994
995
996void SCH_LABEL_BASE::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction, RECURSE_MODE aMode )
997{
998 for( SCH_FIELD& field : m_fields )
999 aFunction( &field );
1000}
1001
1002
1003bool SCH_LABEL_BASE::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
1004{
1005 if( SCH_ITEM::Matches( UnescapeString( GetText() ), aSearchData ) )
1006 {
1007 return true;
1008 }
1009
1010 const SCH_SEARCH_DATA* searchData = dynamic_cast<const SCH_SEARCH_DATA*>( &aSearchData );
1011 SCH_CONNECTION* connection = nullptr;
1012 SCH_SHEET_PATH* sheetPath = reinterpret_cast<SCH_SHEET_PATH*>( aAuxData );
1013
1014 if( searchData && searchData->searchNetNames && sheetPath
1015 && ( connection = Connection( sheetPath ) ) )
1016 {
1017 if( connection->IsBus() )
1018 {
1019 auto allMembers = connection->AllMembers();
1020
1021 std::set<wxString> netNames;
1022
1023 for( std::shared_ptr<SCH_CONNECTION> member : allMembers )
1024 netNames.insert( member->GetNetName() );
1025
1026 for( const wxString& netName : netNames )
1027 {
1028 if( EDA_ITEM::Matches( netName, aSearchData ) )
1029 return true;
1030 }
1031
1032 return false;
1033 }
1034
1035 wxString netName = connection->GetNetName();
1036
1037 if( EDA_ITEM::Matches( netName, aSearchData ) )
1038 return true;
1039 }
1040
1041 return false;
1042}
1043
1044
1045bool SCH_LABEL_BASE::Replace( const EDA_SEARCH_DATA& aSearchData, void* aAuxData )
1046{
1047 EDA_SEARCH_DATA localSearchData( aSearchData );
1048 localSearchData.findString = EscapeString( aSearchData.findString, CTX_NETNAME );
1049 localSearchData.replaceString = EscapeString( aSearchData.replaceString, CTX_NETNAME );
1050
1051 return EDA_TEXT::Replace( localSearchData );
1052}
1053
1054
1056 const std::vector<KICAD_T>& aScanTypes )
1057{
1058 if( IsType( aScanTypes ) )
1059 {
1060 if( INSPECT_RESULT::QUIT == aInspector( this, nullptr ) )
1061 return INSPECT_RESULT::QUIT;
1062 }
1063
1064 for( KICAD_T scanType : aScanTypes )
1065 {
1066 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_FIELD_T )
1067 {
1068 for( SCH_FIELD& field : m_fields )
1069 {
1070 if( INSPECT_RESULT::QUIT == aInspector( &field, this ) )
1071 return INSPECT_RESULT::QUIT;
1072 }
1073 }
1074 }
1075
1077}
1078
1079
1080void SCH_LABEL_BASE::GetEndPoints( std::vector<DANGLING_END_ITEM>& aItemList )
1081{
1082 DANGLING_END_ITEM item( LABEL_END, this, GetTextPos() );
1083 aItemList.push_back( item );
1084}
1085
1086
1087std::vector<VECTOR2I> SCH_LABEL_BASE::GetConnectionPoints() const
1088{
1089 return { GetTextPos() };
1090}
1091
1092
1093std::vector<int> SCH_LABEL_BASE::ViewGetLayers() const
1094{
1095 return { LAYER_DANGLING,
1100}
1101
1102
1104{
1105 double ratio;
1106
1107 if( aSettings )
1108 ratio = static_cast<const SCH_RENDER_SETTINGS*>( aSettings )->m_LabelSizeRatio;
1109 else if( Schematic() )
1110 ratio = Schematic()->Settings().m_LabelSizeRatio;
1111 else
1112 ratio = DEFAULT_LABEL_SIZE_RATIO; // For previews (such as in Preferences), etc.
1113
1114 return KiROUND( ratio * GetTextSize().y );
1115}
1116
1117
1119{
1120 // build the bounding box of the label only, without taking into account its fields
1121
1122 BOX2I box;
1123 std::vector<VECTOR2I> pts;
1124
1125 CreateGraphicShape( aSettings, pts, GetTextPos() );
1126
1127 for( const VECTOR2I& pt : pts )
1128 box.Merge( pt );
1129
1130 box.Inflate( GetEffectiveTextPenWidth() / 2 );
1131 box.Normalize();
1132 return box;
1133}
1134
1135
1137{
1138 // build the bounding box of the entire label, including its fields
1139
1140 BOX2I box = GetBodyBoundingBox( nullptr );
1141
1142 for( const SCH_FIELD& field : m_fields )
1143 {
1144 if( field.IsVisible() && field.GetText() != wxEmptyString )
1145 {
1146 BOX2I fieldBBox = field.GetBoundingBox();
1147
1148 if( Type() == SCH_LABEL_T || Type() == SCH_GLOBAL_LABEL_T )
1149 fieldBBox.Offset( GetSchematicTextOffset( nullptr ) );
1150
1151 box.Merge( fieldBBox );
1152 }
1153 }
1154
1155 box.Normalize();
1156
1157 return box;
1158}
1159
1160
1161bool SCH_LABEL_BASE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
1162{
1163 BOX2I bbox = GetBodyBoundingBox( nullptr );
1164 bbox.Inflate( aAccuracy );
1165
1166 if( bbox.Contains( aPosition ) )
1167 return true;
1168
1169 for( const SCH_FIELD& field : m_fields )
1170 {
1171 if( field.IsVisible() )
1172 {
1173 BOX2I fieldBBox = field.GetBoundingBox();
1174 fieldBBox.Inflate( aAccuracy );
1175
1176 if( Type() == SCH_LABEL_T || Type() == SCH_GLOBAL_LABEL_T )
1177 fieldBBox.Offset( GetSchematicTextOffset( nullptr ) );
1178
1179 if( fieldBBox.Contains( aPosition ) )
1180 return true;
1181 }
1182 }
1183
1184 return false;
1185}
1186
1187
1188bool SCH_LABEL_BASE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
1189{
1190 BOX2I rect = aRect;
1191
1192 rect.Inflate( aAccuracy );
1193
1194 if( aContained )
1195 {
1196 return rect.Contains( GetBoundingBox() );
1197 }
1198 else
1199 {
1200 if( rect.Intersects( GetBodyBoundingBox( nullptr ) ) )
1201 return true;
1202
1203 for( const SCH_FIELD& field : m_fields )
1204 {
1205 if( field.IsVisible() )
1206 {
1207 BOX2I fieldBBox = field.GetBoundingBox();
1208
1209 if( Type() == SCH_LABEL_T || Type() == SCH_GLOBAL_LABEL_T )
1210 fieldBBox.Offset( GetSchematicTextOffset( nullptr ) );
1211
1212 if( rect.Intersects( fieldBBox ) )
1213 return true;
1214 }
1215 }
1216
1217 return false;
1218 }
1219}
1220
1221
1222bool SCH_LABEL_BASE::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
1223{
1224 if( aContained )
1225 {
1226 return KIGEOM::BoxHitTest( aPoly, GetBoundingBox(), aContained );
1227 }
1228 else
1229 {
1230 if( KIGEOM::BoxHitTest( aPoly, GetBodyBoundingBox( nullptr ), aContained ) )
1231 return true;
1232
1233 for( const SCH_FIELD& field : m_fields )
1234 {
1235 if( field.IsVisible() )
1236 {
1237 BOX2I fieldBBox = field.GetBoundingBox();
1238
1239 if( Type() == SCH_LABEL_T || Type() == SCH_GLOBAL_LABEL_T )
1240 fieldBBox.Offset( GetSchematicTextOffset( nullptr ) );
1241
1242 if( KIGEOM::BoxHitTest( aPoly, fieldBBox, aContained ) )
1243 return true;
1244 }
1245 }
1246
1247 return false;
1248 }
1249}
1250
1251
1252bool SCH_LABEL_BASE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
1253 std::vector<DANGLING_END_ITEM>& aItemListByPos,
1254 const SCH_SHEET_PATH* aPath )
1255{
1256 bool previousState = m_isDangling;
1257 VECTOR2I text_pos = GetTextPos();
1258 m_isDangling = true;
1260
1261 for( auto it = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, text_pos );
1262 it < aItemListByPos.end() && it->GetPosition() == text_pos; it++ )
1263 {
1264 DANGLING_END_ITEM& item = *it;
1265
1266 if( item.GetItem() == this )
1267 continue;
1268
1269 switch( item.GetType() )
1270 {
1271 case PIN_END:
1272 case LABEL_END:
1273 case SHEET_LABEL_END:
1274 case NO_CONNECT_END:
1275 if( text_pos == item.GetPosition() )
1276 {
1277 m_isDangling = false;
1278
1279 if( aPath && item.GetType() != PIN_END )
1280 AddConnectionTo( *aPath, static_cast<SCH_ITEM*>( item.GetItem() ) );
1281 }
1282 break;
1283
1284 default: break;
1285 }
1286
1287 if( !m_isDangling )
1288 break;
1289 }
1290
1291 if( m_isDangling )
1292 {
1293 for( auto it = DANGLING_END_ITEM_HELPER::get_lower_type( aItemListByType, BUS_END );
1294 it < aItemListByType.end() && it->GetType() == BUS_END; it++ )
1295 {
1296 DANGLING_END_ITEM& item = *it;
1297 DANGLING_END_ITEM& nextItem = *( ++it );
1298
1299 int accuracy = 1; // We have rounding issues with an accuracy of 0
1300
1301 m_isDangling = !TestSegmentHit( text_pos, item.GetPosition(), nextItem.GetPosition(),
1302 accuracy );
1303
1304 if( m_isDangling )
1305 continue;
1306
1308
1309 // Add the line to the connected items, since it won't be picked
1310 // up by a search of intersecting connection points
1311 if( aPath )
1312 {
1313 auto sch_item = static_cast<SCH_ITEM*>( item.GetItem() );
1314 AddConnectionTo( *aPath, sch_item );
1315 sch_item->AddConnectionTo( *aPath, this );
1316 }
1317
1318 break;
1319 }
1320
1321 if( m_isDangling )
1322 {
1323 for( auto it = DANGLING_END_ITEM_HELPER::get_lower_type( aItemListByType, WIRE_END );
1324 it < aItemListByType.end() && it->GetType() == WIRE_END; it++ )
1325 {
1326 DANGLING_END_ITEM& item = *it;
1327 DANGLING_END_ITEM& nextItem = *( ++it );
1328
1329 int accuracy = 1; // We have rounding issues with an accuracy of 0
1330
1331 m_isDangling = !TestSegmentHit( text_pos, item.GetPosition(),
1332 nextItem.GetPosition(), accuracy );
1333
1334 if( m_isDangling )
1335 continue;
1336
1338
1339 // Add the line to the connected items, since it won't be picked
1340 // up by a search of intersecting connection points
1341 if( aPath )
1342 {
1343 auto sch_item = static_cast<SCH_ITEM*>( item.GetItem() );
1344 AddConnectionTo( *aPath, sch_item );
1345 sch_item->AddConnectionTo( *aPath, this );
1346 }
1347
1348 break;
1349 }
1350 }
1351 }
1352
1353 if( m_isDangling )
1355
1356 return previousState != m_isDangling;
1357}
1358
1359
1361 const SCH_SHEET_PATH* aInstance ) const
1362{
1363 // Do not compare to ourself.
1364 if( aItem == this || !IsConnectable() )
1365 return false;
1366
1367 const SCH_LABEL_BASE* label = dynamic_cast<const SCH_LABEL_BASE*>( aItem );
1368
1369 // Don't compare against a different SCH_ITEM.
1370 wxCHECK( label, false );
1371
1372 if( GetPosition() != label->GetPosition() )
1373 return true;
1374
1375 if( GetShownText( aInstance ) != label->GetShownText( aInstance ) )
1376 return true;
1377
1378 std::vector<wxString> netclasses;
1379 std::vector<wxString> otherNetclasses;
1380
1381 for( const SCH_FIELD& field : m_fields )
1382 {
1383 if( field.GetCanonicalName() == wxT( "Netclass" ) )
1384 netclasses.push_back( field.GetText() );
1385 }
1386
1387 for( const SCH_FIELD& field : label->m_fields )
1388 {
1389 if( field.GetCanonicalName() == wxT( "Netclass" ) )
1390 otherNetclasses.push_back( field.GetText() );
1391 }
1392
1393 return netclasses != otherNetclasses;
1394}
1395
1396
1397void SCH_LABEL_BASE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1398{
1399 wxString msg;
1400
1401 switch( Type() )
1402 {
1403 case SCH_LABEL_T: msg = _( "Label" ); break;
1404 case SCH_DIRECTIVE_LABEL_T: msg = _( "Directive Label" ); break;
1405 case SCH_GLOBAL_LABEL_T: msg = _( "Global Label" ); break;
1406 case SCH_HIER_LABEL_T: msg = _( "Hierarchical Label" ); break;
1407 case SCH_SHEET_PIN_T: msg = _( "Hierarchical Sheet Pin" ); break;
1408 default: return;
1409 }
1410
1411 // Don't use GetShownText() here; we want to show the user the variable references
1412 aList.emplace_back( msg, UnescapeString( GetText() ) );
1413
1414 // Display electrical type if it is relevant
1416 aList.emplace_back( _( "Type" ), getElectricalTypeLabel( GetShape() ) );
1417
1418 aList.emplace_back( _( "Font" ), GetFont() ? GetFont()->GetName() : _( "Default" ) );
1419
1420 wxString textStyle[] = { _( "Normal" ), _( "Italic" ), _( "Bold" ), _( "Bold Italic" ) };
1421 int style = IsBold() && IsItalic() ? 3 : IsBold() ? 2 : IsItalic() ? 1 : 0;
1422 aList.emplace_back( _( "Style" ), textStyle[style] );
1423
1424 aList.emplace_back( _( "Text Size" ), aFrame->MessageTextFromValue( GetTextWidth() ) );
1425
1426 switch( GetSpinStyle() )
1427 {
1428 case SPIN_STYLE::LEFT: msg = _( "Align right" ); break;
1429 case SPIN_STYLE::UP: msg = _( "Align bottom" ); break;
1430 case SPIN_STYLE::RIGHT: msg = _( "Align left" ); break;
1431 case SPIN_STYLE::BOTTOM: msg = _( "Align top" ); break;
1432 default: msg = wxT( "???" ); break;
1433 }
1434
1435 aList.emplace_back( _( "Justification" ), msg );
1436
1437 SCH_CONNECTION* conn = nullptr;
1438
1439 if( !IsConnectivityDirty() && dynamic_cast<SCH_EDIT_FRAME*>( aFrame ) )
1440 conn = Connection();
1441
1442 if( conn )
1443 {
1444 conn->AppendInfoToMsgPanel( aList );
1445
1446 if( !conn->IsBus() )
1447 {
1448 aList.emplace_back( _( "Resolved Netclass" ),
1449 UnescapeString( GetEffectiveNetClass()->GetHumanReadableName() ) );
1450 }
1451 }
1452}
1453
1454
1455void SCH_LABEL_BASE::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
1456 int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
1457{
1458 static std::vector<VECTOR2I> s_poly;
1459
1460 SCH_SHEET_PATH* sheet = &Schematic()->CurrentSheet();
1461 RENDER_SETTINGS* settings = aPlotter->RenderSettings();
1462 SCH_CONNECTION* connection = Connection();
1463 int layer = ( connection && connection->IsBus() ) ? LAYER_BUS : m_layer;
1464 COLOR4D color = settings->GetLayerColor( layer );
1465 int penWidth = GetEffectiveTextPenWidth( settings->GetDefaultPenWidth() );
1466
1467 if( aPlotter->GetColorMode() && GetLabelColor() != COLOR4D::UNSPECIFIED )
1468 color = GetLabelColor();
1469
1470 penWidth = std::max( penWidth, settings->GetMinPenWidth() );
1471 aPlotter->SetCurrentLineWidth( penWidth );
1472
1473 KIFONT::FONT* font = GetDrawFont( settings );
1474
1475 VECTOR2I textpos = GetTextPos() + GetSchematicTextOffset( settings );
1476 CreateGraphicShape( settings, s_poly, GetTextPos() );
1477
1479 attrs.m_StrokeWidth = penWidth;
1480 attrs.m_Multiline = false;
1481
1482 if( aBackground )
1483 {
1484 // No filled shapes (yet)
1485 }
1486 else
1487 {
1488 aPlotter->PlotText( textpos, color, GetShownText( sheet, true ), attrs, font, GetFontMetrics() );
1489
1490 if( aPlotter->GetColorMode() )
1491 {
1492 // For the graphic shape use the override color or the layer color, but not the
1493 // net/netclass color.
1495 aPlotter->SetColor( GetTextColor() );
1496 else
1497 aPlotter->SetColor( settings->GetLayerColor( m_layer ) );
1498 }
1499
1501 {
1502 aPlotter->MoveTo( s_poly[0] );
1503 aPlotter->LineTo( s_poly[1] );
1504 aPlotter->PenFinish();
1505
1506 int diameter = ( s_poly[2] - s_poly[1] ).EuclideanNorm() * 2;
1507 aPlotter->FilledCircle( s_poly[2], diameter, nullptr );
1508 }
1509 else if( GetShape() == LABEL_FLAG_SHAPE::F_ROUND )
1510 {
1511 aPlotter->MoveTo( s_poly[0] );
1512 aPlotter->LineTo( s_poly[1] );
1513 aPlotter->PenFinish();
1514
1515 int diameter = ( s_poly[2] - s_poly[1] ).EuclideanNorm() * 2;
1516 aPlotter->ThickCircle( s_poly[2], diameter, penWidth, nullptr );
1517 }
1518 else
1519 {
1520 if( !s_poly.empty() )
1521 aPlotter->PlotPoly( s_poly, FILL_T::NO_FILL, penWidth, nullptr );
1522 }
1523
1524 // Make sheet pins and hierarchical labels clickable hyperlinks
1525 bool linkAlreadyPlotted = false;
1526 BOX2I bodyBBox = GetBodyBoundingBox( settings );
1527
1528 if( aPlotOpts.m_PDFHierarchicalLinks )
1529 {
1530 if( Type() == SCH_HIER_LABEL_T )
1531 {
1532 if( sheet->size() >= 2 )
1533 {
1534 SCH_SHEET_PATH path = *sheet;
1535 path.pop_back();
1536 aPlotter->HyperlinkBox( bodyBBox, EDA_TEXT::GotoPageHref( path.GetPageNumber() ) );
1537 linkAlreadyPlotted = true;
1538 }
1539 }
1540 else if( Type() == SCH_SHEET_PIN_T )
1541 {
1542 SCH_SHEET_PATH path = *sheet;
1543 SCH_SHEET* parent = static_cast<SCH_SHEET*>( m_parent );
1544 path.push_back( parent );
1545 aPlotter->HyperlinkBox( bodyBBox, EDA_TEXT::GotoPageHref( path.GetPageNumber() ) );
1546 linkAlreadyPlotted = true;
1547 }
1548 }
1549
1550 // Plot attributes to a hypertext menu
1551 if( aPlotOpts.m_PDFPropertyPopups && !linkAlreadyPlotted )
1552 {
1553 std::vector<wxString> properties;
1554
1555 if( connection )
1556 {
1557 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
1558 _( "Net" ),
1559 connection->Name() ) );
1560
1561 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
1562 _( "Resolved netclass" ),
1563 GetEffectiveNetClass()->GetHumanReadableName() ) );
1564 }
1565
1566 for( const SCH_FIELD& field : GetFields() )
1567 {
1568 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
1569 field.GetName(),
1570 field.GetShownText( false ) ) );
1571 }
1572
1573 if( !properties.empty() )
1574 aPlotter->HyperlinkMenu( bodyBBox, properties );
1575 }
1576
1577 if( Type() == SCH_HIER_LABEL_T )
1578 aPlotter->Bookmark( bodyBBox, GetShownText( false ), _( "Hierarchical Labels" ) );
1579 }
1580
1581 for( SCH_FIELD& field : m_fields )
1582 field.Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed );
1583}
1584
1585
1590
1591
1593{
1594 m_autoRotateOnPlacement = autoRotate;
1595}
1596
1597
1598SCH_LABEL::SCH_LABEL( const VECTOR2I& pos, const wxString& text ) :
1600{
1603 m_isDangling = true;
1604}
1605
1606
1607void SCH_LABEL::Serialize( google::protobuf::Any &aContainer ) const
1608{
1609 kiapi::schematic::types::LocalLabel label;
1610
1611 label.mutable_id()->set_value( m_Uuid.AsStdString() );
1612 kiapi::common::PackVector2( *label.mutable_position(), GetPosition() );
1613
1614 aContainer.PackFrom( label );
1615}
1616
1617
1618bool SCH_LABEL::Deserialize( const google::protobuf::Any &aContainer )
1619{
1620 kiapi::schematic::types::LocalLabel label;
1621
1622 if( !aContainer.UnpackTo( &label ) )
1623 return false;
1624
1625 const_cast<KIID&>( m_Uuid ) = KIID( label.id().value() );
1626 SetPosition( kiapi::common::UnpackVector2( label.position() ) );
1627
1628 return true;
1629}
1630
1631
1633{
1634 BOX2I rect = GetTextBox( aSettings );
1635
1636 rect.Offset( 0, -GetTextOffset() );
1638
1639 if( !GetTextAngle().IsZero() )
1640 {
1641 // Rotate rect
1642 VECTOR2I pos = rect.GetOrigin();
1643 VECTOR2I end = rect.GetEnd();
1644
1645 RotatePoint( pos, GetTextPos(), GetTextAngle() );
1647
1648 rect.SetOrigin( pos );
1649 rect.SetEnd( end );
1650
1651 rect.Normalize();
1652 }
1653
1654 // Labels have a position point that is outside of the TextBox
1655 rect.Merge( GetPosition() );
1656
1657 return rect;
1658}
1659
1660
1661wxString SCH_LABEL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1662{
1663 return wxString::Format( _( "Label '%s'" ),
1664 aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() ) );
1665}
1666
1667
1672
1673
1675 SCH_LABEL_BASE( pos, wxEmptyString, SCH_DIRECTIVE_LABEL_T )
1676{
1679 m_pinLength = schIUScale.MilsToIU( 100 );
1680 m_symbolSize = schIUScale.MilsToIU( 20 );
1681 m_isDangling = true;
1682}
1683
1684
1686{
1687 SCH_LABEL_BASE::swapData( aItem );
1688
1689 SCH_DIRECTIVE_LABEL* label = static_cast<SCH_DIRECTIVE_LABEL*>( aItem );
1690
1691 std::swap( m_pinLength, label->m_pinLength );
1692 std::swap( m_symbolSize, label->m_symbolSize );
1693}
1694
1695
1697 SCH_LABEL_BASE( aClassLabel )
1698{
1699 m_pinLength = aClassLabel.m_pinLength;
1700 m_symbolSize = aClassLabel.m_symbolSize;
1701}
1702
1703
1704void SCH_DIRECTIVE_LABEL::Serialize( google::protobuf::Any &aContainer ) const
1705{
1706 // TODO
1707}
1708
1709
1710bool SCH_DIRECTIVE_LABEL::Deserialize( const google::protobuf::Any &aContainer )
1711{
1712 // TODO
1713 return false;
1714}
1715
1716
1718{
1719 int pen = 0;
1720
1721 if( Schematic() )
1723
1724 return GetEffectiveTextPenWidth( pen );
1725}
1726
1727
1729{
1730 // The "text" is in fact a graphic shape. For a horizontal "text", it looks like a
1731 // vertical shape (like a text reduced to only "I" letter).
1732 // So the mirroring is not exactly similar to a SCH_TEXT item
1733 SCH_TEXT::MirrorSpinStyle( !aLeftRight );
1734
1735 for( SCH_FIELD& field : m_fields )
1736 {
1737 if( ( aLeftRight && field.GetTextAngle().IsHorizontal() )
1738 || ( !aLeftRight && field.GetTextAngle().IsVertical() ) )
1739 {
1740 if( field.GetHorizJustify() == GR_TEXT_H_ALIGN_LEFT )
1741 field.SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
1742 else
1743 field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1744 }
1745
1746 VECTOR2I pos = field.GetTextPos();
1748
1749 if( aLeftRight )
1750 pos.x = GetPosition().x + delta.x;
1751 else
1752 pos.y = GetPosition().y + delta.y;
1753
1754 field.SetTextPos( pos );
1755 }
1756}
1757
1758
1760{
1761 VECTOR2I old_pos = GetPosition();
1762
1763 // The "text" is in fact a graphic shape. For a horizontal "text", it looks like a
1764 // vertical shape (like a text reduced to only "I" letter).
1765 // So the mirroring is not exactly similar to a SCH_TEXT item
1766 // Text is NOT really mirrored; it is moved to a suitable horizontal position
1767 SetSpinStyle( GetSpinStyle().MirrorX() );
1768
1769 SetTextX( MIRRORVAL( GetTextPos().x, aCenter ) );
1770
1771 for( SCH_FIELD& field : m_fields )
1772 {
1773 if( field.GetHorizJustify() == GR_TEXT_H_ALIGN_LEFT )
1774 field.SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
1775 else if( field.GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
1776 field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1777
1778 VECTOR2I pos = field.GetTextPos();
1779 VECTOR2I delta = old_pos - pos;
1780 pos.x = GetPosition().x + delta.x;
1781
1782 field.SetPosition( pos );
1783 }
1784}
1785
1786
1788{
1789 VECTOR2I old_pos = GetPosition();
1790 // The "text" is in fact a graphic shape. For a horizontal "text", it looks like a
1791 // vertical shape (like a text reduced to only "I" letter).
1792 // So the mirroring is not exactly similar to a SCH_TEXT item
1793 // Text is NOT really mirrored; it is moved to a suitable vertical position
1794 SetSpinStyle( GetSpinStyle().MirrorY() );
1795
1796 SetTextY( MIRRORVAL( GetTextPos().y, aCenter ) );
1797
1798 for( SCH_FIELD& field : m_fields )
1799 {
1800 VECTOR2I pos = field.GetTextPos();
1801 VECTOR2I delta = old_pos - pos;
1802 pos.y = GetPosition().y + delta.y;
1803
1804 field.SetPosition( pos );
1805 }
1806}
1807
1808
1810 std::vector<VECTOR2I>& aPoints,
1811 const VECTOR2I& aPos ) const
1812{
1813 int symbolSize = m_symbolSize;
1814
1815 aPoints.clear();
1816
1817 switch( m_shape )
1818 {
1820 symbolSize = KiROUND( symbolSize * 0.7 );
1822
1824 // First 3 points are used for generating shape
1825 aPoints.emplace_back( VECTOR2I( 0, 0 ) );
1826 aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) );
1827 aPoints.emplace_back( VECTOR2I( 0, m_pinLength ) );
1828
1829 // These points are just used to bulk out the bounding box
1830 aPoints.emplace_back( VECTOR2I( -m_symbolSize, m_pinLength ) );
1831 aPoints.emplace_back( VECTOR2I( 0, m_pinLength ) );
1832 aPoints.emplace_back( VECTOR2I( m_symbolSize, m_pinLength + symbolSize ) );
1833 break;
1834
1836 aPoints.emplace_back( VECTOR2I( 0, 0 ) );
1837 aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) );
1838 aPoints.emplace_back( VECTOR2I( -2 * m_symbolSize, m_pinLength ) );
1839 aPoints.emplace_back( VECTOR2I( 0, m_pinLength + symbolSize ) );
1840 aPoints.emplace_back( VECTOR2I( 2 * m_symbolSize, m_pinLength ) );
1841 aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) );
1842 aPoints.emplace_back( VECTOR2I( 0, 0 ) );
1843 break;
1844
1846 symbolSize = KiROUND( symbolSize * 0.8 );
1847
1848 aPoints.emplace_back( VECTOR2I( 0, 0 ) );
1849 aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) );
1850 aPoints.emplace_back( VECTOR2I( -2 * symbolSize, m_pinLength - symbolSize ) );
1851 aPoints.emplace_back( VECTOR2I( -2 * symbolSize, m_pinLength + symbolSize ) );
1852 aPoints.emplace_back( VECTOR2I( 2 * symbolSize, m_pinLength + symbolSize ) );
1853 aPoints.emplace_back( VECTOR2I( 2 * symbolSize, m_pinLength - symbolSize ) );
1854 aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) );
1855 aPoints.emplace_back( VECTOR2I( 0, 0 ) );
1856 break;
1857
1858 default:
1859 break;
1860 }
1861
1862 // Rotate outlines and move corners to real position
1863 for( VECTOR2I& aPoint : aPoints )
1864 {
1865 switch( GetSpinStyle() )
1866 {
1867 default:
1868 case SPIN_STYLE::LEFT: break;
1869 case SPIN_STYLE::UP: RotatePoint( aPoint, -ANGLE_90 ); break;
1870 case SPIN_STYLE::RIGHT: RotatePoint( aPoint, ANGLE_180 ); break;
1871 case SPIN_STYLE::BOTTOM: RotatePoint( aPoint, ANGLE_90 ); break;
1872 }
1873
1874 aPoint += aPos;
1875 }
1876}
1877
1878
1880{
1881 int margin = GetTextOffset();
1882 int symbolWidth = m_symbolSize;
1883 int origin = m_pinLength;
1884
1886 symbolWidth *= 2;
1887
1888 if( IsItalic() )
1889 margin = KiROUND( margin * 1.5 );
1890
1891 VECTOR2I offset;
1892
1893 for( SCH_FIELD& field : m_fields )
1894 {
1895 if( field.GetText() == wxEmptyString )
1896 continue;
1897
1898 switch( GetSpinStyle() )
1899 {
1900 default:
1901 case SPIN_STYLE::LEFT:
1902 field.SetTextAngle( ANGLE_HORIZONTAL );
1903 offset = { symbolWidth + margin, origin };
1904 break;
1905
1906 case SPIN_STYLE::UP:
1907 field.SetTextAngle( ANGLE_VERTICAL );
1908 offset = { -origin, -( symbolWidth + margin ) };
1909 break;
1910
1911 case SPIN_STYLE::RIGHT:
1912 field.SetTextAngle( ANGLE_HORIZONTAL );
1913 offset = { symbolWidth + margin, -origin };
1914 break;
1915
1916 case SPIN_STYLE::BOTTOM:
1917 field.SetTextAngle( ANGLE_VERTICAL );
1918 offset = { origin, -( symbolWidth + margin ) };
1919 break;
1920 }
1921
1922 field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1923 field.SetTextPos( GetPosition() + offset );
1924
1925 origin -= field.GetTextHeight() + margin;
1926 }
1927
1928 if( aAlgo == AUTOPLACE_AUTO || aAlgo == AUTOPLACE_MANUAL )
1929 m_fieldsAutoplaced = aAlgo;
1930}
1931
1932
1933wxString SCH_DIRECTIVE_LABEL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1934{
1935 if( m_fields.empty() )
1936 {
1937 return _( "Directive Label" );
1938 }
1939 else
1940 {
1941 const SCH_FIELD& firstField = m_fields[0];
1942 wxString content = aFull ? firstField.GetShownText( false ) : KIUI::EllipsizeMenuText( firstField.GetText() );
1943
1944 if( content.IsEmpty() )
1945 {
1946 return wxString::Format( _( "Directive Label [%s (empty)]" ),
1947 UnescapeString( m_fields[0].GetName() ) );
1948 }
1949 else
1950 {
1951 return wxString::Format( _( "Directive Label [%s %s]" ),
1952 UnescapeString( m_fields[0].GetName() ),
1953 content );
1954 }
1955 }
1956}
1957
1958
1960{
1961 m_connected_rule_areas.insert( aRuleArea );
1962}
1963
1964
1969
1970
1972{
1973 m_connected_rule_areas.erase( aRuleArea );
1974}
1975
1976
1977const std::unordered_set<SCH_RULE_AREA*> SCH_DIRECTIVE_LABEL::GetConnectedRuleAreas() const
1978{
1980}
1981
1982
1984{
1985 return m_isDangling && m_connected_rule_areas.empty();
1986}
1987
1988
1989SCH_GLOBALLABEL::SCH_GLOBALLABEL( const VECTOR2I& pos, const wxString& text ) :
1991{
1994 m_isDangling = true;
1995
1997
1998 m_fields.emplace_back( SCH_FIELD( this, FIELD_T::INTERSHEET_REFS,
2000 m_fields.back().SetText( wxT( "${INTERSHEET_REFS}" ) );
2001 m_fields.back().SetVisible( false );
2002 m_fields.back().SetVertJustify( GR_TEXT_V_ALIGN_CENTER );
2003 m_fields.back().SetTextPos( pos );
2004}
2005
2006
2008 SCH_LABEL_BASE( aGlobalLabel )
2009{
2010}
2011
2012
2013void SCH_GLOBALLABEL::Serialize( google::protobuf::Any &aContainer ) const
2014{
2015 // TODO
2016}
2017
2018
2019bool SCH_GLOBALLABEL::Deserialize( const google::protobuf::Any &aContainer )
2020{
2021 // TODO
2022 return false;
2023}
2024
2025
2027{
2028 if( SCH_FIELD* field = FindField( m_fields, aFieldType ) )
2029 return field;
2030
2031 m_fields.emplace_back( this, aFieldType );
2032 return &m_fields.back();
2033}
2034
2035
2037{
2038 return FindField( m_fields, aFieldType );
2039}
2040
2041
2043{
2044 int horiz = GetLabelBoxExpansion( aSettings );
2045
2046 // Center the text on the center line of "E" instead of "R" to make room for an overbar
2047 int vert = GetTextHeight() * 0.0715;
2048
2049 switch( m_shape )
2050 {
2054 horiz += GetTextHeight() * 3 / 4; // Use three-quarters-height as proxy for triangle size
2055 break;
2056
2059 default:
2060 break;
2061 }
2062
2063 switch( GetSpinStyle() )
2064 {
2065 default:
2066 case SPIN_STYLE::LEFT: return VECTOR2I( -horiz, vert );
2067 case SPIN_STYLE::UP: return VECTOR2I( vert, -horiz );
2068 case SPIN_STYLE::RIGHT: return VECTOR2I( horiz, vert );
2069 case SPIN_STYLE::BOTTOM: return VECTOR2I( vert, horiz );
2070 }
2071}
2072
2073
2079
2080
2081bool SCH_GLOBALLABEL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token,
2082 int aDepth ) const
2083{
2084 wxCHECK( aPath, false );
2085
2086 SCHEMATIC* schematic = Schematic();
2087
2088 if( !schematic )
2089 return false;
2090
2091 if( token->IsSameAs( wxT( "INTERSHEET_REFS" ) ) )
2092 {
2093 SCHEMATIC_SETTINGS& settings = schematic->Settings();
2094 wxString ref;
2095 auto it = schematic->GetPageRefsMap().find( GetShownText( aPath ) );
2096
2097 if( it == schematic->GetPageRefsMap().end() )
2098 {
2099 ref = "?";
2100 }
2101 else
2102 {
2103 std::vector<int> pageListCopy;
2104
2105 pageListCopy.insert( pageListCopy.end(), it->second.begin(), it->second.end() );
2106 std::sort( pageListCopy.begin(), pageListCopy.end() );
2107
2108 if( !settings.m_IntersheetRefsListOwnPage )
2109 {
2110 int currentPage = schematic->CurrentSheet().GetVirtualPageNumber();
2111 std::erase( pageListCopy, currentPage );
2112 }
2113
2114 std::map<int, wxString> sheetPages = schematic->GetVirtualPageToSheetPagesMap();
2115
2116 if( ( settings.m_IntersheetRefsFormatShort ) && ( pageListCopy.size() > 2 ) )
2117 {
2118 ref.Append( wxString::Format( wxT( "%s..%s" ),
2119 sheetPages[pageListCopy.front()],
2120 sheetPages[pageListCopy.back()] ) );
2121 }
2122 else
2123 {
2124 for( const int& pageNo : pageListCopy )
2125 ref.Append( wxString::Format( wxT( "%s," ), sheetPages[pageNo] ) );
2126
2127 if( !ref.IsEmpty() && ref.Last() == ',' )
2128 ref.RemoveLast();
2129 }
2130 }
2131
2132 *token = settings.m_IntersheetRefsPrefix + ref + settings.m_IntersheetRefsSuffix;
2133 return true;
2134 }
2135
2136 return SCH_LABEL_BASE::ResolveTextVar( aPath, token, aDepth );
2137}
2138
2139
2150
2151
2153 std::vector<VECTOR2I>& aPoints,
2154 const VECTOR2I& aPos ) const
2155{
2156 int margin = GetLabelBoxExpansion( aRenderSettings );
2157 int halfSize = ( GetTextHeight() / 2 ) + margin;
2158 int linewidth = GetPenWidth();
2159 int symb_len = GetTextBox( aRenderSettings ).GetWidth() + 2 * margin;
2160
2161 int x = symb_len + linewidth + 3;
2162 int y = halfSize + linewidth + 3;
2163
2164 aPoints.clear();
2165
2166 // Create outline shape : 6 points
2167 aPoints.emplace_back( VECTOR2I( 0, 0 ) );
2168 aPoints.emplace_back( VECTOR2I( 0, -y ) ); // Up
2169 aPoints.emplace_back( VECTOR2I( -x, -y ) ); // left
2170 aPoints.emplace_back( VECTOR2I( -x, 0 ) ); // Up left
2171 aPoints.emplace_back( VECTOR2I( -x, y ) ); // left down
2172 aPoints.emplace_back( VECTOR2I( 0, y ) ); // down
2173
2174 int x_offset = 0;
2175
2176 switch( m_shape )
2177 {
2179 x_offset = -halfSize;
2180 aPoints[0].x += halfSize;
2181 break;
2182
2184 aPoints[3].x -= halfSize;
2185 break;
2186
2189 x_offset = -halfSize;
2190 aPoints[0].x += halfSize;
2191 aPoints[3].x -= halfSize;
2192 break;
2193
2195 default:
2196 break;
2197 }
2198
2199 // Rotate outlines and move corners in real position
2200 for( VECTOR2I& aPoint : aPoints )
2201 {
2202 aPoint.x += x_offset;
2203
2204 switch( GetSpinStyle() )
2205 {
2206 default:
2207 case SPIN_STYLE::LEFT: break;
2208 case SPIN_STYLE::UP: RotatePoint( aPoint, -ANGLE_90 ); break;
2209 case SPIN_STYLE::RIGHT: RotatePoint( aPoint, ANGLE_180 ); break;
2210 case SPIN_STYLE::BOTTOM: RotatePoint( aPoint, ANGLE_90 ); break;
2211 }
2212
2213 aPoint += aPos;
2214 }
2215
2216 aPoints.push_back( aPoints[0] ); // closing
2217}
2218
2219
2220wxString SCH_GLOBALLABEL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
2221{
2222 return wxString::Format( _( "Global Label '%s'" ),
2223 aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() ) );
2224}
2225
2226
2231
2232
2233SCH_HIERLABEL::SCH_HIERLABEL( const VECTOR2I& pos, const wxString& text, KICAD_T aType ) :
2234 SCH_LABEL_BASE( pos, text, aType )
2235{
2238 m_isDangling = true;
2239}
2240
2241
2242void SCH_HIERLABEL::Serialize( google::protobuf::Any &aContainer ) const
2243{
2244 // TODO
2245}
2246
2247
2248bool SCH_HIERLABEL::Deserialize( const google::protobuf::Any &aContainer )
2249{
2250 // TODO
2251 return false;
2252}
2253
2254
2260
2261
2263 std::vector<VECTOR2I>& aPoints, const VECTOR2I& aPos ) const
2264{
2265 CreateGraphicShape( aSettings, aPoints, aPos, m_shape );
2266}
2267
2268
2270 std::vector<VECTOR2I>& aPoints, const VECTOR2I& aPos,
2271 LABEL_FLAG_SHAPE aShape ) const
2272{
2273 int* Template = TemplateShape[static_cast<int>( aShape )][static_cast<int>( GetSpinStyle() )];
2274 int halfSize = GetTextHeight() / 2;
2275 int imax = *Template;
2276 Template++;
2277
2278 aPoints.clear();
2279
2280 for( int ii = 0; ii < imax; ii++ )
2281 {
2282 VECTOR2I corner;
2283 corner.x = ( halfSize * (*Template) ) + aPos.x;
2284 Template++;
2285
2286 corner.y = ( halfSize * (*Template) ) + aPos.y;
2287 Template++;
2288
2289 aPoints.push_back( corner );
2290 }
2291}
2292
2293
2295{
2296 int penWidth = GetEffectiveTextPenWidth();
2297 int margin = GetTextOffset();
2298
2299 int x = GetTextPos().x;
2300 int y = GetTextPos().y;
2301
2302 int height = GetTextHeight() + penWidth + margin;
2303 int length = GetTextBox( aSettings ).GetWidth();
2304
2305 length += height; // add height for triangular shapes
2306
2307 int dx, dy;
2308
2309 switch( GetSpinStyle() )
2310 {
2311 default:
2312 case SPIN_STYLE::LEFT:
2313 dx = -length;
2314 dy = height;
2315 x += schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE );
2316 y -= height / 2;
2317 break;
2318
2319 case SPIN_STYLE::UP:
2320 dx = height;
2321 dy = -length;
2322 x -= height / 2;
2323 y += schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE );
2324 break;
2325
2326 case SPIN_STYLE::RIGHT:
2327 dx = length;
2328 dy = height;
2329 x -= schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE );
2330 y -= height / 2;
2331 break;
2332
2333 case SPIN_STYLE::BOTTOM:
2334 dx = height;
2335 dy = length;
2336 x -= height / 2;
2337 y -= schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE );
2338 break;
2339 }
2340
2341 BOX2I box( VECTOR2I( x, y ), VECTOR2I( dx, dy ) );
2342 box.Normalize();
2343 return box;
2344}
2345
2346
2348{
2349 VECTOR2I text_offset;
2350 int dist = GetTextOffset( aSettings );
2351
2352 dist += GetTextWidth();
2353
2354 switch( GetSpinStyle() )
2355 {
2356 default:
2357 case SPIN_STYLE::LEFT: text_offset.x = -dist; break; // Orientation horiz normale
2358 case SPIN_STYLE::UP: text_offset.y = -dist; break; // Orientation vert UP
2359 case SPIN_STYLE::RIGHT: text_offset.x = dist; break; // Orientation horiz inverse
2360 case SPIN_STYLE::BOTTOM: text_offset.y = dist; break; // Orientation vert BOTTOM
2361 }
2362
2363 return text_offset;
2364}
2365
2366
2367wxString SCH_HIERLABEL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
2368{
2369 return wxString::Format( _( "Hierarchical Label '%s'" ),
2370 aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() ) );
2371}
2372
2373
2378
2379
2381{
2382 wxString msg =
2383#include "sch_text_help_md.h"
2384 ;
2385
2386 HTML_MESSAGE_BOX* dlg = new HTML_MESSAGE_BOX( nullptr, _( "Syntax Help" ) );
2387 wxSize sz( 320, 320 );
2388
2389 dlg->SetMinSize( dlg->ConvertDialogToPixels( sz ) );
2390 dlg->SetDialogSizeInDU( sz.x, sz.y );
2391
2392 wxString html_txt;
2393 ConvertMarkdown2Html( wxGetTranslation( msg ), html_txt );
2394 dlg->AddHTML_Text( html_txt );
2395 dlg->ShowModeless();
2396
2397 return dlg;
2398}
2399
2400
2401static struct SCH_LABEL_DESC
2402{
2404 {
2405 auto& labelShapeEnum = ENUM_MAP<LABEL_SHAPE>::Instance();
2406
2407 if( labelShapeEnum.Choices().GetCount() == 0 )
2408 {
2409 labelShapeEnum.Map( LABEL_SHAPE::LABEL_INPUT, _HKI( "Input" ) )
2410 .Map( LABEL_SHAPE::LABEL_OUTPUT, _HKI( "Output" ) )
2411 .Map( LABEL_SHAPE::LABEL_BIDI, _HKI( "Bidirectional" ) )
2412 .Map( LABEL_SHAPE::LABEL_TRISTATE, _HKI( "Tri-state" ) )
2413 .Map( LABEL_SHAPE::LABEL_PASSIVE, _HKI( "Passive" ) );
2414 }
2415
2420
2424
2428
2432
2437
2438 auto hasLabelShape =
2439 []( INSPECTABLE* aItem ) -> bool
2440 {
2441 if( SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( aItem ) )
2442 return label->IsType( { SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T, SCH_SHEET_PIN_T } );
2443
2444 return false;
2445 };
2446
2449 .SetAvailableFunc( hasLabelShape );
2450
2451 propMgr.Mask( TYPE_HASH( SCH_LABEL_BASE ), TYPE_HASH( EDA_TEXT ), _HKI( "Hyperlink" ) );
2452 }
2454
2455
2457{
2459 {
2460 auto& flagShapeEnum = ENUM_MAP<FLAG_SHAPE>::Instance();
2461
2462 if( flagShapeEnum.Choices().GetCount() == 0 )
2463 {
2464 flagShapeEnum.Map( FLAG_SHAPE::FLAG_DOT, _HKI( "Dot" ) )
2465 .Map( FLAG_SHAPE::FLAG_CIRCLE, _HKI( "Circle" ) )
2466 .Map( FLAG_SHAPE::FLAG_DIAMOND, _HKI( "Diamond" ) )
2467 .Map( FLAG_SHAPE::FLAG_RECTANGLE, _HKI( "Rectangle" ) );
2468 }
2469
2475
2477
2480
2481 propMgr.AddProperty( new PROPERTY<SCH_DIRECTIVE_LABEL, int>( _HKI( "Pin length" ),
2484
2485 propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Text" ) );
2486 propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Thickness" ) );
2487 propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Italic" ) );
2488 propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Bold" ) );
2489 propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Horizontal Justification" ) );
2490 propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Vertical Justification" ) );
2491 }
2493
2494
int color
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:114
BITMAPS
A list of all bitmap identifiers.
@ add_line_label
@ add_hierarchical_label
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
constexpr int GetSizeMax() const
Definition box2.h:235
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 const Vec GetEnd() const
Definition box2.h:212
constexpr void SetOrigin(const Vec &pos)
Definition box2.h:237
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition box2.h:146
constexpr size_type GetWidth() const
Definition box2.h:214
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition box2.h:658
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:168
constexpr const Vec & GetOrigin() const
Definition box2.h:210
constexpr void SetEnd(coord_type x, coord_type y)
Definition box2.h:297
constexpr void Offset(coord_type dx, coord_type dy)
Definition box2.h:259
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition box2.h:311
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:398
static std::vector< DANGLING_END_ITEM >::iterator get_lower_type(std::vector< DANGLING_END_ITEM > &aItemListByType, const DANGLING_END_T &aType)
Definition sch_item.cpp:815
static std::vector< DANGLING_END_ITEM >::iterator get_lower_pos(std::vector< DANGLING_END_ITEM > &aItemListByPos, const VECTOR2I &aPos)
Definition sch_item.cpp:804
Helper class used to store the state of schematic items that can be connected to other schematic item...
Definition sch_item.h:96
DANGLING_END_T GetType() const
Definition sch_item.h:132
EDA_ITEM * GetItem() const
Definition sch_item.h:130
VECTOR2I GetPosition() const
Definition sch_item.h:129
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
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
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.h:113
EDA_ITEM * GetParent() const
Definition eda_item.h:112
EDA_ITEM * m_parent
Owner.
Definition eda_item.h:528
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:80
int GetTextHeight() const
Definition eda_text.h:267
const VECTOR2I & GetTextPos() const
Definition eda_text.h:273
COLOR4D GetTextColor() const
Definition eda_text.h:270
bool IsItalic() const
Definition eda_text.h:169
const EDA_ANGLE & GetTextAngle() const
Definition eda_text.h:147
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:98
void SetTextPos(const VECTOR2I &aPoint)
Definition eda_text.cpp:589
void SetTextX(int aX)
Definition eda_text.cpp:595
KIFONT::FONT * GetFont() const
Definition eda_text.h:247
void SetTextY(int aY)
Definition eda_text.cpp:601
int GetTextWidth() const
Definition eda_text.h:264
BOX2I GetTextBox(const RENDER_SETTINGS *aSettings, int aLine=-1) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
Definition eda_text.cpp:755
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition eda_text.cpp:428
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition eda_text.h:200
bool Replace(const EDA_SEARCH_DATA &aSearchData)
Helper function used in search and replace dialog.
Definition eda_text.cpp:497
bool HasTextVars() const
Indicates the ShownText has text var references which need to be processed.
Definition eda_text.h:117
static wxString GotoPageHref(const wxString &aDestination)
Generate a href to a page in the current schematic.
wxString EvaluateText(const wxString &aText) const
Definition eda_text.cpp:652
virtual void cacheShownText()
Definition eda_text.cpp:634
const TEXT_ATTRIBUTES & GetAttributes() const
Definition eda_text.h:231
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
Definition eda_text.cpp:476
bool IsBold() const
Definition eda_text.h:184
virtual wxString GetShownText(bool aAllowExtraText, int aDepth=0) const
Return the string actually shown after processing of the base text.
Definition eda_text.h:109
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:281
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition eda_text.cpp:310
void SetMultilineAllowed(bool aAllow)
Definition eda_text.cpp:412
VECTOR2I GetTextSize() const
Definition eda_text.h:261
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition eda_text.cpp:420
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:241
static ENUM_MAP< T > & Instance()
Definition property.h:721
void SetDialogSizeInDU(int aWidth, int aHeight)
Set the dialog size, using a "logical" value.
void AddHTML_Text(const wxString &message)
Add HTML text (without any change) to message list.
void ShowModeless()
Show a modeless version of the dialog (without an OK button).
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
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:104
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
Definition kiid.h:49
const wxString GetName() const
Gets the name of this (maybe aggregate) netclass in a format for internal usage or for export to exte...
Definition netclass.cpp:322
COLOR4D GetSchematicColor(bool aIsForSave=false) const
Definition netclass.h:219
Base plotter engine class.
Definition plotter.h:121
virtual void FilledCircle(const VECTOR2I &pos, int diametre, void *aData)
Definition plotter.cpp:598
void MoveTo(const VECTOR2I &pos)
Definition plotter.h:262
RENDER_SETTINGS * RenderSettings()
Definition plotter.h:152
virtual void Bookmark(const BOX2I &aBox, const wxString &aName, const wxString &aGroupName=wxEmptyString)
Create a bookmark to a symbol.
Definition plotter.h:483
virtual void HyperlinkBox(const BOX2I &aBox, const wxString &aDestinationURL)
Create a clickable hyperlink with a rectangular click area.
Definition plotter.h:461
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
void PenFinish()
Definition plotter.h:278
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 PlotPoly(const std::vector< VECTOR2I > &aCornerList, FILL_T aFill, int aWidth, void *aData)=0
Draw a polygon ( filled or not ).
virtual void HyperlinkMenu(const BOX2I &aBox, const std::vector< wxString > &aDestURLs)
Create a clickable hyperlink menu with a rectangular click area.
Definition plotter.h:472
virtual void ThickCircle(const VECTOR2I &pos, int diametre, int width, void *aData)
Definition plotter.cpp:592
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
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.
These are loaded from Eeschema settings but then overwritten by the project settings.
Holds all the data relating to one schematic.
Definition schematic.h:88
wxString GetOperatingPoint(const wxString &aNetName, int aPrecision, const wxString &aRange)
SCHEMATIC_SETTINGS & Settings() const
std::map< wxString, std::set< int > > & GetPageRefsMap()
Definition schematic.h:228
std::map< int, wxString > GetVirtualPageToSheetPagesMap() const
std::map< int, wxString > GetVirtualPageToSheetNamesMap() const
SCH_SHEET_PATH & CurrentSheet() const
Definition schematic.h:171
bool ResolveCrossReference(wxString *token, int aDepth) const
Resolves text vars that refer to other items.
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
wxString GetNetName() const
const std::vector< std::shared_ptr< SCH_CONNECTION > > AllMembers() const
wxString LocalName() const
wxString Name(bool aIgnoreSheet=false) const
bool IsBus() const
void AppendInfoToMsgPanel(std::vector< MSG_PANEL_ITEM > &aList) const
Adds information about the connection object to aList.
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
void MirrorSpinStyle(bool aLeftRight) override
void RemoveConnectedRuleArea(SCH_RULE_AREA *aRuleArea)
Removes a specific rule area from the cache.
void ClearConnectedRuleAreas()
Removes all rule areas from the cache.
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
SCH_DIRECTIVE_LABEL(const VECTOR2I &aPos=VECTOR2I(0, 0))
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
void CreateGraphicShape(const RENDER_SETTINGS *aSettings, std::vector< VECTOR2I > &aPoints, const VECTOR2I &aPos) const override
Calculate the graphic shape (a polygon) associated to the text.
FLAG_SHAPE GetFlagShape() const
Definition sch_label.h:470
int GetPenWidth() const override
std::unordered_set< SCH_RULE_AREA * > m_connected_rule_areas
Cache of any rule areas with borders which this label connects to.
Definition sch_label.h:514
void swapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
void SetPinLength(int aLength)
Definition sch_label.h:474
virtual bool IsDangling() const override
Determines dangling state from connectivity and cached connected rule areas.
void AddConnectedRuleArea(SCH_RULE_AREA *aRuleArea)
Adds an entry to the connected rule area cache.
void SetFlagShape(FLAG_SHAPE aShape)
Definition sch_label.h:471
void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo) override
const std::unordered_set< SCH_RULE_AREA * > GetConnectedRuleAreas() const
int GetPinLength() const
Definition sch_label.h:473
Schematic editor (Eeschema) main window.
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this label.
std::vector< int > ViewGetLayers() const override
Return the all the layers within the VIEW the object is painted on.
void CreateGraphicShape(const RENDER_SETTINGS *aRenderSettings, std::vector< VECTOR2I > &aPoints, const VECTOR2I &aPos) const override
Calculate the graphic shape (a polygon) associated to the text.
bool ResolveTextVar(const SCH_SHEET_PATH *aPath, wxString *token, int aDepth) const override
Resolve any references to system tokens supported by the label.
VECTOR2I GetSchematicTextOffset(const RENDER_SETTINGS *aSettings) const override
This offset depends on the orientation, the type of text, and the area required to draw the associate...
void SetSpinStyle(SPIN_STYLE aSpinStyle) override
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
SCH_GLOBALLABEL(const VECTOR2I &aPos=VECTOR2I(0, 0), const wxString &aText=wxEmptyString)
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
const BOX2I GetBodyBoundingBox(const RENDER_SETTINGS *aSettings) const override
Return the bounding box of the label only, without taking in account its fields.
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
void SetSpinStyle(SPIN_STYLE aSpinStyle) override
void CreateGraphicShape(const RENDER_SETTINGS *aSettings, std::vector< VECTOR2I > &aPoints, const VECTOR2I &aPos) const override
Calculate the graphic shape (a polygon) associated to the text.
SCH_HIERLABEL(const VECTOR2I &aPos=VECTOR2I(0, 0), const wxString &aText=wxEmptyString, KICAD_T aType=SCH_HIER_LABEL_T)
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
VECTOR2I GetSchematicTextOffset(const RENDER_SETTINGS *aSettings) const override
This offset depends on the orientation, the type of text, and the area required to draw the associate...
virtual bool IsConnectable() const
Definition sch_item.h:505
SCH_ITEM & operator=(const SCH_ITEM &aPin)
Definition sch_item.cpp:75
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:244
void AddConnectionTo(const SCH_SHEET_PATH &aPath, SCH_ITEM *aItem)
Add a connection link between this item and another.
Definition sch_item.cpp:417
std::shared_ptr< NETCLASS > GetEffectiveNetClass(const SCH_SHEET_PATH *aSheet=nullptr) const
Definition sch_item.cpp:381
bool IsConnectivityDirty() const
Definition sch_item.h:566
AUTOPLACE_ALGO m_fieldsAutoplaced
Definition sch_item.h:755
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:352
const KIFONT::METRICS & GetFontMetrics() const
Definition sch_item.cpp:622
std::map< SCH_SHEET_PATH, SCH_ITEM_VEC, SHEET_PATH_CMP > m_connected_items
Store pointers to other items that are connected to this one, per sheet.
Definition sch_item.h:760
SCH_LAYER_ID m_layer
Definition sch_item.h:751
bool IsType(const std::vector< KICAD_T > &aScanTypes) const override
Check whether the item is one of the listed types.
Definition sch_item.h:182
bool operator==(const SCH_ITEM &aItem) const override
const wxString & GetCachedDriverName() const override
SCH_LABEL_BASE(const VECTOR2I &aPos, const wxString &aText, KICAD_T aType)
COLOR4D m_lastResolvedColor
Definition sch_label.h:383
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const override
void Move(const VECTOR2I &aMoveVector) override
Move the item by aMoveVector to a new position.
INSPECT_RESULT Visit(INSPECTOR inspector, void *testData, const std::vector< KICAD_T > &scanTypes) override
May be re-implemented for each derived class in order to handle all the types given by its member dat...
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
std::vector< int > ViewGetLayers() const override
Return the layers the item is drawn on (which may be more than its "home" layer)
bool HasCachedDriverName() const override
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
void GetEndPoints(std::vector< DANGLING_END_ITEM > &aItemList) override
Add the schematic item end points to aItemList if the item has end points.
bool AutoRotateOnPlacement() const
autoRotateOnPlacement
SCH_LABEL_BASE & operator=(const SCH_LABEL_BASE &aLabel)
std::vector< SCH_FIELD > m_fields
Definition sch_label.h:375
CONNECTION_TYPE m_connectionType
Definition sch_label.h:379
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
int GetNextFieldOrdinal() const
Return the next ordinal for a user field for this label.
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.
void SetLabelShape(LABEL_SHAPE aShape)
bool HasConnectivityChanges(const SCH_ITEM *aItem, const SCH_SHEET_PATH *aInstance=nullptr) const override
Check if aItem has connectivity changes against this object.
SPIN_STYLE GetSpinStyle() const
void GetIntersheetRefs(const SCH_SHEET_PATH *aPath, std::vector< std::pair< wxString, wxString > > *pages)
Build an array of { pageNumber, pageName } pairs.
void MirrorSpinStyle(bool aLeftRight) override
std::vector< VECTOR2I > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
COLOR4D GetLabelColor() const
LABEL_FLAG_SHAPE GetShape() const
Definition sch_label.h:180
const BOX2I GetBoundingBox() const override
Return the bounding box of the label including its fields.
bool IsType(const std::vector< KICAD_T > &aScanTypes) const override
Check whether the item is one of the listed types.
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
void SetPosition(const VECTOR2I &aPosition) override
void swapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
virtual bool ResolveTextVar(const SCH_SHEET_PATH *aPath, wxString *token, int aDepth) const
Resolve any references to system tokens supported by the label.
LABEL_SHAPE GetLabelShape() const
Definition sch_label.h:177
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode) override
bool m_autoRotateOnPlacement
Definition sch_label.h:381
wxString m_cached_driver_name
Definition sch_label.h:385
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
int GetLabelBoxExpansion(const RENDER_SETTINGS *aSettings=nullptr) const
bool IncrementLabel(int aIncrement)
Increment the label text if it ends with a number.
void SetAutoRotateOnPlacement(bool autoRotate=true)
void cacheShownText() override
void Rotate90(bool aClockwise) override
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.
static const wxString GetDefaultFieldName(const wxString &aName, bool aUseDefaultName)
void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo) override
LABEL_FLAG_SHAPE m_shape
Definition sch_label.h:377
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars & fields for this label.
virtual const BOX2I GetBodyBoundingBox(const RENDER_SETTINGS *aSettings) const
Return the bounding box of the label only, without taking in account its fields.
virtual void CreateGraphicShape(const RENDER_SETTINGS *aSettings, std::vector< VECTOR2I > &aPoints, const VECTOR2I &Pos) const
Calculate the graphic shape (a polygon) associated to the text.
Definition sch_label.h:307
std::vector< SCH_FIELD > & GetFields()
Definition sch_label.h:212
bool UpdateDanglingState(std::vector< DANGLING_END_ITEM > &aItemListByType, std::vector< DANGLING_END_ITEM > &aItemListByPos, const SCH_SHEET_PATH *aPath=nullptr) override
Test the schematic item to aItemList to check if it's dangling state has changed.
VECTOR2I GetSchematicTextOffset(const RENDER_SETTINGS *aSettings) const override
This offset depends on the orientation, the type of text, and the area required to draw the associate...
virtual void SetSpinStyle(SPIN_STYLE aSpinStyle)
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 ...
double Similarity(const SCH_ITEM &aItem) const override
Return a measure of how likely the other object is to represent the same object.
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
const BOX2I GetBodyBoundingBox(const RENDER_SETTINGS *aSettings) const override
Return the bounding box of the label only, without taking in account its fields.
SCH_LABEL(const VECTOR2I &aPos=VECTOR2I(0, 0), const wxString &aText=wxEmptyString)
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
std::vector< SCH_SHEET_PATH > & GetClientSheetPaths()
Return the number of times this screen is used.
Definition sch_screen.h:186
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:117
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
size_t size() const
Forwarded method from std::vector.
int GetVirtualPageNumber() const
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:47
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:116
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition sch_sheet.h:187
bool ResolveTextVar(const SCH_SHEET_PATH *aPath, wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the sheet.
void swapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
Definition sch_text.cpp:232
KIFONT::FONT * GetDrawFont(const RENDER_SETTINGS *aSettings) const override
Definition sch_text.cpp:285
void Move(const VECTOR2I &aMoveVector) override
Move the item by aMoveVector to a new position.
Definition sch_text.h:115
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
Definition sch_text.cpp:159
static HTML_MESSAGE_BOX * ShowSyntaxHelp(wxWindow *aParentWindow)
VECTOR2I GetPosition() const override
Definition sch_text.h:150
virtual void Rotate90(bool aClockwise)
Definition sch_text.cpp:210
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
Definition sch_text.cpp:120
double Similarity(const SCH_ITEM &aItem) const override
Return a measure of how likely the other object is to represent the same object.
Definition sch_text.cpp:617
int GetPenWidth() const override
Definition sch_text.cpp:279
virtual void MirrorSpinStyle(bool aLeftRight)
Definition sch_text.cpp:222
bool operator==(const SCH_ITEM &aItem) const override
Definition sch_text.cpp:600
int GetTextOffset(const RENDER_SETTINGS *aSettings=nullptr) const
Definition sch_text.cpp:264
SCH_TEXT(const VECTOR2I &aPos={ 0, 0 }, const wxString &aText=wxEmptyString, SCH_LAYER_ID aLayer=LAYER_NOTES, KICAD_T aType=SCH_TEXT_T)
Definition sch_text.cpp:51
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
SPIN_STYLE MirrorX()
Mirror the label spin style across the X axis or simply swaps up and bottom.
SPIN m_spin
Definition sch_label.h:91
SPIN_STYLE()=default
SPIN_STYLE MirrorY()
Mirror the label spin style across the Y axis or simply swaps left and right.
unsigned CCWRotationsTo(const SPIN_STYLE &aOther) const
Get CCW rotation needed to get to the given spin style.
SPIN_STYLE RotateCCW()
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
Definition common.cpp:59
#define DEFAULT_LABEL_SIZE_RATIO
The offset of the pin name string from the end of the pin in mils.
#define DANGLING_SYMBOL_SIZE
The size of the rectangle indicating an unconnected wire or label.
#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
static constexpr EDA_ANGLE ANGLE_270
Definition eda_angle.h:416
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:415
RECURSE_MODE
Definition eda_item.h:50
INSPECT_RESULT
Definition eda_item.h:44
const INSPECTOR_FUNC & INSPECTOR
std::function passed to nested users by ref, avoids copying std::function.
Definition eda_item.h:91
@ NONE
Definition eda_shape.h:69
@ NO_FILL
Definition eda_shape.h:57
a few functions useful in geometry calculations.
KICOMMON_API bool IncrementString(wxString &name, int aIncrement)
Generic string incrementer.
Definition increment.cpp:33
@ LAYER_DANGLING
Definition layer_ids.h:477
@ LAYER_DEVICE
Definition layer_ids.h:466
@ LAYER_HIERLABEL
Definition layer_ids.h:457
@ LAYER_GLOBLABEL
Definition layer_ids.h:456
@ LAYER_NOTES
Definition layer_ids.h:467
@ LAYER_BUS
Definition layer_ids.h:453
@ LAYER_FIELDS
Definition layer_ids.h:462
@ LAYER_LOCLABEL
Definition layer_ids.h:455
@ LAYER_NETCLASS_REFS
Definition layer_ids.h:464
@ LAYER_SELECTION_SHADOWS
Definition layer_ids.h:495
@ LAYER_INTERSHEET_REFS
Definition layer_ids.h:463
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition macros.h:83
constexpr T MIRRORVAL(T aPoint, T aMirrorRef)
Returns the mirror of aPoint relative to the aMirrorRef.
Definition mirror.h:36
Message panel definition file.
bool BoxHitTest(const VECTOR2I &aHitPoint, const BOX2I &aHittee, int aAccuracy)
Perform a point-to-box hit test.
KICOMMON_API wxString EllipsizeMenuText(const wxString &aString)
Ellipsize text (at the end) to be no more than 36 characters.
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput)
Definition api_utils.cpp:86
KICOMMON_API void PackVector2(types::Vector2 &aOutput, const VECTOR2I &aInput)
Definition api_utils.cpp:79
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
#define _HKI(x)
Definition page_info.cpp:44
see class PGM_BASE
#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:823
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition property.h:63
#define REGISTER_TYPE(x)
CONNECTION_TYPE
@ BUS
This item represents a bus vector.
@ NET
This item represents a net.
@ NONE
No connection to this item.
const SCH_FIELD * FindField(const std::vector< SCH_FIELD > &aFields, FIELD_T aFieldId)
Definition sch_field.h:362
int NextFieldOrdinal(const std::vector< SCH_FIELD > &aFields)
Definition sch_field.h:351
AUTOPLACE_ALGO
Definition sch_item.h:68
@ AUTOPLACE_MANUAL
Definition sch_item.h:71
@ AUTOPLACE_AUTO
Definition sch_item.h:70
@ NO_CONNECT_END
Definition sch_item.h:87
@ SHEET_LABEL_END
Definition sch_item.h:86
@ LABEL_END
Definition sch_item.h:83
@ BUS_END
Definition sch_item.h:80
@ PIN_END
Definition sch_item.h:82
@ WIRE_END
Definition sch_item.h:79
std::vector< SCH_ITEM * > SCH_ITEM_VEC
Definition sch_item.h:156
static int TemplateIN_HI[]
Definition sch_label.cpp:65
static int TemplateUNSPC_HI[]
Definition sch_label.cpp:75
static int TemplateOUT_HN[]
Definition sch_label.cpp:69
static int Template3STATE_HN[]
Definition sch_label.cpp:84
static int TemplateBIDI_HN[]
Definition sch_label.cpp:79
static int * TemplateShape[5][4]
Definition sch_label.cpp:89
static int TemplateIN_HN[]
Definition sch_label.cpp:64
static int TemplateIN_BOTTOM[]
Definition sch_label.cpp:67
static int TemplateUNSPC_HN[]
Definition sch_label.cpp:74
static int Template3STATE_BOTTOM[]
Definition sch_label.cpp:87
static int TemplateBIDI_BOTTOM[]
Definition sch_label.cpp:82
static struct SCH_LABEL_DESC _SCH_LABEL_DESC
static int Template3STATE_UP[]
Definition sch_label.cpp:86
static int TemplateOUT_UP[]
Definition sch_label.cpp:71
static int TemplateOUT_HI[]
Definition sch_label.cpp:70
static int TemplateUNSPC_UP[]
Definition sch_label.cpp:76
static int TemplateUNSPC_BOTTOM[]
Definition sch_label.cpp:77
static int TemplateOUT_BOTTOM[]
Definition sch_label.cpp:72
static int Template3STATE_HI[]
Definition sch_label.cpp:85
static int TemplateIN_UP[]
Definition sch_label.cpp:66
wxString getElectricalTypeLabel(LABEL_FLAG_SHAPE aType)
Definition sch_label.cpp:99
static int TemplateBIDI_UP[]
Definition sch_label.cpp:81
static int TemplateBIDI_HI[]
Definition sch_label.cpp:80
static struct SCH_DIRECTIVE_LABEL_DESC _SCH_DIRECTIVE_LABEL_DESC
FLAG_SHAPE
Definition sch_label.h:126
@ FLAG_CIRCLE
Definition sch_label.h:128
@ FLAG_RECTANGLE
Definition sch_label.h:130
@ FLAG_DOT
Definition sch_label.h:127
@ FLAG_DIAMOND
Definition sch_label.h:129
LABEL_FLAG_SHAPE
Definition sch_label.h:99
@ L_BIDI
Definition sch_label.h:102
@ L_TRISTATE
Definition sch_label.h:103
@ L_UNSPECIFIED
Definition sch_label.h:104
@ F_DOT
Definition sch_label.h:107
@ F_ROUND
Definition sch_label.h:108
@ L_OUTPUT
Definition sch_label.h:101
@ F_DIAMOND
Definition sch_label.h:109
@ L_INPUT
Definition sch_label.h:100
@ F_RECTANGLE
Definition sch_label.h:110
LABEL_SHAPE
Definition sch_label.h:117
@ LABEL_BIDI
Definition sch_label.h:120
@ LABEL_INPUT
Definition sch_label.h:118
@ LABEL_OUTPUT
Definition sch_label.h:119
@ LABEL_PASSIVE
Definition sch_label.h:122
@ LABEL_TRISTATE
Definition sch_label.h:121
wxString UnescapeString(const wxString &aSource)
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
void ConvertMarkdown2Html(const wxString &aMarkdownInput, wxString &aHtmlOutput)
bool m_PDFPropertyPopups
Definition sch_plotter.h:64
bool m_PDFHierarchicalLinks
Definition sch_plotter.h:65
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
@ INTERSHEET_REFS
Global label cross-reference page numbers.
VECTOR2I end
const int accuracy
int delta
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_CENTER
bool TestSegmentHit(const VECTOR2I &aRefPoint, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aDist)
Test if aRefPoint is with aDistance on the line defined by aStart and aEnd.
Definition trigo.cpp:175
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
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:78
@ SCH_ITEM_LOCATE_WIRE_T
Definition typeinfo.h:190
@ SCH_FIELD_T
Definition typeinfo.h:154
@ SCH_DIRECTIVE_LABEL_T
Definition typeinfo.h:175
@ SCH_LABEL_T
Definition typeinfo.h:171
@ SCH_LOCATE_ANY_T
Definition typeinfo.h:203
@ SCH_ITEM_LOCATE_BUS_T
Definition typeinfo.h:191
@ SCH_HIER_LABEL_T
Definition typeinfo.h:173
@ SCH_LABEL_LOCATE_ANY_T
Definition typeinfo.h:195
@ SCH_LABEL_LOCATE_WIRE_T
Definition typeinfo.h:196
@ SCH_SHEET_PIN_T
Definition typeinfo.h:178
@ SCH_LABEL_LOCATE_BUS_T
Definition typeinfo.h:197
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:172
@ SCH_PIN_T
Definition typeinfo.h:157
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695