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#include <properties/property.h>
59
60
61/* Coding polygons for global symbol graphic shapes.
62 * the first parml is the number of corners
63 * others are the corners coordinates in reduced units
64 * the real coordinate is the reduced coordinate * text half size
65 */
66static int TemplateIN_HN[] = { 6, 0, 0, -1, -1, -2, -1, -2, 1, -1, 1, 0, 0 };
67static int TemplateIN_HI[] = { 6, 0, 0, 1, 1, 2, 1, 2, -1, 1, -1, 0, 0 };
68static int TemplateIN_UP[] = { 6, 0, 0, 1, -1, 1, -2, -1, -2, -1, -1, 0, 0 };
69static int TemplateIN_BOTTOM[] = { 6, 0, 0, 1, 1, 1, 2, -1, 2, -1, 1, 0, 0 };
70
71static int TemplateOUT_HN[] = { 6, -2, 0, -1, 1, 0, 1, 0, -1, -1, -1, -2, 0 };
72static int TemplateOUT_HI[] = { 6, 2, 0, 1, -1, 0, -1, 0, 1, 1, 1, 2, 0 };
73static int TemplateOUT_UP[] = { 6, 0, -2, 1, -1, 1, 0, -1, 0, -1, -1, 0, -2 };
74static int TemplateOUT_BOTTOM[] = { 6, 0, 2, 1, 1, 1, 0, -1, 0, -1, 1, 0, 2 };
75
76static int TemplateUNSPC_HN[] = { 5, 0, -1, -2, -1, -2, 1, 0, 1, 0, -1 };
77static int TemplateUNSPC_HI[] = { 5, 0, -1, 2, -1, 2, 1, 0, 1, 0, -1 };
78static int TemplateUNSPC_UP[] = { 5, 1, 0, 1, -2, -1, -2, -1, 0, 1, 0 };
79static int TemplateUNSPC_BOTTOM[] = { 5, 1, 0, 1, 2, -1, 2, -1, 0, 1, 0 };
80
81static int TemplateBIDI_HN[] = { 5, 0, 0, -1, -1, -2, 0, -1, 1, 0, 0 };
82static int TemplateBIDI_HI[] = { 5, 0, 0, 1, -1, 2, 0, 1, 1, 0, 0 };
83static int TemplateBIDI_UP[] = { 5, 0, 0, -1, -1, 0, -2, 1, -1, 0, 0 };
84static int TemplateBIDI_BOTTOM[] = { 5, 0, 0, -1, 1, 0, 2, 1, 1, 0, 0 };
85
86static int Template3STATE_HN[] = { 5, 0, 0, -1, -1, -2, 0, -1, 1, 0, 0 };
87static int Template3STATE_HI[] = { 5, 0, 0, 1, -1, 2, 0, 1, 1, 0, 0 };
88static int Template3STATE_UP[] = { 5, 0, 0, -1, -1, 0, -2, 1, -1, 0, 0 };
89static int Template3STATE_BOTTOM[] = { 5, 0, 0, -1, 1, 0, 2, 1, 1, 0, 0 };
90
96
97
99{
100 switch( aType )
101 {
102 case LABEL_FLAG_SHAPE::L_INPUT: return _( "Input" );
103 case LABEL_FLAG_SHAPE::L_OUTPUT: return _( "Output" );
104 case LABEL_FLAG_SHAPE::L_BIDI: return _( "Bidirectional" );
105 case LABEL_FLAG_SHAPE::L_TRISTATE: return _( "Tri-State" );
106 case LABEL_FLAG_SHAPE::L_UNSPECIFIED: return _( "Passive" );
107 default: return wxT( "???" );
108 }
109}
110
111
113{
114 SPIN newSpin = m_spin;
115
116 switch( m_spin )
117 {
118 case SPIN_STYLE::LEFT: newSpin = SPIN_STYLE::BOTTOM; break;
119 case SPIN_STYLE::BOTTOM: newSpin = SPIN_STYLE::RIGHT; break;
120 case SPIN_STYLE::RIGHT: newSpin = SPIN_STYLE::UP; break;
121 case SPIN_STYLE::UP: newSpin = SPIN_STYLE::LEFT; break;
122 }
123
124 return SPIN_STYLE( newSpin );
125}
126
127
129{
130 SPIN newSpin = m_spin;
131
132 switch( m_spin )
133 {
134 case SPIN_STYLE::UP: newSpin = SPIN_STYLE::BOTTOM; break;
135 case SPIN_STYLE::BOTTOM: newSpin = SPIN_STYLE::UP; break;
136 case SPIN_STYLE::LEFT: break;
137 case SPIN_STYLE::RIGHT: break;
138 }
139
140 return SPIN_STYLE( newSpin );
141}
142
143
145{
146 SPIN newSpin = m_spin;
147
148 switch( m_spin )
149 {
150 case SPIN_STYLE::LEFT: newSpin = SPIN_STYLE::RIGHT; break;
151 case SPIN_STYLE::RIGHT: newSpin = SPIN_STYLE::LEFT; break;
152 case SPIN_STYLE::UP: break;
153 case SPIN_STYLE::BOTTOM: break;
154 }
155
156 return SPIN_STYLE( newSpin );
157}
158
159
160unsigned SPIN_STYLE::CCWRotationsTo( const SPIN_STYLE& aOther ) const
161{
162 return ( ( (int) m_spin - (int) aOther.m_spin ) % 4 + 4 ) % 4;
163}
164
165
166SCH_LABEL_BASE::SCH_LABEL_BASE( const VECTOR2I& aPos, const wxString& aText, KICAD_T aType ) :
167 SCH_TEXT( aPos, aText, LAYER_NOTES, aType ),
170 m_isDangling( true ),
173{
174 SetMultilineAllowed( false );
175
176 if( !HasTextVars() )
178}
179
180
182 SCH_TEXT( aLabel ),
183 m_shape( aLabel.m_shape ),
185 m_isDangling( aLabel.m_isDangling ),
189{
190 SetMultilineAllowed( false );
191
192 m_fields = aLabel.m_fields;
193
194 for( SCH_FIELD& field : m_fields )
195 field.SetParent( this );
196}
197
198
200{
201 SCH_TEXT::operator=( aLabel );
202
203 m_fields = aLabel.m_fields;
204
205 for( SCH_FIELD& field : m_fields )
206 field.SetParent( this );
207
208 m_shape = aLabel.m_shape;
210 m_isDangling = aLabel.m_isDangling;
214
215 return *this;
216}
217
218
219const wxString SCH_LABEL_BASE::GetDefaultFieldName( const wxString& aName, bool aUseDefaultName )
220{
221 if( aName == wxT( "Intersheetrefs" ) )
222 return _( "Sheet References" );
223 else if( aName == wxT( "Netclass" ) )
224 return _( "Net Class" );
225 else if( aName.IsEmpty() && aUseDefaultName )
226 return _( "Field" );
227 else
228 return aName;
229}
230
231
236
237
238bool SCH_LABEL_BASE::IsType( const std::vector<KICAD_T>& aScanTypes ) const
239{
240 static const std::vector<KICAD_T> wireAndPinTypes = { SCH_ITEM_LOCATE_WIRE_T, SCH_PIN_T };
241 static const std::vector<KICAD_T> busTypes = { SCH_ITEM_LOCATE_BUS_T };
242
243 if( SCH_TEXT::IsType( aScanTypes ) )
244 return true;
245
246 for( KICAD_T scanType : aScanTypes )
247 {
248 if( scanType == SCH_LABEL_LOCATE_ANY_T )
249 return true;
250 }
251
252 wxCHECK_MSG( Schematic(), false, wxT( "No parent SCHEMATIC set for SCH_LABEL!" ) );
253
254 // Ensure m_connected_items for Schematic()->CurrentSheet() exists.
255 // Can be not the case when "this" is living in clipboard
256 if( m_connected_items.find( Schematic()->CurrentSheet() ) == m_connected_items.end() )
257 return false;
258
259 const SCH_ITEM_VEC& item_set = m_connected_items.at( Schematic()->CurrentSheet() );
260
261 for( KICAD_T scanType : aScanTypes )
262 {
263 if( scanType == SCH_LABEL_LOCATE_WIRE_T )
264 {
265 for( SCH_ITEM* connection : item_set )
266 {
267 if( connection->IsType( wireAndPinTypes ) )
268 return true;
269 }
270 }
271
272 if( scanType == SCH_LABEL_LOCATE_BUS_T )
273 {
274 for( SCH_ITEM* connection : item_set )
275 {
276 if( connection->IsType( busTypes ) )
277 return true;
278 }
279 }
280 }
281
282 return false;
283}
284
285
287{
288 SCH_TEXT::swapData( aItem );
289
290 SCH_LABEL_BASE* label = static_cast<SCH_LABEL_BASE*>( aItem );
291
292 m_fields.swap( label->m_fields );
293 std::swap( m_fieldsAutoplaced, label->m_fieldsAutoplaced );
294
295 for( SCH_FIELD& field : m_fields )
296 field.SetParent( this );
297
298 for( SCH_FIELD& field : label->m_fields )
299 field.SetParent( label );
300
301 std::swap( m_shape, label->m_shape );
302 std::swap( m_connectionType, label->m_connectionType );
303 std::swap( m_isDangling, label->m_isDangling );
304 std::swap( m_lastResolvedColor, label->m_lastResolvedColor );
305}
306
307
317
318
320{
321 m_shape = (LABEL_FLAG_SHAPE) aShape;
322
323 static bool s_inUpdate = false;
324
325 if( s_inUpdate )
326 return;
327
328 s_inUpdate = true;
329
330 if( Type() == SCH_HIER_LABEL_T )
331 {
332 SCH_HIERLABEL* label = static_cast<SCH_HIERLABEL*>( this );
333 SCH_SCREEN* screen = dynamic_cast<SCH_SCREEN*>( label->GetParent() );
334
335 if( screen )
336 {
337 const wxString& text = label->GetText();
338
339 for( SCH_ITEM* item : screen->Items().OfType( SCH_HIER_LABEL_T ) )
340 {
341 SCH_HIERLABEL* other = static_cast<SCH_HIERLABEL*>( item );
342
343 if( other != label && other->GetText() == text )
344 other->SetLabelShape( aShape );
345 }
346
347 for( const SCH_SHEET_PATH& sheetPath : screen->GetClientSheetPaths() )
348 {
349 SCH_SHEET* sheet = sheetPath.Last();
350
351 if( sheet )
352 {
353 for( SCH_SHEET_PIN* pin : sheet->GetPins() )
354 {
355 if( pin->GetText() == text )
356 pin->SetLabelShape( aShape );
357 }
358 }
359 }
360 }
361 }
362 else if( Type() == SCH_SHEET_PIN_T )
363 {
364 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( this );
365 SCH_SHEET* parent = pin->GetParent();
366
367 if( parent )
368 {
369 const wxString& text = pin->GetText();
370 SCH_SCREEN* screen = parent->GetScreen();
371
372 if( screen )
373 {
374 for( SCH_ITEM* item : screen->Items().OfType( SCH_HIER_LABEL_T ) )
375 {
376 SCH_HIERLABEL* hlabel = static_cast<SCH_HIERLABEL*>( item );
377
378 if( hlabel->GetText() == text )
379 hlabel->SetLabelShape( aShape );
380 }
381 }
382
383 for( SCH_SHEET_PIN* other : parent->GetPins() )
384 {
385 if( other != pin && other->GetText() == text )
386 other->SetLabelShape( aShape );
387 }
388 }
389 }
390
391 s_inUpdate = false;
392}
393
394
396{
397 // Assume "Right" and Left" mean which side of the anchor the text will be on
398 // Thus we want to left justify text up against the anchor if we are on the right
399 switch( aSpinStyle )
400 {
401 default: wxFAIL_MSG( "Bad spin style" ); KI_FALLTHROUGH;
402
403 case SPIN_STYLE::RIGHT: // Horiz Normal Orientation
406 break;
407
408 case SPIN_STYLE::UP: // Vert Orientation UP
411 break;
412
413 case SPIN_STYLE::LEFT: // Horiz Orientation - Right justified
416 break;
417
418 case SPIN_STYLE::BOTTOM: // Vert Orientation BOTTOM
421 break;
422 }
423
425}
426
427
429{
431 {
433 return SPIN_STYLE::BOTTOM;
434 else
435 return SPIN_STYLE::UP;
436 }
437 else
438 {
440 return SPIN_STYLE::LEFT;
441 else
442 return SPIN_STYLE::RIGHT;
443 }
444}
445
446
448{
449 VECTOR2I text_offset;
450
451 // add an offset to x (or y) position to aid readability of text on a wire or line
452 int dist = GetTextOffset( aSettings ) + GetPenWidth();
453
454 switch( GetSpinStyle() )
455 {
456 case SPIN_STYLE::UP:
457 case SPIN_STYLE::BOTTOM: text_offset.x = -dist; break; // Vert Orientation
458 default:
459 case SPIN_STYLE::LEFT:
460 case SPIN_STYLE::RIGHT: text_offset.y = -dist; break; // Horiz Orientation
461 }
462
463 return text_offset;
464}
465
466
467void SCH_LABEL_BASE::SetPosition( const VECTOR2I& aPosition )
468{
469 VECTOR2I offset = aPosition - GetTextPos();
470 Move( offset );
471}
472
473
474void SCH_LABEL_BASE::Move( const VECTOR2I& aMoveVector )
475{
476 SCH_TEXT::Move( aMoveVector );
477
478 for( SCH_FIELD& field : m_fields )
479 field.Offset( aMoveVector );
480}
481
482
483void SCH_LABEL_BASE::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
484{
485 VECTOR2I pt = GetTextPos();
486 RotatePoint( pt, aCenter, aRotateCCW ? ANGLE_90 : ANGLE_270 );
487 VECTOR2I offset = pt - GetTextPos();
488
489 Rotate90( !aRotateCCW );
490
491 SetTextPos( GetTextPos() + offset );
492
493 for( SCH_FIELD& field : m_fields )
494 field.SetTextPos( field.GetTextPos() + offset );
495}
496
497
498void SCH_LABEL_BASE::Rotate90( bool aClockwise )
499{
500 SCH_TEXT::Rotate90( aClockwise );
501
503 {
505 }
506 else
507 {
508 for( SCH_FIELD& field : m_fields )
509 field.Rotate( GetPosition(), !aClockwise );
510 }
511}
512
513
514void SCH_LABEL_BASE::MirrorSpinStyle( bool aLeftRight )
515{
516 SCH_TEXT::MirrorSpinStyle( aLeftRight );
517
518 for( SCH_FIELD& field : m_fields )
519 {
520 if( ( aLeftRight && field.GetTextAngle().IsHorizontal() )
521 || ( !aLeftRight && field.GetTextAngle().IsVertical() ) )
522 {
523 if( field.GetHorizJustify() == GR_TEXT_H_ALIGN_LEFT )
524 field.SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
525 else
526 field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
527 }
528
529 VECTOR2I pos = field.GetTextPos();
531
532 if( aLeftRight )
533 pos.x = GetPosition().x + delta.x;
534 else
535 pos.y = GetPosition().y + delta.y;
536
537 field.SetTextPos( pos );
538 }
539}
540
541
543{
544 VECTOR2I old_pos = GetPosition();
546
547 for( SCH_FIELD& field : m_fields )
548 {
549 if( field.GetTextAngle() == ANGLE_HORIZONTAL )
550 field.FlipHJustify();
551
552 VECTOR2I pos = field.GetTextPos();
553 VECTOR2I delta = old_pos - pos;
554 pos.x = GetPosition().x + delta.x;
555
556 field.SetPosition( pos );
557 }
558}
559
560
562{
563 VECTOR2I old_pos = GetPosition();
565
566 for( SCH_FIELD& field : m_fields )
567 {
568 if( field.GetTextAngle() == ANGLE_VERTICAL )
569 field.FlipHJustify();
570
571 VECTOR2I pos = field.GetTextPos();
572 VECTOR2I delta = old_pos - pos;
573 pos.y = GetPosition().y + delta.y;
574
575 field.SetPosition( pos );
576 }
577}
578
579
580bool SCH_LABEL_BASE::IncrementLabel( int aIncrement )
581{
582 wxString text = GetText();
583
584 if( IncrementString( text, aIncrement ) )
585 {
586 SetText( text );
587 return true;
588 }
589
590 return false;
591}
592
593
594bool SCH_LABEL_BASE::operator==( const SCH_ITEM& aOther ) const
595{
596 const SCH_LABEL_BASE* other = dynamic_cast<const SCH_LABEL_BASE*>( &aOther );
597
598 if( !other )
599 return false;
600
601 if( m_shape != other->m_shape )
602 return false;
603
604 if( m_connectionType != other->m_connectionType )
605 return false;
606
607 if( m_fields.size() != other->m_fields.size() )
608 return false;
609
610 for( size_t ii = 0; ii < m_fields.size(); ++ii )
611 {
612 if( !( m_fields[ii] == other->m_fields[ii] ) )
613 return false;
614 }
615
616 return SCH_TEXT::operator==( aOther );
617}
618
619
620double SCH_LABEL_BASE::Similarity( const SCH_ITEM& aOther ) const
621{
622 const SCH_LABEL_BASE* other = dynamic_cast<const SCH_LABEL_BASE*>( &aOther );
623
624 if( !other )
625 return 0.0;
626
627 if( m_Uuid == other->m_Uuid )
628 return 1.0;
629
630 double similarity = SCH_TEXT::Similarity( aOther );
631
632 if( typeid( *this ) != typeid( aOther ) )
633 similarity *= 0.9;
634
635 if( m_shape == other->m_shape )
636 similarity *= 0.9;
637
638 if( m_connectionType == other->m_connectionType )
639 similarity *= 0.9;
640
641 for( size_t ii = 0; ii < m_fields.size(); ++ii )
642 {
643 if( ii >= other->m_fields.size() )
644 break;
645
646 similarity *= m_fields[ii].Similarity( other->m_fields[ii] );
647 }
648
649 int diff = std::abs( int( m_fields.size() ) - int( other->m_fields.size() ) );
650
651 similarity *= std::pow( 0.9, diff );
652
653 return similarity;
654}
655
656
658{
659 int margin = GetTextOffset() * 2;
660 int labelLen = GetBodyBoundingBox( nullptr ).GetSizeMax();
661 int accumulated = GetTextHeight() / 2;
662
663 if( Type() == SCH_GLOBAL_LABEL_T )
664 accumulated += margin + GetPenWidth() + margin;
665
666 for( SCH_FIELD& field : m_fields )
667 {
668 VECTOR2I offset( 0, 0 );
669
670 switch( GetSpinStyle() )
671 {
672 default:
673 case SPIN_STYLE::LEFT:
674 field.SetTextAngle( ANGLE_HORIZONTAL );
675 field.SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
676
677 if( field.GetId() == FIELD_T::INTERSHEET_REFS )
678 offset.x = -( labelLen + margin );
679 else
680 offset.y = accumulated + field.GetTextHeight() / 2;
681
682 break;
683
684 case SPIN_STYLE::UP:
685 field.SetTextAngle( ANGLE_VERTICAL );
686 field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
687
688 if( field.GetId() == FIELD_T::INTERSHEET_REFS )
689 offset.y = -( labelLen + margin );
690 else
691 offset.x = accumulated + field.GetTextHeight() / 2;
692
693 break;
694
696 field.SetTextAngle( ANGLE_HORIZONTAL );
697 field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
698
699 if( field.GetId() == FIELD_T::INTERSHEET_REFS )
700 offset.x = labelLen + margin;
701 else
702 offset.y = accumulated + field.GetTextHeight() / 2;
703
704 break;
705
707 field.SetTextAngle( ANGLE_VERTICAL );
708 field.SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
709
710 if( field.GetId() == FIELD_T::INTERSHEET_REFS )
711 offset.y = labelLen + margin;
712 else
713 offset.x = accumulated + field.GetTextHeight() / 2;
714
715 break;
716 }
717
718 field.SetTextPos( GetTextPos() + offset );
719
720 if( field.GetId() == FIELD_T::INTERSHEET_REFS )
721 accumulated += field.GetTextHeight() + margin;
722 }
723
724 if( aAlgo == AUTOPLACE_AUTO || aAlgo == AUTOPLACE_MANUAL )
725 m_fieldsAutoplaced = aAlgo;
726}
727
728
729void SCH_LABEL_BASE::GetIntersheetRefs( const SCH_SHEET_PATH* aPath, std::vector<std::pair<wxString, wxString>>* pages )
730{
731 wxCHECK( pages, /* void */ );
732
733 if( Schematic() )
734 {
735 wxString resolvedLabel = GetShownText( &Schematic()->CurrentSheet(), false );
736 auto it = Schematic()->GetPageRefsMap().find( resolvedLabel );
737
738 if( it != Schematic()->GetPageRefsMap().end() )
739 {
740 std::vector<int> pageListCopy;
741
742 pageListCopy.insert( pageListCopy.end(), it->second.begin(), it->second.end() );
743
744 if( !Schematic()->Settings().m_IntersheetRefsListOwnPage )
745 {
746 int currentPage = Schematic()->CurrentSheet().GetVirtualPageNumber();
747 std::erase( pageListCopy, currentPage );
748
749 if( pageListCopy.empty() )
750 return;
751 }
752
753 std::sort( pageListCopy.begin(), pageListCopy.end() );
754
755 std::map<int, wxString> sheetPages = Schematic()->GetVirtualPageToSheetPagesMap();
756 std::map<int, wxString> sheetNames = Schematic()->GetVirtualPageToSheetNamesMap();
757
758 for( int pageNum : pageListCopy )
759 pages->push_back( { sheetPages[pageNum], sheetNames[pageNum] } );
760 }
761 }
762}
763
764
765void SCH_LABEL_BASE::GetContextualTextVars( wxArrayString* aVars ) const
766{
767 for( const SCH_FIELD& field : m_fields )
768 {
769 if( field.IsMandatory() )
770 aVars->push_back( field.GetCanonicalName().Upper() );
771 else
772 aVars->push_back( field.GetName() );
773 }
774
775 aVars->push_back( wxT( "OP" ) );
776 aVars->push_back( wxT( "CONNECTION_TYPE" ) );
777 aVars->push_back( wxT( "SHORT_NET_NAME" ) );
778 aVars->push_back( wxT( "NET_NAME" ) );
779 aVars->push_back( wxT( "NET_CLASS" ) );
780}
781
782
783bool SCH_LABEL_BASE::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, int aDepth ) const
784{
785 static wxRegEx operatingPoint( wxT( "^"
786 "OP"
787 "(.([0-9])?([a-zA-Z]*))?"
788 "$" ) );
789
790 wxCHECK( aPath, false );
791
792 SCHEMATIC* schematic = Schematic();
793
794 if( !schematic )
795 return false;
796
797 if( operatingPoint.Matches( *token ) )
798 {
799 int precision = 3;
800 wxString precisionStr( operatingPoint.GetMatch( *token, 2 ) );
801 wxString range( operatingPoint.GetMatch( *token, 3 ) );
802
803 if( !precisionStr.IsEmpty() )
804 precision = precisionStr[0] - '0';
805
806 if( range.IsEmpty() )
807 range = wxS( "~V" );
808
809 const SCH_CONNECTION* connection = Connection();
810 *token = wxS( "?" );
811
812 if( connection )
813 *token = schematic->GetOperatingPoint( connection->Name( false ), precision, range );
814
815 return true;
816 }
817
818 if( token->Contains( ':' ) )
819 {
820 if( schematic->ResolveCrossReference( token, aDepth + 1 ) )
821 return true;
822 }
823
825 && token->IsSameAs( wxT( "CONNECTION_TYPE" ) ) )
826 {
827 const SCH_LABEL_BASE* label = static_cast<const SCH_LABEL_BASE*>( this );
828 *token = getElectricalTypeLabel( label->GetShape() );
829 return true;
830 }
831 else if( token->IsSameAs( wxT( "SHORT_NET_NAME" ) ) )
832 {
833 const SCH_CONNECTION* connection = Connection();
834 *token = wxEmptyString;
835
836 if( connection )
837 *token = connection->LocalName();
838
839 return true;
840 }
841 else if( token->IsSameAs( wxT( "NET_NAME" ) ) )
842 {
843 const SCH_CONNECTION* connection = Connection();
844 *token = wxEmptyString;
845
846 if( connection )
847 *token = connection->Name();
848
849 return true;
850 }
851 else if( token->IsSameAs( wxT( "NET_CLASS" ) ) )
852 {
853 const SCH_CONNECTION* connection = Connection();
854 *token = wxEmptyString;
855
856 if( connection )
857 *token = GetEffectiveNetClass()->GetName();
858
859 return true;
860 }
861 else if( Type() == SCH_DIRECTIVE_LABEL_T && token->IsSameAs( wxT( "EXCLUDE_FROM_BOM" ) ) )
862 {
863 const SCH_DIRECTIVE_LABEL* directive = static_cast<const SCH_DIRECTIVE_LABEL*>( this );
864 *token = wxEmptyString;
865
866 for( SCH_RULE_AREA* ruleArea : directive->GetConnectedRuleAreas() )
867 {
868 if( ruleArea->GetExcludedFromBOM() )
869 *token = _( "Excluded from BOM" );
870 }
871
872 return true;
873 }
874 else if( Type() == SCH_DIRECTIVE_LABEL_T && token->IsSameAs( wxT( "EXCLUDE_FROM_BOARD" ) ) )
875 {
876 const SCH_DIRECTIVE_LABEL* directive = static_cast<const SCH_DIRECTIVE_LABEL*>( this );
877 *token = wxEmptyString;
878
879 for( SCH_RULE_AREA* ruleArea : directive->GetConnectedRuleAreas() )
880 {
881 if( ruleArea->GetExcludedFromBoard() )
882 *token = _( "Excluded from board" );
883 }
884
885 return true;
886 }
887 else if( Type() == SCH_DIRECTIVE_LABEL_T && token->IsSameAs( wxT( "EXCLUDE_FROM_SIM" ) ) )
888 {
889 const SCH_DIRECTIVE_LABEL* directive = static_cast<const SCH_DIRECTIVE_LABEL*>( this );
890 *token = wxEmptyString;
891
892 for( SCH_RULE_AREA* ruleArea : directive->GetConnectedRuleAreas() )
893 {
894 if( ruleArea->GetExcludedFromSim() )
895 *token = _( "Excluded from simulation" );
896 }
897
898 return true;
899 }
900 else if( Type() == SCH_DIRECTIVE_LABEL_T && token->IsSameAs( wxT( "DNP" ) ) )
901 {
902 const SCH_DIRECTIVE_LABEL* directive = static_cast<const SCH_DIRECTIVE_LABEL*>( this );
903 *token = wxEmptyString;
904
905 for( SCH_RULE_AREA* ruleArea : directive->GetConnectedRuleAreas() )
906 {
907 if( ruleArea->GetDNP() )
908 *token = _( "DNP" );
909 }
910
911 return true;
912 }
913
914 for( const SCH_FIELD& field : m_fields )
915 {
916 if( token->IsSameAs( field.GetName() ) )
917 {
918 *token = field.GetShownText( false, aDepth + 1 );
919 return true;
920 }
921 }
922
923 // See if parent can resolve it (these will recurse to ancestors)
924
925 if( Type() == SCH_SHEET_PIN_T && m_parent )
926 {
927 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( m_parent );
928
929 SCH_SHEET_PATH path = *aPath;
930 path.push_back( sheet );
931
932 if( sheet->ResolveTextVar( &path, token, aDepth + 1 ) )
933 return true;
934 }
935 else
936 {
937 // aPath->Last() can be null when loading schematic, i.e. when all sheets are not yet loaded
938 if( aPath->Last() && aPath->Last()->ResolveTextVar( aPath, token, aDepth + 1 ) )
939 return true;
940 }
941
942 return false;
943}
944
945
947{
948 return !HasTextVars();
949}
950
951
953{
955}
956
957
965
966
967wxString SCH_LABEL_BASE::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraText, int aDepth ) const
968{
969 // Use local depth counter so each text element starts fresh
970 int depth = 0;
971
972 std::function<bool( wxString* )> textResolver = [&]( wxString* token ) -> bool
973 {
974 return ResolveTextVar( aPath, token, depth + 1 );
975 };
976
977 wxString text = EDA_TEXT::GetShownText( aAllowExtraText, depth );
978
979 if( HasTextVars() )
980 text = ResolveTextVars( text, &textResolver, depth );
981
982 // Convert escape markers back to literals for final display
983 text.Replace( wxT( "<<<ESC_DOLLAR:" ), wxT( "${" ) );
984 text.Replace( wxT( "<<<ESC_AT:" ), wxT( "@{" ) );
985
986 return text;
987}
988
989
990void SCH_LABEL_BASE::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction, RECURSE_MODE aMode )
991{
992 for( SCH_FIELD& field : m_fields )
993 aFunction( &field );
994}
995
996
997bool SCH_LABEL_BASE::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
998{
999 if( SCH_ITEM::Matches( UnescapeString( GetText() ), aSearchData ) )
1000 {
1001 return true;
1002 }
1003
1004 const SCH_SEARCH_DATA* searchData = dynamic_cast<const SCH_SEARCH_DATA*>( &aSearchData );
1005 SCH_CONNECTION* connection = nullptr;
1006 SCH_SHEET_PATH* sheetPath = reinterpret_cast<SCH_SHEET_PATH*>( aAuxData );
1007
1008 if( searchData && searchData->searchNetNames && sheetPath && ( connection = Connection( sheetPath ) ) )
1009 {
1010 if( connection->IsBus() )
1011 {
1012 auto allMembers = connection->AllMembers();
1013
1014 std::set<wxString> netNames;
1015
1016 for( std::shared_ptr<SCH_CONNECTION> member : allMembers )
1017 netNames.insert( member->GetNetName() );
1018
1019 for( const wxString& netName : netNames )
1020 {
1021 if( EDA_ITEM::Matches( netName, aSearchData ) )
1022 return true;
1023 }
1024
1025 return false;
1026 }
1027
1028 wxString netName = connection->GetNetName();
1029
1030 if( EDA_ITEM::Matches( netName, aSearchData ) )
1031 return true;
1032 }
1033
1034 return false;
1035}
1036
1037
1038bool SCH_LABEL_BASE::Replace( const EDA_SEARCH_DATA& aSearchData, void* aAuxData )
1039{
1040 EDA_SEARCH_DATA localSearchData( aSearchData );
1041 localSearchData.findString = EscapeString( aSearchData.findString, CTX_NETNAME );
1042 localSearchData.replaceString = EscapeString( aSearchData.replaceString, CTX_NETNAME );
1043
1044 return EDA_TEXT::Replace( localSearchData );
1045}
1046
1047
1048INSPECT_RESULT SCH_LABEL_BASE::Visit( INSPECTOR aInspector, void* testData, const std::vector<KICAD_T>& aScanTypes )
1049{
1050 if( IsType( aScanTypes ) )
1051 {
1052 if( INSPECT_RESULT::QUIT == aInspector( this, nullptr ) )
1053 return INSPECT_RESULT::QUIT;
1054 }
1055
1056 for( KICAD_T scanType : aScanTypes )
1057 {
1058 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_FIELD_T )
1059 {
1060 for( SCH_FIELD& field : m_fields )
1061 {
1062 if( INSPECT_RESULT::QUIT == aInspector( &field, this ) )
1063 return INSPECT_RESULT::QUIT;
1064 }
1065 }
1066 }
1067
1069}
1070
1071
1072void SCH_LABEL_BASE::GetEndPoints( std::vector<DANGLING_END_ITEM>& aItemList )
1073{
1074 DANGLING_END_ITEM item( LABEL_END, this, GetTextPos() );
1075 aItemList.push_back( item );
1076}
1077
1078
1079std::vector<VECTOR2I> SCH_LABEL_BASE::GetConnectionPoints() const
1080{
1081 return { GetTextPos() };
1082}
1083
1084
1089
1090
1092{
1093 double ratio;
1094
1095 if( aSettings )
1096 ratio = static_cast<const SCH_RENDER_SETTINGS*>( aSettings )->m_LabelSizeRatio;
1097 else if( Schematic() )
1098 ratio = Schematic()->Settings().m_LabelSizeRatio;
1099 else
1100 ratio = DEFAULT_LABEL_SIZE_RATIO; // For previews (such as in Preferences), etc.
1101
1102 return KiROUND( ratio * GetTextSize().y );
1103}
1104
1105
1107{
1108 // build the bounding box of the label only, without taking into account its fields
1109
1110 BOX2I box;
1111 std::vector<VECTOR2I> pts;
1112
1113 CreateGraphicShape( aSettings, pts, GetTextPos() );
1114
1115 for( const VECTOR2I& pt : pts )
1116 box.Merge( pt );
1117
1118 box.Inflate( GetEffectiveTextPenWidth() / 2 );
1119 box.Normalize();
1120 return box;
1121}
1122
1123
1125{
1126 // build the bounding box of the entire label, including its fields
1127
1128 BOX2I box = GetBodyBoundingBox( nullptr );
1129
1130 for( const SCH_FIELD& field : m_fields )
1131 {
1132 if( field.IsVisible() && field.GetText() != wxEmptyString )
1133 {
1134 BOX2I fieldBBox = field.GetBoundingBox();
1135
1136 if( Type() == SCH_LABEL_T || Type() == SCH_GLOBAL_LABEL_T )
1137 fieldBBox.Offset( GetSchematicTextOffset( nullptr ) );
1138
1139 box.Merge( fieldBBox );
1140 }
1141 }
1142
1143 box.Normalize();
1144
1145 return box;
1146}
1147
1148
1149bool SCH_LABEL_BASE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
1150{
1151 BOX2I bbox = GetBodyBoundingBox( nullptr );
1152 bbox.Inflate( aAccuracy );
1153
1154 if( bbox.Contains( aPosition ) )
1155 return true;
1156
1157 for( const SCH_FIELD& field : m_fields )
1158 {
1159 if( field.IsVisible() )
1160 {
1161 BOX2I fieldBBox = field.GetBoundingBox();
1162 fieldBBox.Inflate( aAccuracy );
1163
1164 if( Type() == SCH_LABEL_T || Type() == SCH_GLOBAL_LABEL_T )
1165 fieldBBox.Offset( GetSchematicTextOffset( nullptr ) );
1166
1167 if( fieldBBox.Contains( aPosition ) )
1168 return true;
1169 }
1170 }
1171
1172 return false;
1173}
1174
1175
1176bool SCH_LABEL_BASE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
1177{
1178 BOX2I rect = aRect;
1179
1180 rect.Inflate( aAccuracy );
1181
1182 if( aContained )
1183 {
1184 return rect.Contains( GetBoundingBox() );
1185 }
1186 else
1187 {
1188 if( rect.Intersects( GetBodyBoundingBox( nullptr ) ) )
1189 return true;
1190
1191 for( const SCH_FIELD& field : m_fields )
1192 {
1193 if( field.IsVisible() )
1194 {
1195 BOX2I fieldBBox = field.GetBoundingBox();
1196
1197 if( Type() == SCH_LABEL_T || Type() == SCH_GLOBAL_LABEL_T )
1198 fieldBBox.Offset( GetSchematicTextOffset( nullptr ) );
1199
1200 if( rect.Intersects( fieldBBox ) )
1201 return true;
1202 }
1203 }
1204
1205 return false;
1206 }
1207}
1208
1209
1210bool SCH_LABEL_BASE::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
1211{
1212 if( aContained )
1213 {
1214 return KIGEOM::BoxHitTest( aPoly, GetBoundingBox(), aContained );
1215 }
1216 else
1217 {
1218 if( KIGEOM::BoxHitTest( aPoly, GetBodyBoundingBox( nullptr ), aContained ) )
1219 return true;
1220
1221 for( const SCH_FIELD& field : m_fields )
1222 {
1223 if( field.IsVisible() )
1224 {
1225 BOX2I fieldBBox = field.GetBoundingBox();
1226
1227 if( Type() == SCH_LABEL_T || Type() == SCH_GLOBAL_LABEL_T )
1228 fieldBBox.Offset( GetSchematicTextOffset( nullptr ) );
1229
1230 if( KIGEOM::BoxHitTest( aPoly, fieldBBox, aContained ) )
1231 return true;
1232 }
1233 }
1234
1235 return false;
1236 }
1237}
1238
1239
1240bool SCH_LABEL_BASE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
1241 std::vector<DANGLING_END_ITEM>& aItemListByPos, const SCH_SHEET_PATH* aPath )
1242{
1243 bool previousState = m_isDangling;
1244 VECTOR2I text_pos = GetTextPos();
1245 m_isDangling = true;
1247
1248 for( auto it = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, text_pos );
1249 it < aItemListByPos.end() && it->GetPosition() == text_pos; it++ )
1250 {
1251 DANGLING_END_ITEM& item = *it;
1252
1253 if( item.GetItem() == this )
1254 continue;
1255
1256 switch( item.GetType() )
1257 {
1258 case PIN_END:
1259 case LABEL_END:
1260 case SHEET_LABEL_END:
1261 case NO_CONNECT_END:
1262 if( text_pos == item.GetPosition() )
1263 {
1264 m_isDangling = false;
1265
1266 if( aPath && item.GetType() != PIN_END )
1267 AddConnectionTo( *aPath, static_cast<SCH_ITEM*>( item.GetItem() ) );
1268 }
1269 break;
1270
1271 default: break;
1272 }
1273
1274 if( !m_isDangling )
1275 break;
1276 }
1277
1278 if( m_isDangling )
1279 {
1280 for( auto it = DANGLING_END_ITEM_HELPER::get_lower_type( aItemListByType, BUS_END );
1281 it < aItemListByType.end() && it->GetType() == BUS_END; it++ )
1282 {
1283 DANGLING_END_ITEM& item = *it;
1284 DANGLING_END_ITEM& nextItem = *( ++it );
1285
1286 int accuracy = 1; // We have rounding issues with an accuracy of 0
1287
1288 m_isDangling = !TestSegmentHit( text_pos, item.GetPosition(), nextItem.GetPosition(), accuracy );
1289
1290 if( m_isDangling )
1291 continue;
1292
1294
1295 // Add the line to the connected items, since it won't be picked
1296 // up by a search of intersecting connection points
1297 if( aPath )
1298 {
1299 auto sch_item = static_cast<SCH_ITEM*>( item.GetItem() );
1300 AddConnectionTo( *aPath, sch_item );
1301 sch_item->AddConnectionTo( *aPath, this );
1302 }
1303
1304 break;
1305 }
1306
1307 if( m_isDangling )
1308 {
1309 for( auto it = DANGLING_END_ITEM_HELPER::get_lower_type( aItemListByType, WIRE_END );
1310 it < aItemListByType.end() && it->GetType() == WIRE_END; it++ )
1311 {
1312 DANGLING_END_ITEM& item = *it;
1313 DANGLING_END_ITEM& nextItem = *( ++it );
1314
1315 int accuracy = 1; // We have rounding issues with an accuracy of 0
1316
1317 m_isDangling = !TestSegmentHit( text_pos, item.GetPosition(), nextItem.GetPosition(), accuracy );
1318
1319 if( m_isDangling )
1320 continue;
1321
1323
1324 // Add the line to the connected items, since it won't be picked
1325 // up by a search of intersecting connection points
1326 if( aPath )
1327 {
1328 auto sch_item = static_cast<SCH_ITEM*>( item.GetItem() );
1329 AddConnectionTo( *aPath, sch_item );
1330 sch_item->AddConnectionTo( *aPath, this );
1331 }
1332
1333 break;
1334 }
1335 }
1336 }
1337
1338 if( m_isDangling )
1340
1341 return previousState != m_isDangling;
1342}
1343
1344
1345bool SCH_LABEL_BASE::HasConnectivityChanges( const SCH_ITEM* aItem, const SCH_SHEET_PATH* aInstance ) const
1346{
1347 // Do not compare to ourself.
1348 if( aItem == this || !IsConnectable() )
1349 return false;
1350
1351 const SCH_LABEL_BASE* label = dynamic_cast<const SCH_LABEL_BASE*>( aItem );
1352
1353 // Don't compare against a different SCH_ITEM.
1354 wxCHECK( label, false );
1355
1356 if( GetPosition() != label->GetPosition() )
1357 return true;
1358
1359 if( GetShownText( aInstance ) != label->GetShownText( aInstance ) )
1360 return true;
1361
1362 std::vector<wxString> netclasses;
1363 std::vector<wxString> otherNetclasses;
1364
1365 for( const SCH_FIELD& field : m_fields )
1366 {
1367 if( field.GetCanonicalName() == wxT( "Netclass" ) )
1368 netclasses.push_back( field.GetText() );
1369 }
1370
1371 for( const SCH_FIELD& field : label->m_fields )
1372 {
1373 if( field.GetCanonicalName() == wxT( "Netclass" ) )
1374 otherNetclasses.push_back( field.GetText() );
1375 }
1376
1377 return netclasses != otherNetclasses;
1378}
1379
1380
1381void SCH_LABEL_BASE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1382{
1383 wxString msg;
1384
1385 switch( Type() )
1386 {
1387 case SCH_LABEL_T: msg = _( "Label" ); break;
1388 case SCH_DIRECTIVE_LABEL_T: msg = _( "Directive Label" ); break;
1389 case SCH_GLOBAL_LABEL_T: msg = _( "Global Label" ); break;
1390 case SCH_HIER_LABEL_T: msg = _( "Hierarchical Label" ); break;
1391 case SCH_SHEET_PIN_T: msg = _( "Hierarchical Sheet Pin" ); break;
1392 default: return;
1393 }
1394
1395 // Don't use GetShownText() here; we want to show the user the variable references
1396 aList.emplace_back( msg, UnescapeString( GetText() ) );
1397
1398 // Display electrical type if it is relevant
1400 aList.emplace_back( _( "Type" ), getElectricalTypeLabel( GetShape() ) );
1401
1402 aList.emplace_back( _( "Font" ), GetFont() ? GetFont()->GetName() : _( "Default" ) );
1403
1404 wxString textStyle[] = { _( "Normal" ), _( "Italic" ), _( "Bold" ), _( "Bold Italic" ) };
1405 int style = IsBold() && IsItalic() ? 3 : IsBold() ? 2 : IsItalic() ? 1 : 0;
1406 aList.emplace_back( _( "Style" ), textStyle[style] );
1407
1408 aList.emplace_back( _( "Text Size" ), aFrame->MessageTextFromValue( GetTextWidth() ) );
1409
1410 switch( GetSpinStyle() )
1411 {
1412 case SPIN_STYLE::LEFT: msg = _( "Align right" ); break;
1413 case SPIN_STYLE::UP: msg = _( "Align bottom" ); break;
1414 case SPIN_STYLE::RIGHT: msg = _( "Align left" ); break;
1415 case SPIN_STYLE::BOTTOM: msg = _( "Align top" ); break;
1416 default: msg = wxT( "???" ); break;
1417 }
1418
1419 aList.emplace_back( _( "Justification" ), msg );
1420
1421 SCH_CONNECTION* conn = nullptr;
1422
1423 if( !IsConnectivityDirty() && dynamic_cast<SCH_EDIT_FRAME*>( aFrame ) )
1424 conn = Connection();
1425
1426 if( conn )
1427 {
1428 conn->AppendInfoToMsgPanel( aList );
1429
1430 if( !conn->IsBus() )
1431 {
1432 aList.emplace_back( _( "Resolved Netclass" ),
1433 UnescapeString( GetEffectiveNetClass()->GetHumanReadableName() ) );
1434 }
1435 }
1436}
1437
1438
1439void SCH_LABEL_BASE::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit,
1440 int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
1441{
1442 static std::vector<VECTOR2I> s_poly;
1443
1444 SCH_SHEET_PATH* sheet = &Schematic()->CurrentSheet();
1445 RENDER_SETTINGS* settings = aPlotter->RenderSettings();
1446 SCH_CONNECTION* connection = Connection();
1447 int layer = ( connection && connection->IsBus() ) ? LAYER_BUS : m_layer;
1448 COLOR4D color = settings->GetLayerColor( layer );
1449 int penWidth = GetEffectiveTextPenWidth( settings->GetDefaultPenWidth() );
1450
1451 if( aPlotter->GetColorMode() && GetLabelColor() != COLOR4D::UNSPECIFIED )
1452 color = GetLabelColor();
1453
1454 if( color.m_text && Schematic() )
1455 color = COLOR4D( ResolveText( *color.m_text, &Schematic()->CurrentSheet() ) );
1456
1457 penWidth = std::max( penWidth, settings->GetMinPenWidth() );
1458 aPlotter->SetCurrentLineWidth( penWidth );
1459
1460 KIFONT::FONT* font = GetDrawFont( settings );
1461
1462 VECTOR2I textpos = GetTextPos() + GetSchematicTextOffset( settings );
1463 CreateGraphicShape( settings, s_poly, GetTextPos() );
1464
1466 attrs.m_StrokeWidth = penWidth;
1467 attrs.m_Multiline = false;
1468
1469 if( aBackground )
1470 {
1471 // No filled shapes (yet)
1472 }
1473 else
1474 {
1475 aPlotter->PlotText( textpos, color, GetShownText( sheet, true ), attrs, font, GetFontMetrics() );
1476
1477 if( aPlotter->GetColorMode() )
1478 {
1479 // For the graphic shape use the override color or the layer color, but not the
1480 // net/netclass color.
1482 aPlotter->SetColor( GetTextColor() );
1483 else
1484 aPlotter->SetColor( settings->GetLayerColor( m_layer ) );
1485 }
1486
1488 {
1489 aPlotter->MoveTo( s_poly[0] );
1490 aPlotter->LineTo( s_poly[1] );
1491 aPlotter->PenFinish();
1492
1493 int diameter = ( s_poly[2] - s_poly[1] ).EuclideanNorm() * 2;
1494 aPlotter->FilledCircle( s_poly[2], diameter, nullptr );
1495 }
1496 else if( GetShape() == LABEL_FLAG_SHAPE::F_ROUND )
1497 {
1498 aPlotter->MoveTo( s_poly[0] );
1499 aPlotter->LineTo( s_poly[1] );
1500 aPlotter->PenFinish();
1501
1502 int diameter = ( s_poly[2] - s_poly[1] ).EuclideanNorm() * 2;
1503 aPlotter->ThickCircle( s_poly[2], diameter, penWidth, nullptr );
1504 }
1505 else
1506 {
1507 if( !s_poly.empty() )
1508 aPlotter->PlotPoly( s_poly, FILL_T::NO_FILL, penWidth, nullptr );
1509 }
1510
1511 // Make sheet pins and hierarchical labels clickable hyperlinks
1512 bool linkAlreadyPlotted = false;
1513 BOX2I bodyBBox = GetBodyBoundingBox( settings );
1514
1515 if( aPlotOpts.m_PDFHierarchicalLinks )
1516 {
1517 if( Type() == SCH_HIER_LABEL_T )
1518 {
1519 if( sheet->size() >= 2 )
1520 {
1521 SCH_SHEET_PATH path = *sheet;
1522 path.pop_back();
1523 aPlotter->HyperlinkBox( bodyBBox, EDA_TEXT::GotoPageHref( path.GetPageNumber() ) );
1524 linkAlreadyPlotted = true;
1525 }
1526 }
1527 else if( Type() == SCH_SHEET_PIN_T )
1528 {
1529 SCH_SHEET_PATH path = *sheet;
1530 SCH_SHEET* parent = static_cast<SCH_SHEET*>( m_parent );
1531 path.push_back( parent );
1532 aPlotter->HyperlinkBox( bodyBBox, EDA_TEXT::GotoPageHref( path.GetPageNumber() ) );
1533 linkAlreadyPlotted = true;
1534 }
1535 }
1536
1537 // Plot attributes to a hypertext menu
1538 if( aPlotOpts.m_PDFPropertyPopups && !linkAlreadyPlotted )
1539 {
1540 std::vector<wxString> properties;
1541
1542 if( connection )
1543 {
1544 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), _( "Net" ), connection->Name() ) );
1545
1546 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), _( "Resolved netclass" ),
1547 GetEffectiveNetClass()->GetHumanReadableName() ) );
1548 }
1549
1550 for( const SCH_FIELD& field : GetFields() )
1551 {
1552 properties.emplace_back(
1553 wxString::Format( wxT( "!%s = %s" ), field.GetName(), field.GetShownText( false ) ) );
1554 }
1555
1556 if( !properties.empty() )
1557 aPlotter->HyperlinkMenu( bodyBBox, properties );
1558 }
1559
1560 if( Type() == SCH_HIER_LABEL_T )
1561 aPlotter->Bookmark( bodyBBox, GetShownText( false ), _( "Hierarchical Labels" ) );
1562 }
1563
1564 for( SCH_FIELD& field : m_fields )
1565 field.Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed );
1566}
1567
1568
1573
1574
1576{
1577 m_autoRotateOnPlacement = autoRotate;
1578}
1579
1580
1581SCH_LABEL::SCH_LABEL( const VECTOR2I& pos, const wxString& text ) :
1583{
1586 m_isDangling = true;
1587}
1588
1589
1590void SCH_LABEL::Serialize( google::protobuf::Any& aContainer ) const
1591{
1592 kiapi::schematic::types::LocalLabel label;
1593
1594 label.mutable_id()->set_value( m_Uuid.AsStdString() );
1595 kiapi::common::PackVector2( *label.mutable_position(), GetPosition() );
1596
1597 aContainer.PackFrom( label );
1598}
1599
1600
1601bool SCH_LABEL::Deserialize( const google::protobuf::Any& aContainer )
1602{
1603 kiapi::schematic::types::LocalLabel label;
1604
1605 if( !aContainer.UnpackTo( &label ) )
1606 return false;
1607
1608 const_cast<KIID&>( m_Uuid ) = KIID( label.id().value() );
1609 SetPosition( kiapi::common::UnpackVector2( label.position() ) );
1610
1611 return true;
1612}
1613
1614
1616{
1617 BOX2I rect = GetTextBox( aSettings );
1618
1619 rect.Offset( 0, -GetTextOffset() );
1621
1622 if( !GetTextAngle().IsZero() )
1623 {
1624 // Rotate rect
1625 VECTOR2I pos = rect.GetOrigin();
1626 VECTOR2I end = rect.GetEnd();
1627
1628 RotatePoint( pos, GetTextPos(), GetTextAngle() );
1630
1631 rect.SetOrigin( pos );
1632 rect.SetEnd( end );
1633
1634 rect.Normalize();
1635 }
1636
1637 // Labels have a position point that is outside of the TextBox
1638 rect.Merge( GetPosition() );
1639
1640 return rect;
1641}
1642
1643
1644wxString SCH_LABEL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1645{
1646 return wxString::Format( _( "Label '%s'" ), aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() ) );
1647}
1648
1649
1654
1655
1657 SCH_LABEL_BASE( pos, wxEmptyString, SCH_DIRECTIVE_LABEL_T )
1658{
1661 m_pinLength = schIUScale.MilsToIU( 100 );
1662 m_symbolSize = schIUScale.MilsToIU( 20 );
1663 m_isDangling = true;
1664}
1665
1666
1668{
1669 SCH_LABEL_BASE::swapData( aItem );
1670
1671 SCH_DIRECTIVE_LABEL* label = static_cast<SCH_DIRECTIVE_LABEL*>( aItem );
1672
1673 std::swap( m_pinLength, label->m_pinLength );
1674 std::swap( m_symbolSize, label->m_symbolSize );
1675}
1676
1677
1679 SCH_LABEL_BASE( aClassLabel )
1680{
1681 m_pinLength = aClassLabel.m_pinLength;
1682 m_symbolSize = aClassLabel.m_symbolSize;
1683}
1684
1685
1686void SCH_DIRECTIVE_LABEL::Serialize( google::protobuf::Any& aContainer ) const
1687{
1689}
1690
1691
1692bool SCH_DIRECTIVE_LABEL::Deserialize( const google::protobuf::Any& aContainer )
1693{
1695 return false;
1696}
1697
1698
1700{
1701 int pen = 0;
1702
1703 if( Schematic() )
1705
1706 return GetEffectiveTextPenWidth( pen );
1707}
1708
1709
1711{
1712 // The "text" is in fact a graphic shape. For a horizontal "text", it looks like a
1713 // vertical shape (like a text reduced to only "I" letter).
1714 // So the mirroring is not exactly similar to a SCH_TEXT item
1715 SCH_TEXT::MirrorSpinStyle( !aLeftRight );
1716
1717 for( SCH_FIELD& field : m_fields )
1718 {
1719 if( ( aLeftRight && field.GetTextAngle().IsHorizontal() )
1720 || ( !aLeftRight && field.GetTextAngle().IsVertical() ) )
1721 {
1722 if( field.GetHorizJustify() == GR_TEXT_H_ALIGN_LEFT )
1723 field.SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
1724 else
1725 field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1726 }
1727
1728 VECTOR2I pos = field.GetTextPos();
1729 VECTOR2I delta = (VECTOR2I) GetPosition() - pos;
1730
1731 if( aLeftRight )
1732 pos.x = GetPosition().x + delta.x;
1733 else
1734 pos.y = GetPosition().y + delta.y;
1735
1736 field.SetTextPos( pos );
1737 }
1738}
1739
1740
1742{
1743 VECTOR2I old_pos = GetPosition();
1744
1745 // The "text" is in fact a graphic shape. For a horizontal "text", it looks like a
1746 // vertical shape (like a text reduced to only "I" letter).
1747 // So the mirroring is not exactly similar to a SCH_TEXT item
1748 // Text is NOT really mirrored; it is moved to a suitable horizontal position
1749 SetSpinStyle( GetSpinStyle().MirrorX() );
1750
1751 SetTextX( MIRRORVAL( GetTextPos().x, aCenter ) );
1752
1753 for( SCH_FIELD& field : m_fields )
1754 {
1755 if( field.GetHorizJustify() == GR_TEXT_H_ALIGN_LEFT )
1756 field.SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
1757 else if( field.GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
1758 field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1759
1760 VECTOR2I pos = field.GetTextPos();
1761 VECTOR2I delta = old_pos - pos;
1762 pos.x = GetPosition().x + delta.x;
1763
1764 field.SetPosition( pos );
1765 }
1766}
1767
1768
1770{
1771 VECTOR2I old_pos = GetPosition();
1772 // The "text" is in fact a graphic shape. For a horizontal "text", it looks like a
1773 // vertical shape (like a text reduced to only "I" letter).
1774 // So the mirroring is not exactly similar to a SCH_TEXT item
1775 // Text is NOT really mirrored; it is moved to a suitable vertical position
1776 SetSpinStyle( GetSpinStyle().MirrorY() );
1777
1778 SetTextY( MIRRORVAL( GetTextPos().y, aCenter ) );
1779
1780 for( SCH_FIELD& field : m_fields )
1781 {
1782 VECTOR2I pos = field.GetTextPos();
1783 VECTOR2I delta = old_pos - pos;
1784 pos.y = GetPosition().y + delta.y;
1785
1786 field.SetPosition( pos );
1787 }
1788}
1789
1790
1791void SCH_DIRECTIVE_LABEL::CreateGraphicShape( const RENDER_SETTINGS* aRenderSettings, std::vector<VECTOR2I>& aPoints,
1792 const VECTOR2I& aPos ) const
1793{
1794 int symbolSize = m_symbolSize;
1795
1796 aPoints.clear();
1797
1798 switch( m_shape )
1799 {
1800 case LABEL_FLAG_SHAPE::F_DOT: symbolSize = KiROUND( symbolSize * 0.7 ); KI_FALLTHROUGH;
1801
1803 // First 3 points are used for generating shape
1804 aPoints.emplace_back( VECTOR2I( 0, 0 ) );
1805 aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) );
1806 aPoints.emplace_back( VECTOR2I( 0, m_pinLength ) );
1807
1808 // These points are just used to bulk out the bounding box
1809 aPoints.emplace_back( VECTOR2I( -m_symbolSize, m_pinLength ) );
1810 aPoints.emplace_back( VECTOR2I( 0, m_pinLength ) );
1811 aPoints.emplace_back( VECTOR2I( m_symbolSize, m_pinLength + symbolSize ) );
1812 break;
1813
1815 aPoints.emplace_back( VECTOR2I( 0, 0 ) );
1816 aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) );
1817 aPoints.emplace_back( VECTOR2I( -2 * m_symbolSize, m_pinLength ) );
1818 aPoints.emplace_back( VECTOR2I( 0, m_pinLength + symbolSize ) );
1819 aPoints.emplace_back( VECTOR2I( 2 * m_symbolSize, m_pinLength ) );
1820 aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) );
1821 aPoints.emplace_back( VECTOR2I( 0, 0 ) );
1822 break;
1823
1825 symbolSize = KiROUND( symbolSize * 0.8 );
1826
1827 aPoints.emplace_back( VECTOR2I( 0, 0 ) );
1828 aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) );
1829 aPoints.emplace_back( VECTOR2I( -2 * symbolSize, m_pinLength - symbolSize ) );
1830 aPoints.emplace_back( VECTOR2I( -2 * symbolSize, m_pinLength + symbolSize ) );
1831 aPoints.emplace_back( VECTOR2I( 2 * symbolSize, m_pinLength + symbolSize ) );
1832 aPoints.emplace_back( VECTOR2I( 2 * symbolSize, m_pinLength - symbolSize ) );
1833 aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) );
1834 aPoints.emplace_back( VECTOR2I( 0, 0 ) );
1835 break;
1836
1837 default: break;
1838 }
1839
1840 // Rotate outlines and move corners to real position
1841 for( VECTOR2I& aPoint : aPoints )
1842 {
1843 switch( GetSpinStyle() )
1844 {
1845 default:
1846 case SPIN_STYLE::LEFT: break;
1847 case SPIN_STYLE::UP: RotatePoint( aPoint, -ANGLE_90 ); break;
1848 case SPIN_STYLE::RIGHT: RotatePoint( aPoint, ANGLE_180 ); break;
1849 case SPIN_STYLE::BOTTOM: RotatePoint( aPoint, ANGLE_90 ); break;
1850 }
1851
1852 aPoint += aPos;
1853 }
1854}
1855
1856
1858{
1859 int margin = GetTextOffset();
1860 int symbolWidth = m_symbolSize;
1861 int origin = m_pinLength;
1862
1864 symbolWidth *= 2;
1865
1866 if( IsItalic() )
1867 margin = KiROUND( margin * 1.5 );
1868
1869 VECTOR2I offset;
1870
1871 for( SCH_FIELD& field : m_fields )
1872 {
1873 if( field.GetText() == wxEmptyString )
1874 continue;
1875
1876 switch( GetSpinStyle() )
1877 {
1878 default:
1879 case SPIN_STYLE::LEFT:
1880 field.SetTextAngle( ANGLE_HORIZONTAL );
1881 offset = { symbolWidth + margin, origin };
1882 break;
1883
1884 case SPIN_STYLE::UP:
1885 field.SetTextAngle( ANGLE_VERTICAL );
1886 offset = { -origin, -( symbolWidth + margin ) };
1887 break;
1888
1889 case SPIN_STYLE::RIGHT:
1890 field.SetTextAngle( ANGLE_HORIZONTAL );
1891 offset = { symbolWidth + margin, -origin };
1892 break;
1893
1894 case SPIN_STYLE::BOTTOM:
1895 field.SetTextAngle( ANGLE_VERTICAL );
1896 offset = { origin, -( symbolWidth + margin ) };
1897 break;
1898 }
1899
1900 field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1901 field.SetTextPos( GetPosition() + offset );
1902
1903 origin -= field.GetTextHeight() + margin;
1904 }
1905
1906 if( aAlgo == AUTOPLACE_AUTO || aAlgo == AUTOPLACE_MANUAL )
1907 m_fieldsAutoplaced = aAlgo;
1908}
1909
1910
1911wxString SCH_DIRECTIVE_LABEL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1912{
1913 if( m_fields.empty() )
1914 {
1915 return _( "Directive Label" );
1916 }
1917 else
1918 {
1919 const SCH_FIELD& firstField = m_fields[0];
1920 wxString content = aFull ? firstField.GetShownText( false ) : KIUI::EllipsizeMenuText( firstField.GetText() );
1921
1922 if( content.IsEmpty() )
1923 {
1924 return wxString::Format( _( "Directive Label [%s (empty)]" ), UnescapeString( m_fields[0].GetName() ) );
1925 }
1926 else
1927 {
1928 return wxString::Format( _( "Directive Label [%s %s]" ), UnescapeString( m_fields[0].GetName() ), content );
1929 }
1930 }
1931}
1932
1933
1935{
1936 m_connected_rule_areas.insert( aRuleArea );
1937}
1938
1939
1944
1945
1947{
1948 m_connected_rule_areas.erase( aRuleArea );
1949}
1950
1951
1952const std::unordered_set<SCH_RULE_AREA*> SCH_DIRECTIVE_LABEL::GetConnectedRuleAreas() const
1953{
1955}
1956
1957
1959{
1960 return m_isDangling && m_connected_rule_areas.empty();
1961}
1962
1963
1964SCH_GLOBALLABEL::SCH_GLOBALLABEL( const VECTOR2I& pos, const wxString& text ) :
1966{
1969 m_isDangling = true;
1970
1972
1973 m_fields.emplace_back(
1975 m_fields.back().SetText( wxT( "${INTERSHEET_REFS}" ) );
1976 m_fields.back().SetVisible( false );
1977 m_fields.back().SetVertJustify( GR_TEXT_V_ALIGN_CENTER );
1978 m_fields.back().SetTextPos( pos );
1979}
1980
1981
1983 SCH_LABEL_BASE( aGlobalLabel )
1984{
1985}
1986
1987
1988void SCH_GLOBALLABEL::Serialize( google::protobuf::Any& aContainer ) const
1989{
1991}
1992
1993
1994bool SCH_GLOBALLABEL::Deserialize( const google::protobuf::Any& aContainer )
1995{
1997 return false;
1998}
1999
2000
2002{
2003 if( SCH_FIELD* field = FindField( m_fields, aFieldType ) )
2004 return field;
2005
2006 m_fields.emplace_back( this, aFieldType );
2007 return &m_fields.back();
2008}
2009
2010
2012{
2013 return FindField( m_fields, aFieldType );
2014}
2015
2016
2018{
2019 int horiz = GetLabelBoxExpansion( aSettings );
2020
2021 // Center the text on the center line of "E" instead of "R" to make room for an overbar
2022 int vert = GetTextHeight() * 0.0715;
2023
2024 switch( m_shape )
2025 {
2029 horiz += GetTextHeight() * 3 / 4; // Use three-quarters-height as proxy for triangle size
2030 break;
2031
2034 default: break;
2035 }
2036
2037 switch( GetSpinStyle() )
2038 {
2039 default:
2040 case SPIN_STYLE::LEFT: return VECTOR2I( -horiz, vert );
2041 case SPIN_STYLE::UP: return VECTOR2I( vert, -horiz );
2042 case SPIN_STYLE::RIGHT: return VECTOR2I( horiz, vert );
2043 case SPIN_STYLE::BOTTOM: return VECTOR2I( vert, horiz );
2044 }
2045}
2046
2047
2053
2054
2055bool SCH_GLOBALLABEL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, int aDepth ) const
2056{
2057 wxCHECK( aPath, false );
2058
2059 SCHEMATIC* schematic = Schematic();
2060
2061 if( !schematic )
2062 return false;
2063
2064 if( token->IsSameAs( wxT( "INTERSHEET_REFS" ) ) )
2065 {
2066 SCHEMATIC_SETTINGS& settings = schematic->Settings();
2067 wxString ref;
2068 auto it = schematic->GetPageRefsMap().find( GetShownText( aPath ) );
2069
2070 if( it == schematic->GetPageRefsMap().end() )
2071 {
2072 ref = "?";
2073 }
2074 else
2075 {
2076 std::vector<int> pageListCopy;
2077
2078 pageListCopy.insert( pageListCopy.end(), it->second.begin(), it->second.end() );
2079 std::sort( pageListCopy.begin(), pageListCopy.end() );
2080
2081 if( !settings.m_IntersheetRefsListOwnPage )
2082 {
2083 int currentPage = schematic->CurrentSheet().GetVirtualPageNumber();
2084 std::erase( pageListCopy, currentPage );
2085 }
2086
2087 std::map<int, wxString> sheetPages = schematic->GetVirtualPageToSheetPagesMap();
2088
2089 if( ( settings.m_IntersheetRefsFormatShort ) && ( pageListCopy.size() > 2 ) )
2090 {
2091 ref.Append( wxString::Format( wxT( "%s..%s" ), sheetPages[pageListCopy.front()],
2092 sheetPages[pageListCopy.back()] ) );
2093 }
2094 else
2095 {
2096 for( const int& pageNo : pageListCopy )
2097 ref.Append( wxString::Format( wxT( "%s," ), sheetPages[pageNo] ) );
2098
2099 if( !ref.IsEmpty() && ref.Last() == ',' )
2100 ref.RemoveLast();
2101 }
2102 }
2103
2104 *token = settings.m_IntersheetRefsPrefix + ref + settings.m_IntersheetRefsSuffix;
2105 return true;
2106 }
2107
2108 return SCH_LABEL_BASE::ResolveTextVar( aPath, token, aDepth );
2109}
2110
2111
2117
2118
2119void SCH_GLOBALLABEL::CreateGraphicShape( const RENDER_SETTINGS* aRenderSettings, std::vector<VECTOR2I>& aPoints,
2120 const VECTOR2I& aPos ) const
2121{
2122 int margin = GetLabelBoxExpansion( aRenderSettings );
2123 int halfSize = ( GetTextHeight() / 2 ) + margin;
2124 int linewidth = GetPenWidth();
2125 int symb_len = GetTextBox( aRenderSettings ).GetWidth() + 2 * margin;
2126
2127 int x = symb_len + linewidth + 3;
2128 int y = halfSize + linewidth + 3;
2129
2130 aPoints.clear();
2131
2132 // Create outline shape : 6 points
2133 aPoints.emplace_back( VECTOR2I( 0, 0 ) );
2134 aPoints.emplace_back( VECTOR2I( 0, -y ) ); // Up
2135 aPoints.emplace_back( VECTOR2I( -x, -y ) ); // left
2136 aPoints.emplace_back( VECTOR2I( -x, 0 ) ); // Up left
2137 aPoints.emplace_back( VECTOR2I( -x, y ) ); // left down
2138 aPoints.emplace_back( VECTOR2I( 0, y ) ); // down
2139
2140 int x_offset = 0;
2141
2142 switch( m_shape )
2143 {
2145 x_offset = -halfSize;
2146 aPoints[0].x += halfSize;
2147 break;
2148
2149 case LABEL_FLAG_SHAPE::L_OUTPUT: aPoints[3].x -= halfSize; break;
2150
2153 x_offset = -halfSize;
2154 aPoints[0].x += halfSize;
2155 aPoints[3].x -= halfSize;
2156 break;
2157
2159 default: break;
2160 }
2161
2162 // Rotate outlines and move corners in real position
2163 for( VECTOR2I& aPoint : aPoints )
2164 {
2165 aPoint.x += x_offset;
2166
2167 switch( GetSpinStyle() )
2168 {
2169 default:
2170 case SPIN_STYLE::LEFT: break;
2171 case SPIN_STYLE::UP: RotatePoint( aPoint, -ANGLE_90 ); break;
2172 case SPIN_STYLE::RIGHT: RotatePoint( aPoint, ANGLE_180 ); break;
2173 case SPIN_STYLE::BOTTOM: RotatePoint( aPoint, ANGLE_90 ); break;
2174 }
2175
2176 aPoint += aPos;
2177 }
2178
2179 aPoints.push_back( aPoints[0] ); // closing
2180}
2181
2182
2183wxString SCH_GLOBALLABEL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
2184{
2185 return wxString::Format( _( "Global Label '%s'" ),
2186 aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() ) );
2187}
2188
2189
2194
2195
2196SCH_HIERLABEL::SCH_HIERLABEL( const VECTOR2I& pos, const wxString& text, KICAD_T aType ) :
2197 SCH_LABEL_BASE( pos, text, aType )
2198{
2201 m_isDangling = true;
2202}
2203
2204
2205void SCH_HIERLABEL::Serialize( google::protobuf::Any& aContainer ) const
2206{
2208}
2209
2210
2211bool SCH_HIERLABEL::Deserialize( const google::protobuf::Any& aContainer )
2212{
2214 return false;
2215}
2216
2217
2223
2224
2225void SCH_HIERLABEL::CreateGraphicShape( const RENDER_SETTINGS* aSettings, std::vector<VECTOR2I>& aPoints,
2226 const VECTOR2I& aPos ) const
2227{
2228 CreateGraphicShape( aSettings, aPoints, aPos, m_shape );
2229}
2230
2231
2232void SCH_HIERLABEL::CreateGraphicShape( const RENDER_SETTINGS* aSettings, std::vector<VECTOR2I>& aPoints,
2233 const VECTOR2I& aPos, LABEL_FLAG_SHAPE aShape ) const
2234{
2235 int* Template = TemplateShape[static_cast<int>( aShape )][static_cast<int>( GetSpinStyle() )];
2236 int halfSize = GetTextHeight() / 2;
2237 int imax = *Template;
2238 Template++;
2239
2240 aPoints.clear();
2241
2242 for( int ii = 0; ii < imax; ii++ )
2243 {
2244 VECTOR2I corner;
2245 corner.x = ( halfSize * ( *Template ) ) + aPos.x;
2246 Template++;
2247
2248 corner.y = ( halfSize * ( *Template ) ) + aPos.y;
2249 Template++;
2250
2251 aPoints.push_back( corner );
2252 }
2253}
2254
2255
2257{
2258 int penWidth = GetEffectiveTextPenWidth();
2259 int margin = GetTextOffset();
2260
2261 int x = GetTextPos().x;
2262 int y = GetTextPos().y;
2263
2264 int height = GetTextHeight() + penWidth + margin;
2265 int length = GetTextBox( aSettings ).GetWidth();
2266
2267 length += height; // add height for triangular shapes
2268
2269 int dx, dy;
2270
2271 switch( GetSpinStyle() )
2272 {
2273 default:
2274 case SPIN_STYLE::LEFT:
2275 dx = -length;
2276 dy = height;
2277 x += schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE );
2278 y -= height / 2;
2279 break;
2280
2281 case SPIN_STYLE::UP:
2282 dx = height;
2283 dy = -length;
2284 x -= height / 2;
2285 y += schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE );
2286 break;
2287
2288 case SPIN_STYLE::RIGHT:
2289 dx = length;
2290 dy = height;
2291 x -= schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE );
2292 y -= height / 2;
2293 break;
2294
2295 case SPIN_STYLE::BOTTOM:
2296 dx = height;
2297 dy = length;
2298 x -= height / 2;
2299 y -= schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE );
2300 break;
2301 }
2302
2303 BOX2I box( VECTOR2I( x, y ), VECTOR2I( dx, dy ) );
2304 box.Normalize();
2305 return box;
2306}
2307
2308
2310{
2311 VECTOR2I text_offset;
2312 int dist = GetTextOffset( aSettings );
2313
2314 dist += GetTextWidth();
2315
2316 switch( GetSpinStyle() )
2317 {
2318 default:
2319 case SPIN_STYLE::LEFT: text_offset.x = -dist; break; // Orientation horiz normale
2320 case SPIN_STYLE::UP: text_offset.y = -dist; break; // Orientation vert UP
2321 case SPIN_STYLE::RIGHT: text_offset.x = dist; break; // Orientation horiz inverse
2322 case SPIN_STYLE::BOTTOM: text_offset.y = dist; break; // Orientation vert BOTTOM
2323 }
2324
2325 return text_offset;
2326}
2327
2328
2329wxString SCH_HIERLABEL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
2330{
2331 return wxString::Format( _( "Hierarchical Label '%s'" ),
2332 aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() ) );
2333}
2334
2335
2340
2341
2343{
2344 wxString msg =
2345#include "sch_text_help_md.h"
2346 ;
2347
2348 HTML_MESSAGE_BOX* dlg = new HTML_MESSAGE_BOX( aParentWindow, _( "Syntax Help" ) );
2349 wxSize sz( 320, 320 );
2350
2351 dlg->SetMinSize( dlg->ConvertDialogToPixels( sz ) );
2352 dlg->SetDialogSizeInDU( sz.x, sz.y );
2353
2354 wxString html_txt;
2355 ConvertMarkdown2Html( wxGetTranslation( msg ), html_txt );
2356 dlg->AddHTML_Text( html_txt );
2357 dlg->ShowModeless();
2358
2359 return dlg;
2360}
2361
2362
2363static struct SCH_LABEL_DESC
2364{
2366 {
2367 auto& labelShapeEnum = ENUM_MAP<LABEL_SHAPE>::Instance();
2368
2369 if( labelShapeEnum.Choices().GetCount() == 0 )
2370 {
2371 labelShapeEnum.Map( LABEL_SHAPE::LABEL_INPUT, _HKI( "Input" ) )
2372 .Map( LABEL_SHAPE::LABEL_OUTPUT, _HKI( "Output" ) )
2373 .Map( LABEL_SHAPE::LABEL_BIDI, _HKI( "Bidirectional" ) )
2374 .Map( LABEL_SHAPE::LABEL_TRISTATE, _HKI( "Tri-state" ) )
2375 .Map( LABEL_SHAPE::LABEL_PASSIVE, _HKI( "Passive" ) );
2376 }
2377
2382
2386
2390
2394
2399
2400 auto hasLabelShape = []( INSPECTABLE* aItem ) -> bool
2401 {
2402 if( SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( aItem ) )
2403 return label->IsType( { SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T, SCH_SHEET_PIN_T } );
2404
2405 return false;
2406 };
2407
2410 .SetAvailableFunc( hasLabelShape );
2411
2412 propMgr.Mask( TYPE_HASH( SCH_LABEL_BASE ), TYPE_HASH( EDA_TEXT ), _HKI( "Hyperlink" ) );
2413 }
2415
2416
2418{
2420 {
2421 auto& flagShapeEnum = ENUM_MAP<FLAG_SHAPE>::Instance();
2422
2423 if( flagShapeEnum.Choices().GetCount() == 0 )
2424 {
2425 flagShapeEnum.Map( FLAG_SHAPE::FLAG_DOT, _HKI( "Dot" ) )
2426 .Map( FLAG_SHAPE::FLAG_CIRCLE, _HKI( "Circle" ) )
2427 .Map( FLAG_SHAPE::FLAG_DIAMOND, _HKI( "Diamond" ) )
2428 .Map( FLAG_SHAPE::FLAG_RECTANGLE, _HKI( "Rectangle" ) );
2429 }
2430
2436
2438
2441
2445
2446 propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Text" ) );
2447 propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Thickness" ) );
2448 propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Italic" ) );
2449 propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Bold" ) );
2450 propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Horizontal Justification" ) );
2451 propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Vertical Justification" ) );
2452 }
2454
2455
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
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:402
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:950
static std::vector< DANGLING_END_ITEM >::iterator get_lower_pos(std::vector< DANGLING_END_ITEM > &aItemListByPos, const VECTOR2I &aPos)
Definition sch_item.cpp:939
Helper class used to store the state of schematic items that can be connected to other schematic item...
Definition sch_item.h:97
DANGLING_END_T GetType() const
Definition sch_item.h:133
EDA_ITEM * GetItem() const
Definition sch_item.h:131
VECTOR2I GetPosition() const
Definition sch_item.h:130
The base class for create windows for drawing purpose.
const KIID m_Uuid
Definition eda_item.h:522
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:111
virtual bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const
Compare the item against the search criteria in aSearchData.
Definition eda_item.h:407
EDA_ITEM * GetParent() const
Definition eda_item.h:113
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:93
EDA_ITEM * m_parent
Owner.
Definition eda_item.h:534
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:590
void SetTextX(int aX)
Definition eda_text.cpp:596
KIFONT::FONT * GetFont() const
Definition eda_text.h:247
void SetTextY(int aY)
Definition eda_text.cpp:602
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:431
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:500
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.
virtual void cacheShownText()
Definition eda_text.cpp:635
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:479
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:284
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition eda_text.cpp:313
void SetMultilineAllowed(bool aAllow)
Definition eda_text.cpp:415
VECTOR2I GetTextSize() const
Definition eda_text.h:261
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition eda_text.cpp:423
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:38
FONT is an abstract base class for both outline and stroke fonts.
Definition font.h:98
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:105
std::shared_ptr< wxString > m_text
Definition color4d.h:399
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:328
COLOR4D GetSchematicColor(bool aIsForSave=false) const
Definition netclass.h:219
Base plotter engine class.
Definition plotter.h:136
virtual void FilledCircle(const VECTOR2I &pos, int diametre, void *aData)
Definition plotter.cpp:599
void MoveTo(const VECTOR2I &pos)
Definition plotter.h:308
RENDER_SETTINGS * RenderSettings()
Definition plotter.h:167
virtual void Bookmark(const BOX2I &aBox, const wxString &aName, const wxString &aGroupName=wxEmptyString)
Create a bookmark to a symbol.
Definition plotter.h:528
virtual void HyperlinkBox(const BOX2I &aBox, const wxString &aDestinationURL)
Create a clickable hyperlink with a rectangular click area.
Definition plotter.h:506
bool GetColorMode() const
Definition plotter.h:164
virtual void SetCurrentLineWidth(int width, void *aData=nullptr)=0
Set the line width for the next drawing.
void LineTo(const VECTOR2I &pos)
Definition plotter.h:313
void PenFinish()
Definition plotter.h:324
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:696
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:517
virtual void ThickCircle(const VECTOR2I &pos, int diametre, int width, void *aData)
Definition plotter.cpp:593
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:244
std::map< int, wxString > GetVirtualPageToSheetPagesMap() const
std::map< int, wxString > GetVirtualPageToSheetNamesMap() const
SCH_SHEET_PATH & CurrentSheet() const
Definition schematic.h:187
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:480
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:524
wxString GetClass() const override
Return the class name.
Definition sch_label.h:463
void swapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
void SetPinLength(int aLength)
Definition sch_label.h:484
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:481
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:483
Schematic editor (Eeschema) main window.
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:116
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 wxString &aVariantName=wxEmptyString) 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)
wxString GetClass() const override
Return the class name.
Definition sch_label.h:546
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.
wxString GetClass() const override
Return the class name.
Definition sch_label.h:626
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:527
SCH_ITEM & operator=(const SCH_ITEM &aPin)
Definition sch_item.cpp:80
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:254
void AddConnectionTo(const SCH_SHEET_PATH &aPath, SCH_ITEM *aItem)
Add a connection link between this item and another.
Definition sch_item.cpp:545
std::shared_ptr< NETCLASS > GetEffectiveNetClass(const SCH_SHEET_PATH *aSheet=nullptr) const
Definition sch_item.cpp:509
bool IsConnectivityDirty() const
Definition sch_item.h:588
AUTOPLACE_ALGO m_fieldsAutoplaced
Definition sch_item.h:782
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:56
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:473
wxString ResolveText(const wxString &aText, const SCH_SHEET_PATH *aPath, int aDepth=0) const
Definition sch_item.cpp:363
const KIFONT::METRICS & GetFontMetrics() const
Definition sch_item.cpp:759
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:787
SCH_LAYER_ID m_layer
Definition sch_item.h:778
bool IsType(const std::vector< KICAD_T > &aScanTypes) const override
Check whether the item is one of the listed types.
Definition sch_item.h:183
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:188
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:119
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:48
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:145
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition sch_sheet.h:233
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:233
KIFONT::FONT * GetDrawFont(const RENDER_SETTINGS *aSettings) const override
Definition sch_text.cpp:286
void Move(const VECTOR2I &aMoveVector) override
Move the item by aMoveVector to a new position.
Definition sch_text.h:112
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
Definition sch_text.cpp:162
static HTML_MESSAGE_BOX * ShowSyntaxHelp(wxWindow *aParentWindow)
VECTOR2I GetPosition() const override
Definition sch_text.h:147
virtual void Rotate90(bool aClockwise)
Definition sch_text.cpp:213
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
Definition sch_text.cpp:123
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:690
int GetPenWidth() const override
Definition sch_text.cpp:280
virtual void MirrorSpinStyle(bool aLeftRight)
Definition sch_text.cpp:224
bool operator==(const SCH_ITEM &aItem) const override
Definition sch_text.cpp:673
int GetTextOffset(const RENDER_SETTINGS *aSettings=nullptr) const
Definition sch_text.cpp:265
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:55
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 ResolveTextVars(const wxString &aSource, const std::function< bool(wxString *)> *aResolver, int &aDepth)
Multi-pass text variable expansion and math expression evaluation.
Definition common.cpp:296
#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:51
INSPECT_RESULT
Definition eda_item.h:45
const INSPECTOR_FUNC & INSPECTOR
std::function passed to nested users by ref, avoids copying std::function.
Definition eda_item.h:92
@ 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
#define UNIMPLEMENTED_FOR(type)
Definition macros.h:96
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:365
int NextFieldOrdinal(const std::vector< SCH_FIELD > &aFields)
Definition sch_field.h:354
AUTOPLACE_ALGO
Definition sch_item.h:69
@ AUTOPLACE_MANUAL
Definition sch_item.h:72
@ AUTOPLACE_AUTO
Definition sch_item.h:71
@ NO_CONNECT_END
Definition sch_item.h:88
@ SHEET_LABEL_END
Definition sch_item.h:87
@ LABEL_END
Definition sch_item.h:84
@ BUS_END
Definition sch_item.h:81
@ PIN_END
Definition sch_item.h:83
@ WIRE_END
Definition sch_item.h:80
std::vector< SCH_ITEM * > SCH_ITEM_VEC
Definition sch_item.h:157
static int TemplateIN_HI[]
Definition sch_label.cpp:67
static int TemplateUNSPC_HI[]
Definition sch_label.cpp:77
static int TemplateOUT_HN[]
Definition sch_label.cpp:71
static int Template3STATE_HN[]
Definition sch_label.cpp:86
static int TemplateBIDI_HN[]
Definition sch_label.cpp:81
static int * TemplateShape[5][4]
Definition sch_label.cpp:91
static int TemplateIN_HN[]
Definition sch_label.cpp:66
static int TemplateIN_BOTTOM[]
Definition sch_label.cpp:69
static int TemplateUNSPC_HN[]
Definition sch_label.cpp:76
static int Template3STATE_BOTTOM[]
Definition sch_label.cpp:89
static int TemplateBIDI_BOTTOM[]
Definition sch_label.cpp:84
static struct SCH_LABEL_DESC _SCH_LABEL_DESC
static int Template3STATE_UP[]
Definition sch_label.cpp:88
static int TemplateOUT_UP[]
Definition sch_label.cpp:73
static int TemplateOUT_HI[]
Definition sch_label.cpp:72
static int TemplateUNSPC_UP[]
Definition sch_label.cpp:78
static int TemplateUNSPC_BOTTOM[]
Definition sch_label.cpp:79
static int TemplateOUT_BOTTOM[]
Definition sch_label.cpp:74
static int Template3STATE_HI[]
Definition sch_label.cpp:87
static int TemplateIN_UP[]
Definition sch_label.cpp:68
wxString getElectricalTypeLabel(LABEL_FLAG_SHAPE aType)
Definition sch_label.cpp:98
static int TemplateBIDI_UP[]
Definition sch_label.cpp:83
static int TemplateBIDI_HI[]
Definition sch_label.cpp:82
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.
std::string path
KIBIS_PIN * pin
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