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