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