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 penWidth = std::max( penWidth, settings->GetMinPenWidth() );
1453 aPlotter->SetCurrentLineWidth( penWidth );
1454
1455 KIFONT::FONT* font = GetDrawFont( settings );
1456
1457 VECTOR2I textpos = GetTextPos() + GetSchematicTextOffset( settings );
1458 CreateGraphicShape( settings, s_poly, GetTextPos() );
1459
1461 attrs.m_StrokeWidth = penWidth;
1462 attrs.m_Multiline = false;
1463
1464 if( aBackground )
1465 {
1466 // No filled shapes (yet)
1467 }
1468 else
1469 {
1470 aPlotter->PlotText( textpos, color, GetShownText( sheet, true ), attrs, font, GetFontMetrics() );
1471
1472 if( aPlotter->GetColorMode() )
1473 {
1474 // For the graphic shape use the override color or the layer color, but not the
1475 // net/netclass color.
1477 aPlotter->SetColor( GetTextColor() );
1478 else
1479 aPlotter->SetColor( settings->GetLayerColor( m_layer ) );
1480 }
1481
1483 {
1484 aPlotter->MoveTo( s_poly[0] );
1485 aPlotter->LineTo( s_poly[1] );
1486 aPlotter->PenFinish();
1487
1488 int diameter = ( s_poly[2] - s_poly[1] ).EuclideanNorm() * 2;
1489 aPlotter->FilledCircle( s_poly[2], diameter, nullptr );
1490 }
1491 else if( GetShape() == LABEL_FLAG_SHAPE::F_ROUND )
1492 {
1493 aPlotter->MoveTo( s_poly[0] );
1494 aPlotter->LineTo( s_poly[1] );
1495 aPlotter->PenFinish();
1496
1497 int diameter = ( s_poly[2] - s_poly[1] ).EuclideanNorm() * 2;
1498 aPlotter->ThickCircle( s_poly[2], diameter, penWidth, nullptr );
1499 }
1500 else
1501 {
1502 if( !s_poly.empty() )
1503 aPlotter->PlotPoly( s_poly, FILL_T::NO_FILL, penWidth, nullptr );
1504 }
1505
1506 // Make sheet pins and hierarchical labels clickable hyperlinks
1507 bool linkAlreadyPlotted = false;
1508 BOX2I bodyBBox = GetBodyBoundingBox( settings );
1509
1510 if( aPlotOpts.m_PDFHierarchicalLinks )
1511 {
1512 if( Type() == SCH_HIER_LABEL_T )
1513 {
1514 if( sheet->size() >= 2 )
1515 {
1516 SCH_SHEET_PATH path = *sheet;
1517 path.pop_back();
1518 aPlotter->HyperlinkBox( bodyBBox, EDA_TEXT::GotoPageHref( path.GetPageNumber() ) );
1519 linkAlreadyPlotted = true;
1520 }
1521 }
1522 else if( Type() == SCH_SHEET_PIN_T )
1523 {
1524 SCH_SHEET_PATH path = *sheet;
1525 SCH_SHEET* parent = static_cast<SCH_SHEET*>( m_parent );
1526 path.push_back( parent );
1527 aPlotter->HyperlinkBox( bodyBBox, EDA_TEXT::GotoPageHref( path.GetPageNumber() ) );
1528 linkAlreadyPlotted = true;
1529 }
1530 }
1531
1532 // Plot attributes to a hypertext menu
1533 if( aPlotOpts.m_PDFPropertyPopups && !linkAlreadyPlotted )
1534 {
1535 std::vector<wxString> properties;
1536
1537 if( connection )
1538 {
1539 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), _( "Net" ), connection->Name() ) );
1540
1541 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), _( "Resolved netclass" ),
1542 GetEffectiveNetClass()->GetHumanReadableName() ) );
1543 }
1544
1545 for( const SCH_FIELD& field : GetFields() )
1546 {
1547 properties.emplace_back(
1548 wxString::Format( wxT( "!%s = %s" ), field.GetName(), field.GetShownText( false ) ) );
1549 }
1550
1551 if( !properties.empty() )
1552 aPlotter->HyperlinkMenu( bodyBBox, properties );
1553 }
1554
1555 if( Type() == SCH_HIER_LABEL_T )
1556 aPlotter->Bookmark( bodyBBox, GetShownText( false ), _( "Hierarchical Labels" ) );
1557 }
1558
1559 for( SCH_FIELD& field : m_fields )
1560 field.Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed );
1561}
1562
1563
1568
1569
1571{
1572 m_autoRotateOnPlacement = autoRotate;
1573}
1574
1575
1576SCH_LABEL::SCH_LABEL( const VECTOR2I& pos, const wxString& text ) :
1578{
1581 m_isDangling = true;
1582}
1583
1584
1585void SCH_LABEL::Serialize( google::protobuf::Any& aContainer ) const
1586{
1587 kiapi::schematic::types::LocalLabel label;
1588
1589 label.mutable_id()->set_value( m_Uuid.AsStdString() );
1590 kiapi::common::PackVector2( *label.mutable_position(), GetPosition() );
1591
1592 aContainer.PackFrom( label );
1593}
1594
1595
1596bool SCH_LABEL::Deserialize( const google::protobuf::Any& aContainer )
1597{
1598 kiapi::schematic::types::LocalLabel label;
1599
1600 if( !aContainer.UnpackTo( &label ) )
1601 return false;
1602
1603 const_cast<KIID&>( m_Uuid ) = KIID( label.id().value() );
1604 SetPosition( kiapi::common::UnpackVector2( label.position() ) );
1605
1606 return true;
1607}
1608
1609
1611{
1612 BOX2I rect = GetTextBox( aSettings );
1613
1614 rect.Offset( 0, -GetTextOffset() );
1616
1617 if( !GetTextAngle().IsZero() )
1618 {
1619 // Rotate rect
1620 VECTOR2I pos = rect.GetOrigin();
1621 VECTOR2I end = rect.GetEnd();
1622
1623 RotatePoint( pos, GetTextPos(), GetTextAngle() );
1625
1626 rect.SetOrigin( pos );
1627 rect.SetEnd( end );
1628
1629 rect.Normalize();
1630 }
1631
1632 // Labels have a position point that is outside of the TextBox
1633 rect.Merge( GetPosition() );
1634
1635 return rect;
1636}
1637
1638
1639wxString SCH_LABEL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1640{
1641 return wxString::Format( _( "Label '%s'" ), aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() ) );
1642}
1643
1644
1649
1650
1652 SCH_LABEL_BASE( pos, wxEmptyString, SCH_DIRECTIVE_LABEL_T )
1653{
1656 m_pinLength = schIUScale.MilsToIU( 100 );
1657 m_symbolSize = schIUScale.MilsToIU( 20 );
1658 m_isDangling = true;
1659}
1660
1661
1663{
1664 SCH_LABEL_BASE::swapData( aItem );
1665
1666 SCH_DIRECTIVE_LABEL* label = static_cast<SCH_DIRECTIVE_LABEL*>( aItem );
1667
1668 std::swap( m_pinLength, label->m_pinLength );
1669 std::swap( m_symbolSize, label->m_symbolSize );
1670}
1671
1672
1674 SCH_LABEL_BASE( aClassLabel )
1675{
1676 m_pinLength = aClassLabel.m_pinLength;
1677 m_symbolSize = aClassLabel.m_symbolSize;
1678}
1679
1680
1681void SCH_DIRECTIVE_LABEL::Serialize( google::protobuf::Any& aContainer ) const
1682{
1683 // TODO
1684}
1685
1686
1687bool SCH_DIRECTIVE_LABEL::Deserialize( const google::protobuf::Any& aContainer )
1688{
1689 // TODO
1690 return false;
1691}
1692
1693
1695{
1696 int pen = 0;
1697
1698 if( Schematic() )
1700
1701 return GetEffectiveTextPenWidth( pen );
1702}
1703
1704
1706{
1707 // The "text" is in fact a graphic shape. For a horizontal "text", it looks like a
1708 // vertical shape (like a text reduced to only "I" letter).
1709 // So the mirroring is not exactly similar to a SCH_TEXT item
1710 SCH_TEXT::MirrorSpinStyle( !aLeftRight );
1711
1712 for( SCH_FIELD& field : m_fields )
1713 {
1714 if( ( aLeftRight && field.GetTextAngle().IsHorizontal() )
1715 || ( !aLeftRight && field.GetTextAngle().IsVertical() ) )
1716 {
1717 if( field.GetHorizJustify() == GR_TEXT_H_ALIGN_LEFT )
1718 field.SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
1719 else
1720 field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1721 }
1722
1723 VECTOR2I pos = field.GetTextPos();
1724 VECTOR2I delta = (VECTOR2I) GetPosition() - pos;
1725
1726 if( aLeftRight )
1727 pos.x = GetPosition().x + delta.x;
1728 else
1729 pos.y = GetPosition().y + delta.y;
1730
1731 field.SetTextPos( pos );
1732 }
1733}
1734
1735
1737{
1738 VECTOR2I old_pos = GetPosition();
1739
1740 // The "text" is in fact a graphic shape. For a horizontal "text", it looks like a
1741 // vertical shape (like a text reduced to only "I" letter).
1742 // So the mirroring is not exactly similar to a SCH_TEXT item
1743 // Text is NOT really mirrored; it is moved to a suitable horizontal position
1744 SetSpinStyle( GetSpinStyle().MirrorX() );
1745
1746 SetTextX( MIRRORVAL( GetTextPos().x, aCenter ) );
1747
1748 for( SCH_FIELD& field : m_fields )
1749 {
1750 if( field.GetHorizJustify() == GR_TEXT_H_ALIGN_LEFT )
1751 field.SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
1752 else if( field.GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
1753 field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1754
1755 VECTOR2I pos = field.GetTextPos();
1756 VECTOR2I delta = old_pos - pos;
1757 pos.x = GetPosition().x + delta.x;
1758
1759 field.SetPosition( pos );
1760 }
1761}
1762
1763
1765{
1766 VECTOR2I old_pos = GetPosition();
1767 // The "text" is in fact a graphic shape. For a horizontal "text", it looks like a
1768 // vertical shape (like a text reduced to only "I" letter).
1769 // So the mirroring is not exactly similar to a SCH_TEXT item
1770 // Text is NOT really mirrored; it is moved to a suitable vertical position
1771 SetSpinStyle( GetSpinStyle().MirrorY() );
1772
1773 SetTextY( MIRRORVAL( GetTextPos().y, aCenter ) );
1774
1775 for( SCH_FIELD& field : m_fields )
1776 {
1777 VECTOR2I pos = field.GetTextPos();
1778 VECTOR2I delta = old_pos - pos;
1779 pos.y = GetPosition().y + delta.y;
1780
1781 field.SetPosition( pos );
1782 }
1783}
1784
1785
1786void SCH_DIRECTIVE_LABEL::CreateGraphicShape( const RENDER_SETTINGS* aRenderSettings, std::vector<VECTOR2I>& aPoints,
1787 const VECTOR2I& aPos ) const
1788{
1789 int symbolSize = m_symbolSize;
1790
1791 aPoints.clear();
1792
1793 switch( m_shape )
1794 {
1795 case LABEL_FLAG_SHAPE::F_DOT: symbolSize = KiROUND( symbolSize * 0.7 ); KI_FALLTHROUGH;
1796
1798 // First 3 points are used for generating shape
1799 aPoints.emplace_back( VECTOR2I( 0, 0 ) );
1800 aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) );
1801 aPoints.emplace_back( VECTOR2I( 0, m_pinLength ) );
1802
1803 // These points are just used to bulk out the bounding box
1804 aPoints.emplace_back( VECTOR2I( -m_symbolSize, m_pinLength ) );
1805 aPoints.emplace_back( VECTOR2I( 0, m_pinLength ) );
1806 aPoints.emplace_back( VECTOR2I( m_symbolSize, m_pinLength + symbolSize ) );
1807 break;
1808
1810 aPoints.emplace_back( VECTOR2I( 0, 0 ) );
1811 aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) );
1812 aPoints.emplace_back( VECTOR2I( -2 * m_symbolSize, m_pinLength ) );
1813 aPoints.emplace_back( VECTOR2I( 0, m_pinLength + symbolSize ) );
1814 aPoints.emplace_back( VECTOR2I( 2 * m_symbolSize, m_pinLength ) );
1815 aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) );
1816 aPoints.emplace_back( VECTOR2I( 0, 0 ) );
1817 break;
1818
1820 symbolSize = KiROUND( symbolSize * 0.8 );
1821
1822 aPoints.emplace_back( VECTOR2I( 0, 0 ) );
1823 aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) );
1824 aPoints.emplace_back( VECTOR2I( -2 * symbolSize, m_pinLength - symbolSize ) );
1825 aPoints.emplace_back( VECTOR2I( -2 * symbolSize, m_pinLength + symbolSize ) );
1826 aPoints.emplace_back( VECTOR2I( 2 * symbolSize, m_pinLength + symbolSize ) );
1827 aPoints.emplace_back( VECTOR2I( 2 * symbolSize, m_pinLength - symbolSize ) );
1828 aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) );
1829 aPoints.emplace_back( VECTOR2I( 0, 0 ) );
1830 break;
1831
1832 default: break;
1833 }
1834
1835 // Rotate outlines and move corners to real position
1836 for( VECTOR2I& aPoint : aPoints )
1837 {
1838 switch( GetSpinStyle() )
1839 {
1840 default:
1841 case SPIN_STYLE::LEFT: break;
1842 case SPIN_STYLE::UP: RotatePoint( aPoint, -ANGLE_90 ); break;
1843 case SPIN_STYLE::RIGHT: RotatePoint( aPoint, ANGLE_180 ); break;
1844 case SPIN_STYLE::BOTTOM: RotatePoint( aPoint, ANGLE_90 ); break;
1845 }
1846
1847 aPoint += aPos;
1848 }
1849}
1850
1851
1853{
1854 int margin = GetTextOffset();
1855 int symbolWidth = m_symbolSize;
1856 int origin = m_pinLength;
1857
1859 symbolWidth *= 2;
1860
1861 if( IsItalic() )
1862 margin = KiROUND( margin * 1.5 );
1863
1864 VECTOR2I offset;
1865
1866 for( SCH_FIELD& field : m_fields )
1867 {
1868 if( field.GetText() == wxEmptyString )
1869 continue;
1870
1871 switch( GetSpinStyle() )
1872 {
1873 default:
1874 case SPIN_STYLE::LEFT:
1875 field.SetTextAngle( ANGLE_HORIZONTAL );
1876 offset = { symbolWidth + margin, origin };
1877 break;
1878
1879 case SPIN_STYLE::UP:
1880 field.SetTextAngle( ANGLE_VERTICAL );
1881 offset = { -origin, -( symbolWidth + margin ) };
1882 break;
1883
1884 case SPIN_STYLE::RIGHT:
1885 field.SetTextAngle( ANGLE_HORIZONTAL );
1886 offset = { symbolWidth + margin, -origin };
1887 break;
1888
1889 case SPIN_STYLE::BOTTOM:
1890 field.SetTextAngle( ANGLE_VERTICAL );
1891 offset = { origin, -( symbolWidth + margin ) };
1892 break;
1893 }
1894
1895 field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1896 field.SetTextPos( GetPosition() + offset );
1897
1898 origin -= field.GetTextHeight() + margin;
1899 }
1900
1901 if( aAlgo == AUTOPLACE_AUTO || aAlgo == AUTOPLACE_MANUAL )
1902 m_fieldsAutoplaced = aAlgo;
1903}
1904
1905
1906wxString SCH_DIRECTIVE_LABEL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1907{
1908 if( m_fields.empty() )
1909 {
1910 return _( "Directive Label" );
1911 }
1912 else
1913 {
1914 const SCH_FIELD& firstField = m_fields[0];
1915 wxString content = aFull ? firstField.GetShownText( false ) : KIUI::EllipsizeMenuText( firstField.GetText() );
1916
1917 if( content.IsEmpty() )
1918 {
1919 return wxString::Format( _( "Directive Label [%s (empty)]" ), UnescapeString( m_fields[0].GetName() ) );
1920 }
1921 else
1922 {
1923 return wxString::Format( _( "Directive Label [%s %s]" ), UnescapeString( m_fields[0].GetName() ), content );
1924 }
1925 }
1926}
1927
1928
1930{
1931 m_connected_rule_areas.insert( aRuleArea );
1932}
1933
1934
1939
1940
1942{
1943 m_connected_rule_areas.erase( aRuleArea );
1944}
1945
1946
1947const std::unordered_set<SCH_RULE_AREA*> SCH_DIRECTIVE_LABEL::GetConnectedRuleAreas() const
1948{
1950}
1951
1952
1954{
1955 return m_isDangling && m_connected_rule_areas.empty();
1956}
1957
1958
1959SCH_GLOBALLABEL::SCH_GLOBALLABEL( const VECTOR2I& pos, const wxString& text ) :
1961{
1964 m_isDangling = true;
1965
1967
1968 m_fields.emplace_back(
1970 m_fields.back().SetText( wxT( "${INTERSHEET_REFS}" ) );
1971 m_fields.back().SetVisible( false );
1972 m_fields.back().SetVertJustify( GR_TEXT_V_ALIGN_CENTER );
1973 m_fields.back().SetTextPos( pos );
1974}
1975
1976
1978 SCH_LABEL_BASE( aGlobalLabel )
1979{
1980}
1981
1982
1983void SCH_GLOBALLABEL::Serialize( google::protobuf::Any& aContainer ) const
1984{
1985 // TODO
1986}
1987
1988
1989bool SCH_GLOBALLABEL::Deserialize( const google::protobuf::Any& aContainer )
1990{
1991 // TODO
1992 return false;
1993}
1994
1995
1997{
1998 if( SCH_FIELD* field = FindField( m_fields, aFieldType ) )
1999 return field;
2000
2001 m_fields.emplace_back( this, aFieldType );
2002 return &m_fields.back();
2003}
2004
2005
2007{
2008 return FindField( m_fields, aFieldType );
2009}
2010
2011
2013{
2014 int horiz = GetLabelBoxExpansion( aSettings );
2015
2016 // Center the text on the center line of "E" instead of "R" to make room for an overbar
2017 int vert = GetTextHeight() * 0.0715;
2018
2019 switch( m_shape )
2020 {
2024 horiz += GetTextHeight() * 3 / 4; // Use three-quarters-height as proxy for triangle size
2025 break;
2026
2029 default: break;
2030 }
2031
2032 switch( GetSpinStyle() )
2033 {
2034 default:
2035 case SPIN_STYLE::LEFT: return VECTOR2I( -horiz, vert );
2036 case SPIN_STYLE::UP: return VECTOR2I( vert, -horiz );
2037 case SPIN_STYLE::RIGHT: return VECTOR2I( horiz, vert );
2038 case SPIN_STYLE::BOTTOM: return VECTOR2I( vert, horiz );
2039 }
2040}
2041
2042
2048
2049
2050bool SCH_GLOBALLABEL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, int aDepth ) const
2051{
2052 wxCHECK( aPath, false );
2053
2054 SCHEMATIC* schematic = Schematic();
2055
2056 if( !schematic )
2057 return false;
2058
2059 if( token->IsSameAs( wxT( "INTERSHEET_REFS" ) ) )
2060 {
2061 SCHEMATIC_SETTINGS& settings = schematic->Settings();
2062 wxString ref;
2063 auto it = schematic->GetPageRefsMap().find( GetShownText( aPath ) );
2064
2065 if( it == schematic->GetPageRefsMap().end() )
2066 {
2067 ref = "?";
2068 }
2069 else
2070 {
2071 std::vector<int> pageListCopy;
2072
2073 pageListCopy.insert( pageListCopy.end(), it->second.begin(), it->second.end() );
2074 std::sort( pageListCopy.begin(), pageListCopy.end() );
2075
2076 if( !settings.m_IntersheetRefsListOwnPage )
2077 {
2078 int currentPage = schematic->CurrentSheet().GetVirtualPageNumber();
2079 std::erase( pageListCopy, currentPage );
2080 }
2081
2082 std::map<int, wxString> sheetPages = schematic->GetVirtualPageToSheetPagesMap();
2083
2084 if( ( settings.m_IntersheetRefsFormatShort ) && ( pageListCopy.size() > 2 ) )
2085 {
2086 ref.Append( wxString::Format( wxT( "%s..%s" ), sheetPages[pageListCopy.front()],
2087 sheetPages[pageListCopy.back()] ) );
2088 }
2089 else
2090 {
2091 for( const int& pageNo : pageListCopy )
2092 ref.Append( wxString::Format( wxT( "%s," ), sheetPages[pageNo] ) );
2093
2094 if( !ref.IsEmpty() && ref.Last() == ',' )
2095 ref.RemoveLast();
2096 }
2097 }
2098
2099 *token = settings.m_IntersheetRefsPrefix + ref + settings.m_IntersheetRefsSuffix;
2100 return true;
2101 }
2102
2103 return SCH_LABEL_BASE::ResolveTextVar( aPath, token, aDepth );
2104}
2105
2106
2112
2113
2114void SCH_GLOBALLABEL::CreateGraphicShape( const RENDER_SETTINGS* aRenderSettings, std::vector<VECTOR2I>& aPoints,
2115 const VECTOR2I& aPos ) const
2116{
2117 int margin = GetLabelBoxExpansion( aRenderSettings );
2118 int halfSize = ( GetTextHeight() / 2 ) + margin;
2119 int linewidth = GetPenWidth();
2120 int symb_len = GetTextBox( aRenderSettings ).GetWidth() + 2 * margin;
2121
2122 int x = symb_len + linewidth + 3;
2123 int y = halfSize + linewidth + 3;
2124
2125 aPoints.clear();
2126
2127 // Create outline shape : 6 points
2128 aPoints.emplace_back( VECTOR2I( 0, 0 ) );
2129 aPoints.emplace_back( VECTOR2I( 0, -y ) ); // Up
2130 aPoints.emplace_back( VECTOR2I( -x, -y ) ); // left
2131 aPoints.emplace_back( VECTOR2I( -x, 0 ) ); // Up left
2132 aPoints.emplace_back( VECTOR2I( -x, y ) ); // left down
2133 aPoints.emplace_back( VECTOR2I( 0, y ) ); // down
2134
2135 int x_offset = 0;
2136
2137 switch( m_shape )
2138 {
2140 x_offset = -halfSize;
2141 aPoints[0].x += halfSize;
2142 break;
2143
2144 case LABEL_FLAG_SHAPE::L_OUTPUT: aPoints[3].x -= halfSize; break;
2145
2148 x_offset = -halfSize;
2149 aPoints[0].x += halfSize;
2150 aPoints[3].x -= halfSize;
2151 break;
2152
2154 default: break;
2155 }
2156
2157 // Rotate outlines and move corners in real position
2158 for( VECTOR2I& aPoint : aPoints )
2159 {
2160 aPoint.x += x_offset;
2161
2162 switch( GetSpinStyle() )
2163 {
2164 default:
2165 case SPIN_STYLE::LEFT: break;
2166 case SPIN_STYLE::UP: RotatePoint( aPoint, -ANGLE_90 ); break;
2167 case SPIN_STYLE::RIGHT: RotatePoint( aPoint, ANGLE_180 ); break;
2168 case SPIN_STYLE::BOTTOM: RotatePoint( aPoint, ANGLE_90 ); break;
2169 }
2170
2171 aPoint += aPos;
2172 }
2173
2174 aPoints.push_back( aPoints[0] ); // closing
2175}
2176
2177
2178wxString SCH_GLOBALLABEL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
2179{
2180 return wxString::Format( _( "Global Label '%s'" ),
2181 aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() ) );
2182}
2183
2184
2189
2190
2191SCH_HIERLABEL::SCH_HIERLABEL( const VECTOR2I& pos, const wxString& text, KICAD_T aType ) :
2192 SCH_LABEL_BASE( pos, text, aType )
2193{
2196 m_isDangling = true;
2197}
2198
2199
2200void SCH_HIERLABEL::Serialize( google::protobuf::Any& aContainer ) const
2201{
2202 // TODO
2203}
2204
2205
2206bool SCH_HIERLABEL::Deserialize( const google::protobuf::Any& aContainer )
2207{
2208 // TODO
2209 return false;
2210}
2211
2212
2218
2219
2220void SCH_HIERLABEL::CreateGraphicShape( const RENDER_SETTINGS* aSettings, std::vector<VECTOR2I>& aPoints,
2221 const VECTOR2I& aPos ) const
2222{
2223 CreateGraphicShape( aSettings, aPoints, aPos, m_shape );
2224}
2225
2226
2227void SCH_HIERLABEL::CreateGraphicShape( const RENDER_SETTINGS* aSettings, std::vector<VECTOR2I>& aPoints,
2228 const VECTOR2I& aPos, LABEL_FLAG_SHAPE aShape ) const
2229{
2230 int* Template = TemplateShape[static_cast<int>( aShape )][static_cast<int>( GetSpinStyle() )];
2231 int halfSize = GetTextHeight() / 2;
2232 int imax = *Template;
2233 Template++;
2234
2235 aPoints.clear();
2236
2237 for( int ii = 0; ii < imax; ii++ )
2238 {
2239 VECTOR2I corner;
2240 corner.x = ( halfSize * ( *Template ) ) + aPos.x;
2241 Template++;
2242
2243 corner.y = ( halfSize * ( *Template ) ) + aPos.y;
2244 Template++;
2245
2246 aPoints.push_back( corner );
2247 }
2248}
2249
2250
2252{
2253 int penWidth = GetEffectiveTextPenWidth();
2254 int margin = GetTextOffset();
2255
2256 int x = GetTextPos().x;
2257 int y = GetTextPos().y;
2258
2259 int height = GetTextHeight() + penWidth + margin;
2260 int length = GetTextBox( aSettings ).GetWidth();
2261
2262 length += height; // add height for triangular shapes
2263
2264 int dx, dy;
2265
2266 switch( GetSpinStyle() )
2267 {
2268 default:
2269 case SPIN_STYLE::LEFT:
2270 dx = -length;
2271 dy = height;
2272 x += schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE );
2273 y -= height / 2;
2274 break;
2275
2276 case SPIN_STYLE::UP:
2277 dx = height;
2278 dy = -length;
2279 x -= height / 2;
2280 y += schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE );
2281 break;
2282
2283 case SPIN_STYLE::RIGHT:
2284 dx = length;
2285 dy = height;
2286 x -= schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE );
2287 y -= height / 2;
2288 break;
2289
2290 case SPIN_STYLE::BOTTOM:
2291 dx = height;
2292 dy = length;
2293 x -= height / 2;
2294 y -= schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE );
2295 break;
2296 }
2297
2298 BOX2I box( VECTOR2I( x, y ), VECTOR2I( dx, dy ) );
2299 box.Normalize();
2300 return box;
2301}
2302
2303
2305{
2306 VECTOR2I text_offset;
2307 int dist = GetTextOffset( aSettings );
2308
2309 dist += GetTextWidth();
2310
2311 switch( GetSpinStyle() )
2312 {
2313 default:
2314 case SPIN_STYLE::LEFT: text_offset.x = -dist; break; // Orientation horiz normale
2315 case SPIN_STYLE::UP: text_offset.y = -dist; break; // Orientation vert UP
2316 case SPIN_STYLE::RIGHT: text_offset.x = dist; break; // Orientation horiz inverse
2317 case SPIN_STYLE::BOTTOM: text_offset.y = dist; break; // Orientation vert BOTTOM
2318 }
2319
2320 return text_offset;
2321}
2322
2323
2324wxString SCH_HIERLABEL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
2325{
2326 return wxString::Format( _( "Hierarchical Label '%s'" ),
2327 aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() ) );
2328}
2329
2330
2335
2336
2338{
2339 wxString msg =
2340#include "sch_text_help_md.h"
2341 ;
2342
2343 HTML_MESSAGE_BOX* dlg = new HTML_MESSAGE_BOX( aParentWindow, _( "Syntax Help" ) );
2344 wxSize sz( 320, 320 );
2345
2346 dlg->SetMinSize( dlg->ConvertDialogToPixels( sz ) );
2347 dlg->SetDialogSizeInDU( sz.x, sz.y );
2348
2349 wxString html_txt;
2350 ConvertMarkdown2Html( wxGetTranslation( msg ), html_txt );
2351 dlg->AddHTML_Text( html_txt );
2352 dlg->ShowModeless();
2353
2354 return dlg;
2355}
2356
2357
2358static struct SCH_LABEL_DESC
2359{
2361 {
2362 auto& labelShapeEnum = ENUM_MAP<LABEL_SHAPE>::Instance();
2363
2364 if( labelShapeEnum.Choices().GetCount() == 0 )
2365 {
2366 labelShapeEnum.Map( LABEL_SHAPE::LABEL_INPUT, _HKI( "Input" ) )
2367 .Map( LABEL_SHAPE::LABEL_OUTPUT, _HKI( "Output" ) )
2368 .Map( LABEL_SHAPE::LABEL_BIDI, _HKI( "Bidirectional" ) )
2369 .Map( LABEL_SHAPE::LABEL_TRISTATE, _HKI( "Tri-state" ) )
2370 .Map( LABEL_SHAPE::LABEL_PASSIVE, _HKI( "Passive" ) );
2371 }
2372
2377
2381
2385
2389
2394
2395 auto hasLabelShape = []( INSPECTABLE* aItem ) -> bool
2396 {
2397 if( SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( aItem ) )
2398 return label->IsType( { SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T, SCH_SHEET_PIN_T } );
2399
2400 return false;
2401 };
2402
2405 .SetAvailableFunc( hasLabelShape );
2406
2407 propMgr.Mask( TYPE_HASH( SCH_LABEL_BASE ), TYPE_HASH( EDA_TEXT ), _HKI( "Hyperlink" ) );
2408 }
2410
2411
2413{
2415 {
2416 auto& flagShapeEnum = ENUM_MAP<FLAG_SHAPE>::Instance();
2417
2418 if( flagShapeEnum.Choices().GetCount() == 0 )
2419 {
2420 flagShapeEnum.Map( FLAG_SHAPE::FLAG_DOT, _HKI( "Dot" ) )
2421 .Map( FLAG_SHAPE::FLAG_CIRCLE, _HKI( "Circle" ) )
2422 .Map( FLAG_SHAPE::FLAG_DIAMOND, _HKI( "Diamond" ) )
2423 .Map( FLAG_SHAPE::FLAG_RECTANGLE, _HKI( "Rectangle" ) );
2424 }
2425
2431
2433
2436
2440
2441 propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Text" ) );
2442 propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Thickness" ) );
2443 propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Italic" ) );
2444 propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Bold" ) );
2445 propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Horizontal Justification" ) );
2446 propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Vertical Justification" ) );
2447 }
2449
2450
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:399
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:831
static std::vector< DANGLING_END_ITEM >::iterator get_lower_pos(std::vector< DANGLING_END_ITEM > &aItemListByPos, const VECTOR2I &aPos)
Definition sch_item.cpp:820
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
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:507
SCH_ITEM & operator=(const SCH_ITEM &aPin)
Definition sch_item.cpp:75
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:244
void AddConnectionTo(const SCH_SHEET_PATH &aPath, SCH_ITEM *aItem)
Add a connection link between this item and another.
Definition sch_item.cpp:424
std::shared_ptr< NETCLASS > GetEffectiveNetClass(const SCH_SHEET_PATH *aSheet=nullptr) const
Definition sch_item.cpp:388
bool IsConnectivityDirty() const
Definition sch_item.h:568
AUTOPLACE_ALGO m_fieldsAutoplaced
Definition sch_item.h:757
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:51
SCH_CONNECTION * Connection(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve the connection associated with this object in the given sheet.
Definition sch_item.cpp:352
const KIFONT::METRICS & GetFontMetrics() const
Definition sch_item.cpp:638
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:762
SCH_LAYER_ID m_layer
Definition sch_item.h:753
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:612
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:595
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