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