KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_field.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) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <sch_render_settings.h>
22#include <scintilla_tricks.h>
23#include <netclass.h>
24#include <wx/log.h>
25#include <wx/menu.h>
26
27#include <advanced_config.h>
28#include <base_units.h>
29#include <common.h> // for ExpandTextVars
30#include <sch_edit_frame.h>
31#include <plotters/plotter.h>
32#include <bitmaps.h>
33#include <kiway.h>
35#include <string_utils.h>
37#include <trace_helpers.h>
38#include <tool/tool_manager.h>
40#include <font/glyph_types.h>
41#include <font/outline_font.h>
42#include "sim/sim_lib_mgr.h"
43#include <properties/property.h>
45#include <google/protobuf/any.pb.h>
46#include <api/api_utils.h>
47#include <api/schematic/schematic_types.pb.h>
48
49static const std::vector<KICAD_T> labelTypes = { SCH_LABEL_LOCATE_ANY_T };
50
51
61static const std::vector<wxString>& GetKnownNetclassFieldTranslations()
62{
63 static const std::vector<wxString> translations = {
64 wxString::FromUTF8( "Net Class" ),
65 wxString::FromUTF8( "صنف الشبكة" ), // ar
66 wxString::FromUTF8( "Верига Клас" ), // bg
67 wxString::FromUTF8( "Classe de xarxa" ), // ca
68 wxString::FromUTF8( "Třídy spojů" ), // cs
69 wxString::FromUTF8( "Netklasse" ), // da, nl
70 wxString::FromUTF8( "Netzklasse" ), // de
71 wxString::FromUTF8( "Κλάση Δικτύου" ), // el
72 wxString::FromUTF8( "Clase de red" ), // es, es_MX
73 wxString::FromUTF8( "Ühendusniidiklass" ), // et
74 wxString::FromUTF8( "Verkkoluokka" ), // fi
75 wxString::FromUTF8( "Classe d'Equipot" ), // fr
76 wxString::FromUTF8( "מחלקת רשת" ), // he
77 wxString::FromUTF8( "नेट क्लास" ), // hi
78 wxString::FromUTF8( "Hálózatosztály" ), // hu
79 wxString::FromUTF8( "Kelas Net" ), // id
80 wxString::FromUTF8( "Netclass" ), // it, ro (same as untranslated)
81 wxString::FromUTF8( "ネットクラス" ), // ja
82 wxString::FromUTF8( "ქსელის კლასი" ), // ka
83 wxString::FromUTF8( "네트 클래스" ), // ko
84 wxString::FromUTF8( "Grandinių klasė" ), // lt
85 wxString::FromUTF8( "Tīklu klase" ), // lv
86 wxString::FromUTF8( "Nettklasse" ), // no
87 wxString::FromUTF8( "Klasy sieci" ), // pl
88 wxString::FromUTF8( "Classes da rede" ), // pt_BR
89 wxString::FromUTF8( "Classe de Rede" ), // pt
90 wxString::FromUTF8( "Класс цепей" ), // ru
91 wxString::FromUTF8( "Triedy spojov" ), // sk
92 wxString::FromUTF8( "Razred vozlišča" ), // sl
93 wxString::FromUTF8( "Класа везе" ), // sr
94 wxString::FromUTF8( "Nätklass" ), // sv
95 wxString::FromUTF8( "நிகர வகுப்பு" ), // ta
96 wxString::FromUTF8( "నెట్ క్లాస్" ), // te
97 wxString::FromUTF8( "เน็ตคลาส" ), // th
98 wxString::FromUTF8( "Ağ Sınıfı" ), // tr
99 wxString::FromUTF8( "Клас зв'язків" ), // uk
100 wxString::FromUTF8( "Lớp mạng" ), // vi
101 wxString::FromUTF8( "网络类" ), // zh_CN
102 wxString::FromUTF8( "網路類" ) // zh_TW
103 };
104
105 return translations;
106}
107
108
109bool SCH_FIELD::IsNetclassLabelFieldName( const wxString& aName )
110{
111 if( aName == wxT( "Netclass" ) )
112 return true;
113
114 for( const wxString& candidate : GetKnownNetclassFieldTranslations() )
115 {
116 if( aName == candidate )
117 return true;
118 }
119
120 return false;
121}
122
123
125 SCH_ITEM( nullptr, SCH_FIELD_T ),
126 EDA_TEXT( schIUScale, wxEmptyString ),
127 m_id( FIELD_T::USER ),
128 m_ordinal( 0 ),
129 m_showName( false ),
130 m_allowAutoPlace( true ),
131 m_isGeneratedField( false ),
132 m_autoAdded( false ),
133 m_showInChooser( true ),
135{
136}
137
138
139SCH_FIELD::SCH_FIELD( SCH_ITEM* aParent, FIELD_T aFieldId, const wxString& aName ) :
140 SCH_FIELD()
141{
142 m_parent = aParent;
143
144 if( !aName.IsEmpty() )
145 SetName( aName );
146 else
147 SetName( GetDefaultFieldName( aFieldId, TRANSLATED ) );
148
149 setId( aFieldId ); // will also set the layer; call only AFTER SetName()
150 SetVisible( true );
151
152 if( aParent && aParent->Schematic() )
153 {
154 SCHEMATIC_SETTINGS& settings = aParent->Schematic()->Settings();
156 }
157
158 if( aFieldId == FIELD_T::USER && aParent )
159 {
160 wxASSERT_MSG( aParent->Type() != SCH_SHEET_T, wxT( "Sheets use FIELD_T::SHEET_USER, not FIELD_T::USER!" ) );
161
162 if( aParent->Type() == SCH_SYMBOL_T )
163 m_ordinal = static_cast<SCH_SYMBOL*>( aParent )->GetNextFieldOrdinal();
164 else if( aParent->Type() == LIB_SYMBOL_T )
165 m_ordinal = static_cast<LIB_SYMBOL*>( aParent )->GetNextFieldOrdinal();
166 else if( SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( aParent ) )
167 m_ordinal = label->GetNextFieldOrdinal();
168 }
169 else if( aFieldId == FIELD_T::SHEET_USER && aParent )
170 {
171 if( aParent->Type() == SCH_SHEET_T )
172 m_ordinal = static_cast<SCH_SHEET*>( aParent )->GetNextFieldOrdinal();
173 }
174}
175
176
178 SCH_FIELD( aParent, FIELD_T::USER, wxEmptyString )
179{
180 SCH_ITEM::operator=( *aText );
181 EDA_TEXT::operator=( *aText );
182}
183
184
186 SCH_ITEM( aField ),
187 EDA_TEXT( aField )
188{
189 m_private = aField.m_private;
190 m_name = aField.m_name;
191 setId( aField.m_id ); // will also set the layer; call only AFTER setting m_name
192 m_ordinal = aField.m_ordinal;
193 m_showName = aField.m_showName;
196 m_autoAdded = aField.m_autoAdded;
199
200 m_renderCache.reset();
201}
202
203
204void SCH_FIELD::Serialize( kiapi::schematic::types::SchematicField& field, const EDA_IU_SCALE& aScale ) const
205{
206 field.set_name( GetName( false ).ToUTF8() );
207 field.set_visible( IsVisible() );
208 field.set_show_name( IsNameShown() );
209 field.set_allow_auto_place( CanAutoplace() );
210 field.set_is_private( IsPrivate() );
211
212 EDA_TEXT::Serialize( *field.mutable_text(), aScale );
213
214 // Override the position from the above for symbols so that they are in the right reference frame
215 if( m_parent && m_parent->Type() == SCH_SYMBOL_T )
216 kiapi::common::PackVector2( *field.mutable_text()->mutable_position(), GetPosition(), aScale );
217
218 kiapi::common::PackCustomProperties( field.mutable_custom_properties(), *this );
219}
220
221
222void SCH_FIELD::Serialize( google::protobuf::Any& aContainer ) const
223{
224 kiapi::schematic::types::SchematicField field;
225 Serialize( field, schIUScale );
226 aContainer.PackFrom( field );
227}
228
229
230bool SCH_FIELD::Deserialize( const kiapi::schematic::types::SchematicField& field, const EDA_IU_SCALE& aScale )
231{
232 SetName( wxString::FromUTF8( field.name() ) );
233 SetVisible( field.visible() );
234 SetNameShown( field.show_name() );
235 SetCanAutoplace( field.allow_auto_place() );
236 SetPrivate( field.is_private() );
237
238 bool result = EDA_TEXT::Deserialize( field.text(), aScale );
239
240 if( m_parent && m_parent->Type() == SCH_SYMBOL_T )
241 SetPosition( kiapi::common::UnpackVector2( field.text().position(), aScale ) );
242
243 kiapi::common::UnpackCustomProperties( field.custom_properties(), *this );
244 return result;
245}
246
247
248bool SCH_FIELD::Deserialize( const google::protobuf::Any& aContainer )
249{
250 kiapi::schematic::types::SchematicField field;
251
252 if( !aContainer.UnpackTo( &field ) )
253 return false;
254
255 return Deserialize( field, schIUScale );
256}
257
258
260{
261 EDA_TEXT::operator=( aField );
262
263 m_private = aField.m_private;
264 m_name = aField.m_name;
265 setId( aField.m_id ); // will also set the layer; call only AFTER setting m_name
266 m_ordinal = aField.m_ordinal;
267 m_showName = aField.m_showName;
271
272 m_renderCache.reset();
274
275 return *this;
276}
277
278
280{
281 return new SCH_FIELD( *this );
282}
283
284
285void SCH_FIELD::Copy( SCH_FIELD* aTarget ) const
286{
287 *aTarget = *this;
288}
289
290
292{
293 m_id = aId;
295}
296
297
302
303
305 const wxString& aVariantName, int aDepth ) const
306{
307 bool hasTextVars = HasTextVars();
308 wxString text = getUnescapedText( aPath, aVariantName );
309
310 if( !aVariantName.IsEmpty() )
311 hasTextVars = text.Contains( wxT( "${" ) ) || text.Contains( wxT( "@{" ) );
312
313 if( IsNameShown() && aContext == FOR_CANVAS )
314 text = GetShownName() << wxS( ": " ) << text;
315
316 if( hasTextVars && aContext != RAW_VALUE )
317 {
318 text = ResolveText( text, aPath, aDepth, aVariantName );
319 FinalizeTextVarExpansion( text, aContext );
320 }
321
322 return text;
323}
324
325
326wxString SCH_FIELD::GetShownText( RESOLUTION_CONTEXT aContext, int aDepth ) const
327{
328 if( SCHEMATIC* schematic = Schematic() )
329 {
330 const SCH_SHEET_PATH& currentSheet = schematic->CurrentSheet();
331 wxString variantName = schematic->GetCurrentVariant();
332
333 // Path() builds a KIID_PATH, so keep it off the render path unless the trace is on
334 if( wxLog::IsAllowedTraceMask( traceSchFieldRendering ) )
335 {
336 wxLogTrace( traceSchFieldRendering,
337 "GetShownText (no path arg): field=%s, current sheet path='%s', variant='%s', "
338 "size=%zu, empty=%d",
339 GetName(), currentSheet.Path().AsString(), variantName, currentSheet.size(),
340 currentSheet.empty() ? 1 : 0 );
341 }
342
343 return GetShownText( &currentSheet, aContext, variantName, aDepth );
344 }
345 else
346 {
347 return GetShownText( nullptr, aContext, wxEmptyString, aDepth );
348 }
349}
350
351
352wxString SCH_FIELD::GetFullText( int unit ) const
353{
354 if( GetId() != FIELD_T::REFERENCE )
355 return GetText();
356
357 wxString text = GetText();
358 text << wxT( "?" );
359
360 if( GetParentSymbol() && GetParentSymbol()->IsMultiUnit() )
361 text << GetParentSymbol()->GetUnitDisplayName( unit, false );
362
363 return text;
364}
365
366
368{
370}
371
372
374{
376
377 if( !font )
378 font = KIFONT::FONT::GetFont( GetDefaultFont( aSettings ), IsBold(), IsItalic() );
379
380 return font;
381}
382
383
389
390
396
397
398std::vector<std::unique_ptr<KIFONT::GLYPH>>*
399SCH_FIELD::GetRenderCache( const wxString& forResolvedText, const VECTOR2I& forPosition, TEXT_ATTRIBUTES& aAttrs ) const
400{
401 KIFONT::FONT* font = GetDrawFont( nullptr );
402
403 if( font->IsOutline() )
404 {
405 KIFONT::OUTLINE_FONT* outlineFont = static_cast<KIFONT::OUTLINE_FONT*>( font );
406
407 if( !m_renderCache )
408 m_renderCache = std::make_unique<SCH_FIELD_RENDER_CACHE_DATA>();
409
410 if( m_renderCache->glyphs.empty() )
411 {
412 m_renderCache->glyphs.clear();
413
414 outlineFont->GetLinesAsGlyphs( &m_renderCache->glyphs, forResolvedText, forPosition, aAttrs,
415 GetFontMetrics() );
416
417 m_renderCache->pos = forPosition;
418 }
419
420 if( m_renderCache->pos != forPosition )
421 {
422 VECTOR2I delta = forPosition - m_renderCache->pos;
423
424 for( std::unique_ptr<KIFONT::GLYPH>& glyph : m_renderCache->glyphs )
425 {
426 if( glyph->IsOutline() )
427 static_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() )->Move( delta );
428 else
429 static_cast<KIFONT::STROKE_GLYPH*>( glyph.get() )->Move( delta );
430 }
431
432 m_renderCache->pos = forPosition;
433 }
434
435 return &m_renderCache->glyphs;
436 }
437
438 return nullptr;
439}
440
441
442void SCH_FIELD::ImportValues( const SCH_FIELD& aSource )
443{
444 SetAttributes( aSource );
445 SetVisible( aSource.IsVisible() );
446 SetNameShown( aSource.IsNameShown() );
447 SetCanAutoplace( aSource.CanAutoplace() );
448}
449
450
452{
453 wxCHECK_RET( aItem && aItem->Type() == SCH_FIELD_T, wxT( "Cannot swap with invalid item." ) );
454
455 SCH_FIELD* item = static_cast<SCH_FIELD*>( aItem );
456
457 std::swap( m_showName, item->m_showName );
458 std::swap( m_allowAutoPlace, item->m_allowAutoPlace );
459 std::swap( m_isGeneratedField, item->m_isGeneratedField );
460 SwapText( *item );
461 SwapAttributes( *item );
462
463 std::swap( m_lastResolvedColor, item->m_lastResolvedColor );
464}
465
466
468{
470 {
472 }
473 else
474 {
475 SCH_LABEL_BASE* parentLabel = dynamic_cast<SCH_LABEL_BASE*>( GetParent() );
476
477 if( parentLabel && !parentLabel->IsConnectivityDirty() )
479 else
481 }
482
483 return m_lastResolvedColor;
484}
485
486
487std::vector<int> SCH_FIELD::ViewGetLayers() const
488{
490}
491
492
494{
495 if( m_parent && m_parent->Type() == SCH_LABEL_T )
496 {
497 if( GetUntranslatedName() == wxT( "Netclass" ) || GetUntranslatedName() == wxT( "Component Class" ) )
498 {
499 return LAYER_NETCLASS_REFS;
500 }
501 }
502
503 switch( m_id )
504 {
506 case FIELD_T::VALUE: return LAYER_VALUEPART;
511 default: return LAYER_FIELDS;
512 }
513}
514
515
517{
518 // Calculate the text orientation according to the symbol orientation.
519 EDA_ANGLE orient = GetTextAngle();
520
521 if( m_parent && m_parent->Type() == SCH_SYMBOL_T )
522 {
523 SCH_SYMBOL* parentSymbol = static_cast<SCH_SYMBOL*>( m_parent );
524
525 if( parentSymbol && parentSymbol->GetTransform().y1 ) // Rotate symbol 90 degrees.
526 {
527 if( orient.IsHorizontal() )
528 orient = ANGLE_VERTICAL;
529 else
530 orient = ANGLE_HORIZONTAL;
531 }
532 }
533
534 return orient;
535}
536
537
539{
540 BOX2I bbox = GetTextBox( nullptr );
541
542 // Calculate the bounding box position relative to the parent:
543 VECTOR2I origin = GetParentPosition();
544 VECTOR2I pos = GetTextPos() - origin;
545 VECTOR2I begin = bbox.GetOrigin() - origin;
546 VECTOR2I end = bbox.GetEnd() - origin;
547 RotatePoint( begin, pos, GetTextAngle() );
548 RotatePoint( end, pos, GetTextAngle() );
549
550 // Now, apply the symbol transform (mirror/rot)
551 TRANSFORM transform;
552
553 if( m_parent && m_parent->Type() == SCH_SYMBOL_T )
554 transform = static_cast<SCH_SYMBOL*>( m_parent )->GetTransform();
555
556 bbox.SetOrigin( transform.TransformCoordinate( begin ) );
557 bbox.SetEnd( transform.TransformCoordinate( end ) );
558
559 bbox.Move( origin );
560 bbox.Normalize();
561
562 return bbox;
563}
564
565
567{
568 VECTOR2I render_center = GetBoundingBox().Centre();
569 VECTOR2I pos = GetPosition();
570
571 switch( GetHorizJustify() )
572 {
574 if( GetDrawRotation().IsVertical() )
575 return render_center.y > pos.y;
576 else
577 return render_center.x < pos.x;
578
580 if( GetDrawRotation().IsVertical() )
581 return render_center.y < pos.y;
582 else
583 return render_center.x > pos.x;
584
585 default:
586 return false;
587 }
588}
589
590
592{
593 // The justification must be stored before asking whether it is flipped, as a center
594 // justification has no side to report.
595 SetHorizJustify( aJustify );
596
598 SetHorizJustify( MapHorizJustify( -aJustify ) );
599}
600
601
611
612
614{
615 VECTOR2I render_center = GetBoundingBox().Centre();
616 VECTOR2I pos = GetPosition();
617
618 switch( GetVertJustify() )
619 {
621 if( GetDrawRotation().IsVertical() )
622 return render_center.x < pos.x;
623 else
624 return render_center.y < pos.y;
625
627 if( GetDrawRotation().IsVertical() )
628 return render_center.x > pos.x;
629 else
630 return render_center.y > pos.y;
631
632 default:
633 return false;
634 }
635}
636
637
639{
640 SetVertJustify( aJustify );
641
643 SetVertJustify( MapVertJustify( -aJustify ) );
644}
645
646
656
657
658bool SCH_FIELD::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
659{
660 bool searchHiddenFields = aSearchData.searchAllFields;
661 bool searchAndReplace = aSearchData.searchAndReplace;
662 bool replaceReferences = false;
663
664 try
665 {
666 // downcast
667 const SCH_SEARCH_DATA& schSearchData = dynamic_cast<const SCH_SEARCH_DATA&>( aSearchData );
668 replaceReferences = schSearchData.replaceReferences;
669 }
670 catch( const std::bad_cast& )
671 {
672 }
673
674 wxString text = UnescapeString( GetText() );
675
676 if( !IsVisible() && !searchHiddenFields )
677 return false;
678
679 if( m_id == FIELD_T::REFERENCE )
680 {
681 if( searchAndReplace && !replaceReferences )
682 return false;
683
684 SCH_SYMBOL* parentSymbol = dyn_cast<SCH_SYMBOL*>( m_parent );
685
686 // The parent might be a LIB_SYMBOL, in which case, we don't
687 // have a sheet path to resolve the reference.
688 if( !parentSymbol )
689 return false;
690
691 // the search pane surfaces metadata hits through the reference field
692 if( aSearchData.searchMetadata && parentSymbol->Matches( aSearchData, aAuxData ) )
693 return true;
694
695 wxASSERT( aAuxData );
696
697 // Take sheet path into account which effects the reference field and the unit for
698 // symbols with multiple parts.
699 if( aAuxData )
700 {
701 SCH_SHEET_PATH* sheet = (SCH_SHEET_PATH*) aAuxData;
702 text = parentSymbol->GetRef( sheet );
703
704 if( SCH_ITEM::Matches( text, aSearchData ) )
705 return true;
706
707 if( parentSymbol->GetUnitCount() > 1 )
708 text << parentSymbol->SubReference( parentSymbol->GetUnitSelection( sheet ) );
709 }
710 }
711
712 return SCH_ITEM::Matches( text, aSearchData );
713}
714
715
716void SCH_FIELD::OnScintillaCharAdded( SCINTILLA_TRICKS* aScintillaTricks, wxStyledTextEvent& aEvent ) const
717{
718 SCH_ITEM* parent = dynamic_cast<SCH_ITEM*>( GetParent() );
719 SCHEMATIC* schematic = parent ? parent->Schematic() : nullptr;
720
721 if( !schematic )
722 return;
723
724 wxStyledTextCtrl* scintilla = aScintillaTricks->Scintilla();
725 int key = aEvent.GetKey();
726
727 wxArrayString autocompleteTokens;
728 int pos = scintilla->GetCurrentPos();
729 int start = scintilla->WordStartPosition( pos, true );
730 wxString partial;
731
732 // Multi-line fields are not allowed. So remove '\n' if entered.
733 if( key == '\n' )
734 {
735 wxString text = scintilla->GetText();
736 int currpos = scintilla->GetCurrentPos();
737 text.Replace( wxS( "\n" ), wxS( "" ) );
738 scintilla->SetText( text );
739 scintilla->GotoPos( currpos - 1 );
740 return;
741 }
742
743 auto textVarRef =
744 [&]( int pt )
745 {
746 return pt >= 2 && scintilla->GetCharAt( pt - 2 ) == '$' && scintilla->GetCharAt( pt - 1 ) == '{';
747 };
748
749 // Check for cross-reference
750 if( start > 1 && scintilla->GetCharAt( start - 1 ) == ':' )
751 {
752 int refStart = scintilla->WordStartPosition( start - 1, true );
753
754 if( textVarRef( refStart ) )
755 {
756 partial = scintilla->GetRange( start, pos );
757
758 wxString ref = scintilla->GetRange( refStart, start - 1 );
759
760 if( ref == wxS( "OP" ) )
761 {
762 // SPICE operating points use ':' syntax for ports
763 if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( parent ) )
764 {
765 NULL_REPORTER devnull;
766 SCH_SHEET_PATH& sheet = schematic->CurrentSheet();
767 wxString variant = schematic->GetCurrentVariant();
768 SIM_LIB_MGR mgr( &schematic->Project() );
769
770 std::vector<EMBEDDED_FILES*> embeddedFilesStack;
771 embeddedFilesStack.push_back( schematic->GetEmbeddedFiles() );
772
773 if( EMBEDDED_FILES* symbolEmbeddedFiles = symbol->GetEmbeddedFiles() )
774 {
775 embeddedFilesStack.push_back( symbolEmbeddedFiles );
776 symbol->GetLibSymbolRef()->AppendParentEmbeddedFiles( embeddedFilesStack );
777 }
778
779 mgr.SetFilesStack( std::move( embeddedFilesStack ) );
780
781 SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol, true, 0, variant, devnull ).model;
782
783 for( wxString pin : model.GetPinNames() )
784 {
785 if( pin.StartsWith( '<' ) && pin.EndsWith( '>' ) )
786 autocompleteTokens.push_back( pin.Mid( 1, pin.Length() - 2 ) );
787 else
788 autocompleteTokens.push_back( pin );
789 }
790
791 // add the synthetic port for power measurements
792 autocompleteTokens.push_back( wxT( "power" ) );
793 }
794 }
795 else
796 {
798 SCH_SYMBOL* refSymbol = nullptr;
799
800 schematic->Hierarchy().GetSymbols( refs, SYMBOL_FILTER_NON_POWER );
801
802 for( size_t jj = 0; jj < refs.GetCount(); jj++ )
803 {
804 if( refs[jj].GetSymbol()->GetRef( &refs[jj].GetSheetPath(), true ) == ref )
805 {
806 refSymbol = refs[jj].GetSymbol();
807 break;
808 }
809 }
810
811 if( refSymbol )
812 refSymbol->GetContextualTextVars( &autocompleteTokens );
813 }
814 }
815 }
816 else if( textVarRef( start ) )
817 {
818 partial = scintilla->GetTextRange( start, pos );
819
820 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( parent );
821 SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( parent );
822 SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( parent );
823
824 if( symbol )
825 {
826 symbol->GetContextualTextVars( &autocompleteTokens );
827
828 if( schematic->CurrentSheet().Last() )
829 schematic->CurrentSheet().Last()->GetContextualTextVars( &autocompleteTokens );
830 }
831
832 if( sheet )
833 sheet->GetContextualTextVars( &autocompleteTokens );
834
835 if( label )
836 label->GetContextualTextVars( &autocompleteTokens );
837
838 for( std::pair<wxString, wxString> entry : schematic->Project().GetTextVars() )
839 autocompleteTokens.push_back( entry.first );
840 }
841
842 aScintillaTricks->DoAutocomplete( partial, autocompleteTokens );
843 scintilla->SetFocus();
844}
845
846
848{
849 // See comments in SCH_FIELD::Replace(), below.
851 return false;
852
853 return true;
854}
855
856
858{
859 if( const SYMBOL* parentSymbol = GetParentSymbol() )
860 {
861 if( parentSymbol->IsLocked() )
862 return true;
863 }
864
865 if( const SCH_SHEET* parentSheet = dynamic_cast<const SCH_SHEET*>( m_parent ) )
866 {
867 if( parentSheet->IsLocked() )
868 return true;
869 }
870
871 if( const SCH_LABEL_BASE* parentLabel = dynamic_cast<const SCH_LABEL_BASE*>( m_parent ) )
872 {
873 if( parentLabel->IsLocked() )
874 return true;
875 }
876
877 return SCH_ITEM::IsLocked();
878}
879
880
881bool SCH_FIELD::Replace( const EDA_SEARCH_DATA& aSearchData, void* aAuxData )
882{
884 return false;
885
886 bool replaceReferences = false;
887
888 try
889 {
890 const SCH_SEARCH_DATA& schSearchData = dynamic_cast<const SCH_SEARCH_DATA&>( aSearchData );
891 replaceReferences = schSearchData.replaceReferences;
892 }
893 catch( const std::bad_cast& )
894 {
895 }
896
897 wxString text;
898 bool isReplaced = false;
899
900 if( m_id == FIELD_T::REFERENCE && m_parent && m_parent->Type() == SCH_SYMBOL_T )
901 {
902 SCH_SYMBOL* parentSymbol = static_cast<SCH_SYMBOL*>( m_parent );
903
904 if( !replaceReferences )
905 return false;
906
907 wxCHECK_MSG( aAuxData, false, wxT( "Need sheetpath to replace in refdes." ) );
908
909 text = parentSymbol->GetRef( (SCH_SHEET_PATH*) aAuxData );
910 isReplaced = EDA_ITEM::Replace( aSearchData, text );
911
912 if( isReplaced )
913 parentSymbol->SetRef( (SCH_SHEET_PATH*) aAuxData, text );
914 }
915 else
916 {
917 isReplaced = EDA_TEXT::Replace( aSearchData );
918
919 if( m_id == FIELD_T::SHEET_FILENAME && isReplaced )
920 {
921 // If we allowed this we'd have a bunch of work to do here, including warning
922 // about it not being undoable, checking for recursive hierarchies, reloading
923 // sheets, etc. See DIALOG_SHEET_PROPERTIES::TransferDataFromWindow().
924 }
925 }
926
927 return isReplaced;
928}
929
930
931void SCH_FIELD::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
932{
934
935 if( GetTextAngle().IsVertical() )
936 {
937 switch( horizJustify )
938 {
940 if( aRotateCCW )
942
943 break;
944
946 if( aRotateCCW )
948
949 break;
950
953 break;
954 }
955
957 }
958 else if( GetTextAngle().IsHorizontal() )
959 {
960 switch( horizJustify )
961 {
963 if( !aRotateCCW )
965
966 break;
967
969 if( !aRotateCCW )
971
972 break;
973
976 break;
977 }
978
980 }
981 else
982 {
983 wxFAIL_MSG( wxString::Format( wxT( "SCH_FIELD text angle is not horizontal or vertical: %f" ),
984 GetTextAngle().AsDegrees() ) );
985 }
986
987 VECTOR2I pt = GetPosition();
988 RotatePoint( pt, aCenter, aRotateCCW ? ANGLE_90 : ANGLE_270 );
989 SetPosition( pt );
990}
991
992
994{
995 int x = GetTextPos().x;
996
997 x -= aCenter;
998 x *= -1;
999 x += aCenter;
1000
1001 SetTextX( x );
1002}
1003
1004
1006{
1007 int y = GetTextPos().y;
1008
1009 y -= aCenter;
1010 y *= -1;
1011 y += aCenter;
1012
1013 SetTextY( y );
1014}
1015
1016
1017void SCH_FIELD::BeginEdit( const VECTOR2I& aPosition )
1018{
1019 SetTextPos( aPosition );
1020}
1021
1022
1023void SCH_FIELD::CalcEdit( const VECTOR2I& aPosition )
1024{
1025 SetTextPos( aPosition );
1026}
1027
1028
1029wxString SCH_FIELD::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1030{
1031 wxString content = aFull ? GetShownText( FOR_GUI ) : KIUI::EllipsizeMenuText( GetText() );
1032
1033 if( content.IsEmpty() )
1034 return wxString::Format( _( "Field %s (empty)" ), UnescapeString( GetName() ) );
1035 else
1036 return wxString::Format( _( "Field %s '%s'" ), UnescapeString( GetName() ), content );
1037}
1038
1039
1040void SCH_FIELD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1041{
1042 wxString msg;
1043
1044 aList.emplace_back( _( "Symbol Field" ), UnescapeString( GetName() ) );
1045
1046 // Don't use GetShownText() here; we want to show the user the variable references
1047 aList.emplace_back( _( "Text" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
1048
1049 aList.emplace_back( _( "Visible" ), IsVisible() ? _( "Yes" ) : _( "No" ) );
1050
1051 aList.emplace_back( _( "Font" ), GetFont() ? GetFont()->GetName() : _( "Default" ) );
1052
1053 aList.emplace_back( _( "Style" ), GetTextStyleName() );
1054
1055 aList.emplace_back( _( "Text Size" ), aFrame->MessageTextFromValue( GetTextWidth() ) );
1056
1057 switch( GetHorizJustify() )
1058 {
1059 case GR_TEXT_H_ALIGN_LEFT: msg = _( "Left" ); break;
1060 case GR_TEXT_H_ALIGN_CENTER: msg = _( "Center" ); break;
1061 case GR_TEXT_H_ALIGN_RIGHT: msg = _( "Right" ); break;
1063 }
1064
1065 aList.emplace_back( _( "H Justification" ), msg );
1066
1067 switch( GetVertJustify() )
1068 {
1069 case GR_TEXT_V_ALIGN_TOP: msg = _( "Top" ); break;
1070 case GR_TEXT_V_ALIGN_CENTER: msg = _( "Center" ); break;
1071 case GR_TEXT_V_ALIGN_BOTTOM: msg = _( "Bottom" ); break;
1073 }
1074
1075 aList.emplace_back( _( "V Justification" ), msg );
1076}
1077
1078
1080{
1082 return true;
1083
1084 return IsURL( GetShownText( FOR_GUI ) );
1085}
1086
1087
1088void SCH_FIELD::DoHypertextAction( EDA_DRAW_FRAME* aFrame, const VECTOR2I& aMousePos ) const
1089{
1090 constexpr int START_ID = 1;
1091
1092 wxString href;
1093
1095 {
1096 SCH_LABEL_BASE* label = static_cast<SCH_LABEL_BASE*>( m_parent );
1097 SCH_SHEET_PATH* sheet = &label->Schematic()->CurrentSheet();
1098 wxMenu menu;
1099
1100 std::vector<std::pair<wxString, wxString>> pages;
1101
1102 label->GetIntersheetRefs( sheet, &pages );
1103
1104 for( int i = 0; i < (int) pages.size(); ++i )
1105 {
1106 menu.Append( i + START_ID,
1107 wxString::Format( _( "Go to Page %s (%s)" ), pages[i].first, pages[i].second ) );
1108 }
1109
1110 menu.AppendSeparator();
1111 menu.Append( 999 + START_ID, _( "Back to Previous Selected Sheet" ) );
1112
1113 int sel = aFrame->GetPopupMenuSelectionFromUser( menu ) - START_ID;
1114
1115 if( sel >= 0 && sel < (int) pages.size() )
1116 href = wxT( "#" ) + pages[sel].first;
1117 else if( sel == 999 )
1119 }
1121 {
1122 href = GetShownText( FOR_GUI );
1123 }
1124
1125 if( !href.IsEmpty() )
1126 {
1128 navTool->HypertextCommand( href );
1129 }
1130}
1131
1132
1133void SCH_FIELD::SetName( const wxString& aName )
1134{
1135 const bool generated = ::IsGeneratedField( aName );
1136 const bool changed = m_name != aName || ( generated && EDA_TEXT::GetText() != aName );
1137 m_name = aName;
1138 m_isGeneratedField = generated;
1139
1140 if( m_isGeneratedField )
1141 EDA_TEXT::SetText( aName );
1142
1143 if( changed )
1145}
1146
1147
1148void SCH_FIELD::SetText( const wxString& aText )
1149{
1150 // Don't allow modification of text value of generated fields.
1151 if( m_isGeneratedField )
1152 return;
1153
1154 // Mandatory fields should not have leading or trailing whitespace.
1155 const wxString text = IsMandatory() ? aText.Strip( wxString::both ) : aText;
1156 const bool changed = EDA_TEXT::GetText() != text;
1158
1159 if( changed )
1161}
1162
1163
1164void SCH_FIELD::SetText( const wxString& aText, const SCH_SHEET_PATH* aPath, const wxString& aVariantName )
1165{
1166 wxCHECK( m_parent, /* void */ );
1167
1168 if( m_isGeneratedField )
1169 return;
1170
1171 const wxString text = IsMandatory() ? aText.Strip( wxString::both ) : aText;
1172
1173 switch( m_parent->Type() )
1174 {
1175 case SCH_SYMBOL_T:
1176 {
1177 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( m_parent );
1178 wxCHECK( symbol, /* void */ );
1179
1180 // Just because we _have_ a parent, doesn't mean we've been added to it yet. Make sure to
1181 // use the version of SetFieldText() which gives our parent a pointer to us.
1182 symbol->SetFieldText( this, GetName( false ), text, aPath, aVariantName );
1183
1184 break;
1185 }
1186
1187 case SCH_SHEET_T:
1188 {
1189 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( m_parent );
1190 wxCHECK( sheet, /* void */ );
1191
1192 // Just because we _have_ a parent, doesn't mean we've been added to it yet. Make sure to
1193 // use the version of SetFieldText() which gives our parent a pointer to us.
1194 sheet->SetFieldText( this, GetName( false ), text, aPath, aVariantName );
1195
1196 break;
1197 }
1198
1199 default:
1201 break;
1202 }
1203}
1204
1205
1206wxString SCH_FIELD::GetText( const SCH_SHEET_PATH* aPath, const wxString& aVariantName ) const
1207{
1208 wxString retv;
1209
1210 wxCHECK( aPath && m_parent, retv );
1211
1212 switch( m_parent->Type() )
1213 {
1214 case SCH_SYMBOL_T:
1215 {
1216 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( m_parent );
1217 wxCHECK( symbol, retv );
1218
1219 // Just because we _have_ a parent, doesn't mean we've been added to it yet. Make sure to
1220 // use the version of SetFieldText() which gives our parent a pointer to us.
1221 retv = symbol->GetFieldText( this, GetName( false ), aPath, aVariantName );
1222
1223 break;
1224 }
1225
1226 case SCH_SHEET_T:
1227 {
1228 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( m_parent );
1229 wxCHECK( sheet, retv );
1230
1231 // Just because we _have_ a parent, doesn't mean we've been added to it yet. Make sure to
1232 // use the version of SetFieldText() which gives our parent a pointer to us.
1233 retv = sheet->GetFieldText( this, GetName( false ), aPath, aVariantName );
1234
1235 break;
1236 }
1237
1238 default:
1239 retv = GetText();
1240 break;
1241 }
1242
1243 return retv;
1244}
1245
1246
1247wxString SCH_FIELD::GetName( bool aUseDefaultName ) const
1248{
1249 if( m_parent && m_parent->IsType( labelTypes ) )
1250 return SCH_LABEL_BASE::GetDefaultFieldName( m_name, aUseDefaultName );
1251
1252 if( IsMandatory() )
1254 else if( m_name.IsEmpty() && aUseDefaultName )
1256 else
1257 return m_name;
1258}
1259
1260
1262{
1263 if( m_parent && m_parent->IsType( labelTypes ) )
1264 {
1265 // These should be stored untranslated, but recover translated forms written by
1266 // older versions or by cross-language collaboration via Git.
1268 return wxT( "Netclass" );
1269 }
1270
1271 if( IsMandatory() )
1273
1274 return m_name;
1275}
1276
1277
1279{
1280 if( m_parent && ( m_parent->Type() == SCH_SYMBOL_T || m_parent->Type() == LIB_SYMBOL_T ) )
1281 {
1282 switch( m_id )
1283 {
1287 default: return BITMAPS::text;
1288 }
1289 }
1290
1291 return BITMAPS::text;
1292}
1293
1294
1295bool SCH_FIELD::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
1296{
1298 return false;
1299
1300 BOX2I rect = GetBoundingBox();
1301
1302 // Text in symbol editor can have additional chars (ie: reference designators U? or U?A)
1303 if( m_parent && m_parent->Type() == LIB_SYMBOL_T )
1304 {
1305 SCH_FIELD temp( *this );
1306 temp.SetText( GetFullText() );
1307 rect = temp.GetBoundingBox();
1308 }
1309
1310 rect.Inflate( aAccuracy );
1311
1312 if( m_parent && m_parent->Type() == SCH_GLOBAL_LABEL_T )
1313 {
1314 SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( GetParent() );
1315 rect.Offset( label->GetSchematicTextOffset( nullptr ) );
1316 }
1317
1318 return rect.Contains( aPosition );
1319}
1320
1321
1322bool SCH_FIELD::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
1323{
1325 return false;
1326
1327 if( m_flags & ( STRUCT_DELETED | SKIP_STRUCT ) )
1328 return false;
1329
1330 BOX2I rect = aRect;
1331
1332 rect.Inflate( aAccuracy );
1333
1334 if( GetParent() && GetParent()->Type() == SCH_GLOBAL_LABEL_T )
1335 {
1336 SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( GetParent() );
1337 rect.Offset( label->GetSchematicTextOffset( nullptr ) );
1338 }
1339
1340 if( aContained )
1341 return rect.Contains( GetBoundingBox() );
1342
1343 return rect.Intersects( GetBoundingBox() );
1344}
1345
1346
1347bool SCH_FIELD::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
1348{
1350 return false;
1351
1352 if( m_flags & ( STRUCT_DELETED | SKIP_STRUCT ) )
1353 return false;
1354
1355 BOX2I bbox = GetBoundingBox();
1356
1357 if( GetParent() && GetParent()->Type() == SCH_GLOBAL_LABEL_T )
1358 {
1359 SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( GetParent() );
1360 bbox.Offset( label->GetSchematicTextOffset( nullptr ) );
1361 }
1362
1363 return KIGEOM::BoxHitTest( aPoly, bbox, aContained );
1364}
1365
1366
1367void SCH_FIELD::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit, int aBodyStyle,
1368 const VECTOR2I& aOffset, bool aDimmed )
1369{
1370 wxString text;
1371
1372 if( Schematic() )
1373 text = GetShownText( &Schematic()->CurrentSheet(), FOR_CANVAS, Schematic()->GetCurrentVariant() );
1374 else
1376
1377 if( ( !IsVisible() && !IsForceVisible() ) || text.IsEmpty() || aBackground )
1378 return;
1379
1380 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
1381 COLOR4D color = renderSettings->GetLayerColor( GetLayer() );
1382 int penWidth = GetEffectiveTextPenWidth( renderSettings->GetDefaultPenWidth() );
1383
1384 COLOR4D bg = renderSettings->GetBackgroundColor();
1385
1386 if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
1387 bg = COLOR4D::WHITE;
1388
1389 if( aPlotter->GetColorMode() && GetTextColor() != COLOR4D::UNSPECIFIED )
1390 color = GetTextColor();
1391
1392 if( color.m_text && Schematic() )
1393 color = COLOR4D( ResolveText( *color.m_text, &Schematic()->CurrentSheet() ) );
1394
1395 if( aDimmed )
1396 {
1397 color.Desaturate();
1398 color = color.Mix( bg, 0.5f );
1399 }
1400
1401 penWidth = std::max( penWidth, renderSettings->GetMinPenWidth() );
1402
1403 // clamp the pen width to be sure the text is readable
1404 penWidth = std::min( penWidth, std::min( GetTextSize().x, GetTextSize().y ) / 4 );
1405
1406 if( !IsVisible() && !renderSettings->m_ShowHiddenFields )
1407 return;
1408
1409 // Calculate the text orientation, according to the symbol orientation/mirror
1410 EDA_ANGLE orient = GetTextAngle();
1411 VECTOR2I textpos = GetTextPos();
1413 GR_TEXT_V_ALIGN_T vjustify = GetVertJustify();
1414
1415 if( renderSettings->m_Transform.y1 ) // Rotate symbol 90 deg.
1416 {
1417 if( orient.IsHorizontal() )
1418 orient = ANGLE_VERTICAL;
1419 else
1420 orient = ANGLE_HORIZONTAL;
1421 }
1422
1423 if( m_parent && m_parent->Type() == SCH_SYMBOL_T )
1424 {
1425 /*
1426 * Calculate the text justification, according to the symbol orientation/mirror. This is
1427 * a bit complicated due to cumulative calculations:
1428 * - numerous cases (mirrored or not, rotation)
1429 * - the plotter's Text() function will also recalculate H and V justifications according
1430 * to the text orientation
1431 * - when a symbol is mirrored the text is not, and justifications become a nightmare
1432 *
1433 * So the easier way is to use no justifications (centered text) and use GetBoundingBox
1434 * to know the text coordinate considered as centered.
1435 */
1436 hjustify = GR_TEXT_H_ALIGN_CENTER;
1437 vjustify = GR_TEXT_V_ALIGN_CENTER;
1438 textpos = GetBoundingBox().Centre();
1439 }
1440 else if( m_parent && m_parent->Type() == LIB_SYMBOL_T )
1441 {
1442 // Library-symbol exports (CLI/symbol editor) provide an item offset in the same coordinate
1443 // frame as body graphics/pins. Apply the same transform+offset pipeline to field text.
1444 textpos = renderSettings->TransformCoordinate( textpos ) + aOffset;
1445 }
1446 else if( m_parent && m_parent->Type() == SCH_GLOBAL_LABEL_T )
1447 {
1448 SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( m_parent );
1449 textpos += label->GetSchematicTextOffset( renderSettings );
1450 }
1451 else if( m_parent && m_parent->Type() == SCH_DIRECTIVE_LABEL_T )
1452 {
1453 SCH_DIRECTIVE_LABEL* label = static_cast<SCH_DIRECTIVE_LABEL*>( m_parent );
1454 std::shared_ptr<NETCLASS> nc = label->GetEffectiveNetClass();
1455
1456 if( nc && ( nc->GetSchematicColor() != COLOR4D::UNSPECIFIED ) && aPlotter->GetColorMode() )
1457 color = nc->GetSchematicColor();
1458 }
1459
1460 KIFONT::FONT* font = GetDrawFont( renderSettings );
1462 attrs.m_StrokeWidth = penWidth;
1463 attrs.m_Halign = hjustify;
1464 attrs.m_Valign = vjustify;
1465 attrs.m_Angle = orient;
1466 attrs.m_Multiline = false;
1467
1468 aPlotter->PlotText( textpos, color, text, attrs, font, GetFontMetrics() );
1469
1471 {
1472 if( SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( m_parent ) )
1473 {
1474 std::vector<std::pair<wxString, wxString>> pages;
1475 std::vector<wxString> pageHrefs;
1476
1477 label->GetIntersheetRefs( &Schematic()->CurrentSheet(), &pages );
1478
1479 for( const auto& [pageNumber, sheetName] : pages )
1480 pageHrefs.push_back( wxT( "#" ) + pageNumber );
1481
1482 BOX2I bbox = GetBoundingBox();
1483 bbox.Offset( label->GetSchematicTextOffset( renderSettings ) );
1484
1485 aPlotter->HyperlinkMenu( bbox, pageHrefs );
1486 }
1487 }
1488}
1489
1490
1491void SCH_FIELD::SetPosition( const VECTOR2I& aPosition )
1492{
1493 // Actual positions are calculated by the rotation/mirror transform of the parent symbol
1494 // of the field. The inverse transform is used to calculate the position relative to the
1495 // parent symbol.
1496 if( m_parent && m_parent->Type() == SCH_SYMBOL_T )
1497 {
1498 SCH_SYMBOL* parentSymbol = static_cast<SCH_SYMBOL*>( m_parent );
1499 VECTOR2I relPos = aPosition - parentSymbol->GetPosition();
1500
1501 relPos = parentSymbol->GetTransform().InverseTransform().TransformCoordinate( relPos );
1502
1503 SetTextPos( relPos + parentSymbol->GetPosition() );
1504 return;
1505 }
1506
1507 SetTextPos( aPosition );
1508}
1509
1510
1512{
1513 if( m_parent && m_parent->Type() == SCH_SYMBOL_T )
1514 {
1515 SCH_SYMBOL* parentSymbol = static_cast<SCH_SYMBOL*>( m_parent );
1516 VECTOR2I relativePos = GetTextPos() - parentSymbol->GetPosition();
1517
1518 relativePos = parentSymbol->GetTransform().TransformCoordinate( relativePos );
1519
1520 return relativePos + parentSymbol->GetPosition();
1521 }
1522
1523 return GetTextPos();
1524}
1525
1526
1528{
1529 return m_parent ? m_parent->GetPosition() : VECTOR2I( 0, 0 );
1530}
1531
1532
1539
1540
1541bool SCH_FIELD::operator<( const SCH_ITEM& aItem ) const
1542{
1543 if( Type() != aItem.Type() )
1544 return Type() < aItem.Type();
1545
1546 auto field = static_cast<const SCH_FIELD*>( &aItem );
1547
1548 if( GetId() != field->GetId() )
1549 return GetId() < field->GetId();
1550
1551 if( GetText() != field->GetText() )
1552 return GetText() < field->GetText();
1553
1554 if( GetLibPosition().x != field->GetLibPosition().x )
1555 return GetLibPosition().x < field->GetLibPosition().x;
1556
1557 if( GetLibPosition().y != field->GetLibPosition().y )
1558 return GetLibPosition().y < field->GetLibPosition().y;
1559
1560 return GetName() < field->GetName();
1561}
1562
1563
1564bool SCH_FIELD::operator==( const SCH_ITEM& aOther ) const
1565{
1566 if( Type() != aOther.Type() )
1567 return false;
1568
1569 const SCH_FIELD& field = static_cast<const SCH_FIELD&>( aOther );
1570
1571 return *this == field;
1572}
1573
1574
1575bool SCH_FIELD::operator==( const SCH_FIELD& aOther ) const
1576{
1577 // Identical fields owned by different items are not equal.
1578 if( m_parent || aOther.m_parent )
1579 {
1580 if( !m_parent || !aOther.m_parent )
1581 return false;
1582
1583 if( m_parent->Type() != aOther.m_parent->Type() )
1584 return false;
1585
1586 if( m_parent->m_Uuid != aOther.m_parent->m_Uuid )
1587 return false;
1588 }
1589
1590 if( IsMandatory() != aOther.IsMandatory() )
1591 return false;
1592
1593 if( IsMandatory() )
1594 {
1595 if( GetId() != aOther.GetId() )
1596 return false;
1597 }
1598 else
1599 {
1600 if( GetOrdinal() != aOther.GetOrdinal() )
1601 return false;
1602 }
1603
1604 if( GetPosition() != aOther.GetPosition() )
1605 return false;
1606
1607 if( IsGeneratedField() != aOther.IsGeneratedField() )
1608 return false;
1609
1610 if( IsNameShown() != aOther.IsNameShown() )
1611 return false;
1612
1613 if( CanAutoplace() != aOther.CanAutoplace() )
1614 return false;
1615
1616 return EDA_TEXT::operator==( aOther );
1617}
1618
1619
1620bool SCH_FIELD::HasSameContent( const SCH_FIELD& aOther ) const
1621{
1622 if( GetUntranslatedName() != aOther.GetUntranslatedName() )
1623 return false;
1624
1625 if( GetPosition() != aOther.GetPosition() )
1626 return false;
1627
1628 if( IsVisible() != aOther.IsVisible() )
1629 return false;
1630
1631 if( IsPrivate() != aOther.IsPrivate() )
1632 return false;
1633
1634 if( IsGeneratedField() != aOther.IsGeneratedField() )
1635 return false;
1636
1637 if( IsNameShown() != aOther.IsNameShown() )
1638 return false;
1639
1640 if( CanAutoplace() != aOther.CanAutoplace() )
1641 return false;
1642
1643 return EDA_TEXT::operator==( aOther );
1644}
1645
1646
1647double SCH_FIELD::Similarity( const SCH_ITEM& aOther ) const
1648{
1649 if( Type() != aOther.Type() )
1650 return 0.0;
1651
1652 if( m_Uuid == aOther.m_Uuid )
1653 return 1.0;
1654
1655 const SCH_FIELD& field = static_cast<const SCH_FIELD&>( aOther );
1656
1657 double similarity = 0.99; // The UUIDs are different, so we start with non-identity
1658
1659 if( GetId() != field.GetId() )
1660 {
1661 // We don't allow swapping of mandatory fields, so these cannot be the same item
1662 if( IsMandatory() || field.IsMandatory() )
1663 return 0.0;
1664 else
1665 similarity *= 0.5;
1666 }
1667
1668 similarity *= SimilarityBase( aOther );
1669
1670 similarity *= EDA_TEXT::Similarity( field );
1671
1672 if( GetPosition() != field.GetPosition() )
1673 similarity *= 0.5;
1674
1675 if( IsGeneratedField() != field.IsGeneratedField() )
1676 similarity *= 0.5;
1677
1678 if( IsNameShown() != field.IsNameShown() )
1679 similarity *= 0.5;
1680
1681 if( CanAutoplace() != field.CanAutoplace() )
1682 similarity *= 0.5;
1683
1684 return similarity;
1685}
1686
1687
1688int SCH_FIELD::compare( const SCH_ITEM& aOther, int aCompareFlags ) const
1689{
1690 wxASSERT( aOther.Type() == SCH_FIELD_T );
1691
1692 int retv = SCH_ITEM::compare( aOther, aCompareFlags );
1693
1694 if( retv )
1695 return retv;
1696
1697 const SCH_FIELD* tmp = static_cast<const SCH_FIELD*>( &aOther );
1698
1699 // If we're not testing the UUID then we're looking for an equivalence test
1700 if( !( aCompareFlags & COMPARE_FLAGS::UUID ) )
1701 {
1702 // Mandatory fields have fixed ordinals and their names can vary due to translated field
1703 // names. Optional fields have fixed names and their ordinals can vary.
1704 if( IsMandatory() )
1705 {
1706 if( m_id != tmp->m_id )
1707 return (int) m_id - (int) tmp->m_id;
1708 }
1709 else
1710 {
1711 retv = m_name.Cmp( tmp->m_name );
1712
1713 if( retv )
1714 return retv;
1715 }
1716 }
1717 else // assume we're sorting for stable file order
1718 {
1719 if( m_id != tmp->m_id )
1720 return (int) m_id - (int) tmp->m_id;
1721 }
1722
1723 if( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::FIELD_TEXT )
1724 {
1725 retv = GetText().CmpNoCase( tmp->GetText() );
1726
1727 if( retv != 0 )
1728 return retv;
1729 }
1730
1731 if( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::FIELD_POSITIONS )
1732 {
1733 if( GetTextPos().x != tmp->GetTextPos().x )
1734 return GetTextPos().x - tmp->GetTextPos().x;
1735
1736 if( GetTextPos().y != tmp->GetTextPos().y )
1737 return GetTextPos().y - tmp->GetTextPos().y;
1738 }
1739
1740 if( aCompareFlags & COMPARE_FLAGS::FIELD_SIZE_AND_STYLE )
1741 {
1742 retv = GetAttributes().Compare( tmp->GetAttributes() );
1743
1744 if( retv )
1745 return retv;
1746 }
1747
1748 return 0;
1749}
1750
1751
1752wxString SCH_FIELD::getUnescapedText( const SCH_SHEET_PATH* aPath, const wxString& aVariantName ) const
1753{
1754 // This is the default variant field text for all fields except the reference field.
1755 wxString retv = EDA_TEXT::GetShownText( INTERNAL );
1756
1757 // Special handling for parent object field instance and variant information.
1758 // Only use the path if it's non-empty; an empty path can't match any instances
1759 if( m_parent && aPath && !aPath->empty() )
1760 {
1761 const bool trace = wxLog::IsAllowedTraceMask( traceSchFieldRendering );
1762
1763 if( trace )
1764 wxLogTrace( traceSchFieldRendering, " Path is valid and non-empty, parent type=%d", m_parent->Type() );
1765
1766 switch( m_parent->Type() )
1767 {
1768 case SCH_SYMBOL_T:
1769 if( const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( m_parent ) )
1770 {
1771 if( m_id == FIELD_T::REFERENCE )
1772 {
1773 if( trace )
1774 {
1775 wxLogTrace( traceSchFieldRendering, " Calling GetRef for symbol %s on path %s",
1776 symbol->m_Uuid.AsString(), aPath->Path().AsString() );
1777 }
1778
1779 retv = symbol->GetRef( aPath, true );
1780
1781 if( trace )
1782 wxLogTrace( traceSchFieldRendering, " GetRef returned: '%s'", retv );
1783 }
1784 else if( !aVariantName.IsEmpty() )
1785 {
1786 // If the variant is not found, fall back to default variant above.
1787 if( std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( *aPath, aVariantName ) )
1788 {
1789 // An explicit override wins; otherwise resolve through the alternate
1790 // library symbol so the canvas matches the fields table and netlist.
1791 if( variant->m_Fields.contains( GetName() ) )
1792 {
1793 retv = variant->m_Fields[GetName()];
1794 }
1795 else if( LIB_SYMBOL* altSymbol = symbol->GetVariantLibSymbol( aVariantName, *aPath ) )
1796 {
1797 const SCH_FIELD* altField = altSymbol->GetField( GetName() );
1798
1799 if( altField && !altField->GetText().IsEmpty() )
1800 retv = altField->GetText();
1801 }
1802 }
1803 }
1804 }
1805
1806 break;
1807
1808 case SCH_SHEET_T:
1809 if( const SCH_SHEET* sheet = static_cast<const SCH_SHEET*>( m_parent ) )
1810 {
1811 if( !aVariantName.IsEmpty() )
1812 {
1813 const SCH_SHEET_INSTANCE* instance = sheet->GetInstance( aPath->Path() );
1814
1815 if( instance
1816 && instance->m_Variants.contains( aVariantName )
1817 && instance->m_Variants.at( aVariantName ).m_Fields.contains( GetName() ) )
1818 {
1819 return instance->m_Variants.at( aVariantName ).m_Fields.at( GetName() );
1820 }
1821 }
1822 }
1823
1824 break;
1825
1826 default:
1827 break;
1828 }
1829 }
1830
1831 return retv;
1832}
1833
1834
1835static struct SCH_FIELD_DESC
1836{
1838 {
1839 // These are defined in EDA_TEXT as well but initialization order is
1840 // not defined, so this needs to be conditional. Defining in both
1841 // places leads to duplicate symbols.
1843
1844 if( h_inst.Choices().GetCount() == 0 )
1845 {
1846 h_inst.Map( GR_TEXT_H_ALIGN_LEFT, _HKI( "Left" ) );
1847 h_inst.Map( GR_TEXT_H_ALIGN_CENTER, _HKI( "Center" ) );
1848 h_inst.Map( GR_TEXT_H_ALIGN_RIGHT, _HKI( "Right" ) );
1849 }
1850
1852
1853 if( v_inst.Choices().GetCount() == 0 )
1854 {
1855 v_inst.Map( GR_TEXT_V_ALIGN_TOP, _HKI( "Top" ) );
1856 v_inst.Map( GR_TEXT_V_ALIGN_CENTER, _HKI( "Center" ) );
1857 v_inst.Map( GR_TEXT_V_ALIGN_BOTTOM, _HKI( "Bottom" ) );
1858 }
1859
1866
1867 // Lock state is inherited from parent symbol (no independent locking of child items)
1868 propMgr.Mask( TYPE_HASH( SCH_FIELD ), TYPE_HASH( SCH_ITEM ), _HKI( "Locked" ) );
1869
1870 // Library fields are written at symbol scope rather than inside a unit body, so a
1871 // per-unit or per-body-style assignment is silently dropped by the next save
1872 propMgr.Mask( TYPE_HASH( SCH_FIELD ), TYPE_HASH( SCH_ITEM ), _HKI( "Unit" ) );
1873 propMgr.Mask( TYPE_HASH( SCH_FIELD ), TYPE_HASH( SCH_ITEM ), _HKI( "Body Style" ) );
1874
1875 const wxString textProps = _HKI( "Text Properties" );
1876
1877 propMgr.ReplaceProperty( TYPE_HASH( EDA_TEXT ), _HKI( "Horizontal Justification" ),
1878 new PROPERTY_ENUM<SCH_FIELD, GR_TEXT_H_ALIGN_T>( _HKI( "Horizontal Justification" ),
1880 textProps );
1881
1882 propMgr.ReplaceProperty( TYPE_HASH( EDA_TEXT ), _HKI( "Vertical Justification" ),
1883 new PROPERTY_ENUM<SCH_FIELD, GR_TEXT_V_ALIGN_T>( _HKI( "Vertical Justification" ),
1885 textProps );
1886
1887 propMgr.AddProperty( new PROPERTY<SCH_FIELD, bool>( _HKI( "Show Field Name" ),
1889
1890 propMgr.AddProperty( new PROPERTY<SCH_FIELD, bool>( _HKI( "Allow Autoplacement" ),
1892
1893 propMgr.Mask( TYPE_HASH( SCH_FIELD ), TYPE_HASH( EDA_TEXT ), _HKI( "Hyperlink" ) );
1894 propMgr.Mask( TYPE_HASH( SCH_FIELD ), TYPE_HASH( EDA_TEXT ), _HKI( "Thickness" ) );
1895 propMgr.Mask( TYPE_HASH( SCH_FIELD ), TYPE_HASH( EDA_TEXT ), _HKI( "Mirrored" ) );
1896 propMgr.Mask( TYPE_HASH( SCH_FIELD ), TYPE_HASH( EDA_TEXT ), _HKI( "Width" ) );
1897 propMgr.Mask( TYPE_HASH( SCH_FIELD ), TYPE_HASH( EDA_TEXT ), _HKI( "Height" ) );
1898
1899
1900 propMgr.AddProperty( new PROPERTY<SCH_FIELD, int>( _HKI( "Text Size" ),
1902 _HKI( "Text Properties" ) );
1903
1904 propMgr.Mask( TYPE_HASH( SCH_FIELD ), TYPE_HASH( EDA_TEXT ), _HKI( "Orientation" ) );
1905
1907 []( INSPECTABLE* aItem ) -> bool
1908 {
1909 if( SCH_FIELD* field = dynamic_cast<SCH_FIELD*>( aItem ) )
1910 return !field->IsGeneratedField();
1911
1912 return true;
1913 } );
1914
1915
1916 propMgr.OverrideAvailability( TYPE_HASH( SCH_FIELD ), TYPE_HASH( SCH_ITEM ), _HKI( "Private" ),
1917 []( INSPECTABLE* aItem ) -> bool
1918 {
1919 if( SCH_FIELD* field = dynamic_cast<SCH_FIELD*>( aItem ) )
1920 return !field->IsMandatory();
1921
1922 return false;
1923 } );
1924 }
1926
1927
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:130
BITMAPS
A list of all bitmap identifiers.
@ edit_comp_value
@ edit_comp_footprint
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:553
constexpr const Vec GetEnd() const
Definition box2.h:209
constexpr void SetOrigin(const Vec &pos)
Definition box2.h:234
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition box2.h:143
constexpr Vec Centre() const
Definition box2.h:94
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:165
constexpr void Move(const Vec &aMoveVector)
Move the rectangle by the aMoveVector.
Definition box2.h:135
constexpr const Vec & GetOrigin() const
Definition box2.h:207
constexpr void SetEnd(coord_type x, coord_type y)
Definition box2.h:294
constexpr void Offset(coord_type dx, coord_type dy)
Definition box2.h:256
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition box2.h:308
static const COLOR4D WHITE
Definition color4d.h:403
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:400
bool IsHorizontal() const
Definition eda_angle.h:141
The base class for create windows for drawing purpose.
const KIID m_Uuid
Definition eda_item.h:599
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
EDA_ITEM_FLAGS m_flags
Definition eda_item.h:608
virtual bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const
Compare the item against the search criteria in aSearchData.
Definition eda_item.h:484
EDA_ITEM * GetParent() const
Definition eda_item.h:112
EDA_ITEM * m_parent
Owner.
Definition eda_item.h:609
bool IsForceVisible() const
Definition eda_item.h:233
static bool Replace(const EDA_SEARCH_DATA &aSearchData, wxString &aText)
Perform a text replace on aText using the find and replace criteria in aSearchData on items that supp...
Definition eda_item.cpp:396
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:84
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:94
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Definition eda_text.cpp:170
virtual VECTOR2I GetTextSize() const
Definition eda_text.h:301
COLOR4D GetTextColor() const
Definition eda_text.h:310
wxString GetTextStyleName() const
virtual VECTOR2I GetTextPos() const
Definition eda_text.h:313
bool IsItalic() const
Definition eda_text.h:200
virtual void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition eda_text.cpp:512
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:118
virtual bool IsVisible() const
Definition eda_text.h:226
virtual void SetTextPos(const VECTOR2I &aPoint)
Definition eda_text.cpp:556
virtual void SetTextX(int aX)
Definition eda_text.cpp:563
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
Definition eda_text.cpp:200
KIFONT::FONT * GetFont() const
Definition eda_text.h:286
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
Definition eda_text.cpp:394
virtual void SetTextY(int aY)
Definition eda_text.cpp:569
EDA_TEXT & operator=(const EDA_TEXT &aItem)
Definition eda_text.cpp:140
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:754
virtual wxString GetShownText(RESOLUTION_CONTEXT aContext, int aDepth=0) const
Return the string actually shown after processing of the base text.
Definition eda_text.h:128
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition eda_text.cpp:378
virtual int GetTextWidth() const
Definition eda_text.h:304
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition eda_text.h:239
bool Replace(const EDA_SEARCH_DATA &aSearchData)
Helper function used in search and replace dialog.
Definition eda_text.cpp:450
bool HasTextVars() const
Indicates the ShownText has text var references which need to be processed.
Definition eda_text.h:139
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:347
EDA_TEXT(const EDA_IU_SCALE &aIuScale, const wxString &aText=wxEmptyString)
Definition eda_text.cpp:98
virtual void ClearBoundingBoxCache()
Definition eda_text.cpp:675
double Similarity(const EDA_TEXT &aOther) const
static GR_TEXT_H_ALIGN_T MapHorizJustify(int aHorizJustify)
Definition eda_text.cpp:70
virtual void ClearRenderCache()
Definition eda_text.cpp:669
virtual EDA_ANGLE GetTextAngle() const
Definition eda_text.h:178
const TEXT_ATTRIBUTES & GetAttributes() const
Definition eda_text.h:270
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
Definition eda_text.cpp:427
void SwapAttributes(EDA_TEXT &aTradingPartner)
Swap the text attributes of the two involved instances.
Definition eda_text.cpp:414
bool IsBold() const
Definition eda_text.h:215
static GR_TEXT_V_ALIGN_T MapVertJustify(int aVertJustify)
Definition eda_text.cpp:84
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition eda_text.h:242
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:236
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition eda_text.cpp:268
void SwapText(EDA_TEXT &aTradingPartner)
Definition eda_text.cpp:406
bool operator==(const EDA_TEXT &aRhs) const
Definition eda_text.h:444
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition eda_text.cpp:370
static ENUM_MAP< T > & Instance()
Definition property.h:792
Class that other classes need to inherit from, in order to be inspectable.
Definition inspectable.h:39
FONT is an abstract base class for both outline and stroke fonts.
Definition font.h:94
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
Definition font.cpp:144
virtual bool IsOutline() const
Definition font.h:102
Implement outline font drawing.
void GetLinesAsGlyphs(std::vector< std::unique_ptr< GLYPH > > *aGlyphs, const wxString &aText, const VECTOR2I &aPosition, const TEXT_ATTRIBUTES &aAttrs, const METRICS &aFontMetrics) const
void Move(const VECTOR2I &aOffset)
Definition glyph.cpp:115
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
std::shared_ptr< wxString > m_text
Definition color4d.h:397
COLOR4D & Desaturate()
Removes color (in HSL model)
Definition color4d.cpp:530
COLOR4D Mix(const COLOR4D &aColor, double aFactor) const
Return a color that is mixed with the input by a factor.
Definition color4d.h:293
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.
wxString AsString() const
Definition kiid.cpp:423
COLOR4D GetSchematicColor(bool aIsForSave=false) const
Definition netclass.h:244
A singleton reporter that reports to nowhere.
Definition reporter.h:267
Base plotter engine class.
Definition plotter.h:138
bool GetColorMode() const
Definition plotter.h:166
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:618
virtual void HyperlinkMenu(const BOX2I &aBox, const std::vector< wxString > &aDestURLs)
Create a clickable hyperlink menu with a rectangular click area.
Definition plotter.h:536
virtual std::map< wxString, wxString > & GetTextVars() const
Definition project.cpp:222
Provide class metadata.
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 OverrideAvailability(TYPE_ID aDerived, TYPE_ID aBase, const wxString &aName, std::function< bool(INSPECTABLE *)> aFunc)
Sets an override availability functor for a base class property of a given derived class.
PROPERTY_BASE & ReplaceProperty(size_t aBase, const wxString &aName, PROPERTY_BASE *aNew, const wxString &aGroup=wxEmptyString)
Replace an existing property for a specific type.
void OverrideWriteability(TYPE_ID aDerived, TYPE_ID aBase, const wxString &aName, std::function< bool(INSPECTABLE *)> aFunc)
Sets an override writeability functor for a base class property of a given derived class.
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:149
SCHEMATIC_SETTINGS & Settings() const
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
PROJECT & Project() const
Return a reference to the project this schematic is part of.
Definition schematic.h:171
wxString GetCurrentVariant() const
Return the current variant being edited.
EMBEDDED_FILES * GetEmbeddedFiles() override
SCH_SHEET_PATH & CurrentSheet() const
Definition schematic.h:312
void ClearRenderCache() override
int compare(const SCH_ITEM &aOther, int aCompareFlags=0) const override
Provide the draw object specific comparison called by the == and < operators.
COLOR4D m_lastResolvedColor
Definition sch_field.h:379
GR_TEXT_V_ALIGN_T GetEffectiveVertJustify() const
bool IsMandatory() const
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
bool HasSameContent(const SCH_FIELD &aOther) const
Test if this field has the same name, content and presentation as another field, ignoring the owning ...
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
wxString GetFullText(int unit=1) const
Return the text of a field.
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
bool IsLocked() const override
void swapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
VECTOR2I GetPosition() const override
void SetEffectiveHorizJustify(GR_TEXT_H_ALIGN_T)
int GetSchTextSize() const
Definition sch_field.h:190
bool Replace(const EDA_SEARCH_DATA &aSearchData, void *aAuxData=nullptr) override
Perform a text replace using the find and replace criteria in aSearchData on items that support text ...
bool m_showName
Render the field name in addition to its value.
Definition sch_field.h:369
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.
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
bool IsNameShown() const
Definition sch_field.h:229
bool m_autoAdded
Was this field automatically added to a LIB_SYMBOL?
Definition sch_field.h:374
double Similarity(const SCH_ITEM &aItem) const override
Return a measure of how likely the other object is to represent the same object.
std::unique_ptr< SCH_FIELD_RENDER_CACHE_DATA > m_renderCache
Definition sch_field.h:377
bool IsGeneratedField() const
Generated fields are fields whose names are variables like ${VAR}.
Definition sch_field.h:238
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
SCH_LAYER_ID GetDefaultLayer() const
bool HasHypertext() const override
Indicates that the item has at least one hypertext action.
bool IsHorizJustifyFlipped() const
Return whether the field will be rendered with the horizontal justification inverted due to rotation ...
bool IsVertJustifyFlipped() const
EDA_ANGLE GetDrawRotation() const override
Adjusters to allow EDA_TEXT to draw/print/etc.
void SetEffectiveVertJustify(GR_TEXT_V_ALIGN_T)
void CalcEdit(const VECTOR2I &aPosition) override
Calculate the attributes of an item at aPosition when it is being edited.
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:139
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
FIELD_T GetId() const
Definition sch_field.h:143
void SetCanAutoplace(bool aCanPlace)
Definition sch_field.h:241
int GetPenWidth() const override
bool m_isGeneratedField
If the field name is a variable name (e.g.
Definition sch_field.h:371
int m_ordinal
Sort order for non-mandatory fields.
Definition sch_field.h:366
COLOR4D GetFieldColor() const
wxString getUnescapedText(const SCH_SHEET_PATH *aPath=nullptr, const wxString &aVariantName=wxEmptyString) const
bool operator==(const SCH_ITEM &aItem) const override
SCH_FIELD & operator=(const SCH_FIELD &aField)
void ImportValues(const SCH_FIELD &aSource)
Copy parameters from a SCH_FIELD source.
wxString GetUntranslatedName() const
Get the untranslated field name for storage, variable look-up, etc.
bool operator<(const SCH_ITEM &aItem) const override
FIELD_T m_id
Field id,.
Definition sch_field.h:365
void DoHypertextAction(EDA_DRAW_FRAME *aFrame, const VECTOR2I &aMousePos) const override
wxString GetShownName() const
Get the field's name as displayed on the schematic or in the symbol fields table.
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
VECTOR2I GetLibPosition() const
Definition sch_field.h:287
void setId(FIELD_T aId)
int GetOrdinal() const
Definition sch_field.h:145
bool IsEmpty()
Return true if both the name and value of the field are empty.
Definition sch_field.h:182
KIFONT::FONT * GetDrawFont(const RENDER_SETTINGS *aSettings) const override
void BeginEdit(const VECTOR2I &aStartPoint) override
Begin drawing a symbol library draw item at aPosition.
bool IsReplaceable() const override
Override this method in any derived object that supports test find and replace.
void SetSchTextSize(int aSize)
Definition sch_field.h:191
wxString GetShownText(const SCH_SHEET_PATH *aPath, RESOLUTION_CONTEXT aContext, const wxString &aVariantName=wxEmptyString, int aDepth=0) const
GR_TEXT_H_ALIGN_T GetEffectiveHorizJustify() const
std::vector< int > ViewGetLayers() const override
Return the all the layers within the VIEW the object is painted on.
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
void SetPosition(const VECTOR2I &aPosition) override
void SetName(const wxString &aName)
bool CanAutoplace() const
Definition sch_field.h:240
std::vector< std::unique_ptr< KIFONT::GLYPH > > * GetRenderCache(const wxString &forResolvedText, const VECTOR2I &forPosition, TEXT_ATTRIBUTES &aAttrs) const
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.
void ClearCaches() override
void SetText(const wxString &aText) override
VECTOR2I GetParentPosition() const
bool m_showInChooser
This field is available as a data column for the chooser.
Definition sch_field.h:375
void OnScintillaCharAdded(SCINTILLA_TRICKS *aScintillaTricks, wxStyledTextEvent &aEvent) const
wxString m_name
Definition sch_field.h:367
void SetNameShown(bool aShown=true)
Definition sch_field.h:230
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
static bool IsNetclassLabelFieldName(const wxString &aName)
Test whether aName is one of the known translations of the directive-label net class field name (used...
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
void Copy(SCH_FIELD *aTarget) const
Copy parameters of this field to another field.
bool m_allowAutoPlace
This field can be autoplaced.
Definition sch_field.h:370
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...
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:170
SCH_ITEM & operator=(const SCH_ITEM &aPin)
Definition sch_item.cpp:91
const wxString & GetDefaultFont(const KIGFX::RENDER_SETTINGS *aSettings) const
void invalidateConnectivity(KICAD_T aChangedType=TYPE_NOT_INIT)
Bump the parent screen's connectivity revision when this item, or the item owning it as a child,...
Definition sch_item.cpp:323
SCH_RENDER_SETTINGS * getRenderSettings(PLOTTER *aPlotter) const
Definition sch_item.cpp:46
const SYMBOL * GetParentSymbol() const
Definition sch_item.cpp:350
void SetPrivate(bool aPrivate)
Definition sch_item.h:258
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:302
virtual wxString GetUnitDisplayName(int aUnit, bool aLabel) const
Definition sch_item.cpp:225
bool IsLocked() const override
Definition sch_item.cpp:179
friend class LIB_SYMBOL
Definition sch_item.h:822
@ FIELD_SIZE_AND_STYLE
Definition sch_item.h:757
@ FIELD_TEXT
Definition sch_item.h:755
@ FIELD_POSITIONS
Definition sch_item.h:758
std::shared_ptr< NETCLASS > GetEffectiveNetClass(const SCH_SHEET_PATH *aSheet=nullptr) const
Definition sch_item.cpp:733
bool IsPrivate() const
Definition sch_item.h:259
void SetLayer(SCH_LAYER_ID aLayer)
Definition sch_item.h:354
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition sch_item.h:353
bool IsConnectivityDirty() const
Definition sch_item.h:635
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:65
bool m_private
Definition sch_item.h:846
wxString ResolveText(const wxString &aText, const SCH_SHEET_PATH *aPath, int aDepth=0) const
Definition sch_item.cpp:464
virtual int compare(const SCH_ITEM &aOther, int aCompareFlags=~COMPARE_FLAGS::UNIT) const
Provide the draw object specific comparison called by the == and < operators.
Definition sch_item.cpp:935
const KIFONT::METRICS & GetFontMetrics() const
double SimilarityBase(const SCH_ITEM &aItem) const
Calculate the boilerplate similarity for all LIB_ITEMs without preventing the use above of a pure vir...
Definition sch_item.h:403
void GetIntersheetRefs(const SCH_SHEET_PATH *aPath, std::vector< std::pair< wxString, wxString > > *pages)
Build an array of { pageNumber, pageName } pairs.
static const wxString GetDefaultFieldName(const wxString &aName, bool aUseDefaultName)
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars & fields for this label.
Handle actions specific to the schematic editor.
static wxString g_BackLink
void HypertextCommand(const wxString &aHref)
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
VECTOR2I TransformCoordinate(const VECTOR2I &aPoint) const
const KIGFX::COLOR4D & GetBackgroundColor() const override
Return current background color settings.
void GetSymbols(SCH_REFERENCE_LIST &aReferences, SYMBOL_FILTER aSymbolFilter, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
bool empty() const
Forwarded method from std::vector.
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
size_t size() const
Forwarded method from std::vector.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars & fields for this sheet.
wxString GetFieldText(const SCH_FIELD *aField, const wxString &aFieldName, const SCH_SHEET_PATH *aPath, const wxString &aVariantName) const
void SetFieldText(SCH_FIELD *aField, const wxString &aFieldName, const wxString &aFieldText, const SCH_SHEET_PATH *aPath, const wxString &aVariantName)
Schematic symbol object.
Definition sch_symbol.h:75
void SetFieldText(SCH_FIELD *aField, const wxString &aFieldName, const wxString &aFieldText, const SCH_SHEET_PATH *aPath, const wxString &aVariantName)
wxString SubReference(int aUnit, bool aAddSeparator=true) const
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
void SetRef(const SCH_SHEET_PATH *aSheet, const wxString &aReference)
Set the reference for the given sheet path for this symbol.
VECTOR2I GetPosition() const override
Definition sch_symbol.h:908
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars & fields for this symbol.
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
int GetUnitCount() const override
Return the number of units per package of the symbol.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
wxString GetFieldText(const SCH_FIELD *aField, const wxString &aFieldName, const SCH_SHEET_PATH *aPath, const wxString &aVariantName) const
Add cut/copy/paste, dark theme, autocomplete and brace highlighting to a wxStyleTextCtrl instance.
wxStyledTextCtrl * Scintilla() const
void DoAutocomplete(const wxString &aPartial, const wxArrayString &aTokens)
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void Move(const VECTOR2I &aVector) override
static constexpr auto LIBRARY_FIELD
Definition sim_library.h:31
SIM_MODEL & CreateModel(SIM_MODEL::TYPE aType, std::span< const wxString > aPins, REPORTER &aReporter)
void SetFilesStack(std::vector< EMBEDDED_FILES * > aFilesStack)
Definition sim_lib_mgr.h:45
A base class for LIB_SYMBOL and SCH_SYMBOL.
Definition symbol.h:60
const TRANSFORM & GetTransform() const
Definition symbol.h:247
EDA_ORIENTATION m_Angle
int Compare(const TEXT_ATTRIBUTES &aRhs) const
GR_TEXT_H_ALIGN_T m_Halign
GR_TEXT_V_ALIGN_T m_Valign
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
T * GetTool()
Return the tool of given type or nullptr if there is no such tool registered.
for transforming drawing coordinates for a wxDC device context.
Definition transform.h:42
TRANSFORM InverseTransform() const
Calculate the Inverse mirror/rotation transform.
Definition transform.cpp:55
VECTOR2I TransformCoordinate(const VECTOR2I &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition transform.cpp:40
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
void FinalizeTextVarExpansion(wxString &aText, RESOLUTION_CONTEXT aContext)
Definition common.cpp:88
wxString GetGeneratedFieldDisplayName(const wxString &aSource)
Returns any variables unexpanded, e.g.
Definition common.cpp:481
RESOLUTION_CONTEXT
Definition common.h:91
@ FOR_GUI
Definition common.h:93
@ FOR_CANVAS
Definition common.h:92
@ RAW_VALUE
Definition common.h:98
@ INTERNAL
Definition common.h:96
#define UNSPECIFIED
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:450
static constexpr EDA_ANGLE ANGLE_VERTICAL
Definition eda_angle.h:445
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition eda_angle.h:444
static constexpr EDA_ANGLE ANGLE_270
Definition eda_angle.h:453
#define STRUCT_DELETED
flag indication structures to be erased
#define SKIP_STRUCT
flag indicating that the structure should be ignored
a few functions useful in geometry calculations.
const wxChar *const traceSchFieldRendering
Flag to enable debug output of schematic field rendering and positioning.
@ USER
The main config directory (e.g. ~/.config/kicad/)
SCH_LAYER_ID
Eeschema drawing layers.
Definition layer_ids.h:477
@ LAYER_SHEETNAME
Definition layer_ids.h:500
@ LAYER_VALUEPART
Definition layer_ids.h:489
@ LAYER_FIELDS
Definition layer_ids.h:490
@ LAYER_SHEETFIELDS
Definition layer_ids.h:502
@ LAYER_REFERENCEPART
Definition layer_ids.h:488
@ LAYER_NETCLASS_REFS
Definition layer_ids.h:492
@ LAYER_SELECTION_SHADOWS
Definition layer_ids.h:523
@ LAYER_INTERSHEET_REFS
Definition layer_ids.h:491
@ LAYER_SHEETFILENAME
Definition layer_ids.h:501
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 wxString EllipsizeStatusText(wxWindow *aWindow, const wxString &aString)
Ellipsize text (at the end) to be no more than 1/3 of the window width.
KICOMMON_API void PackCustomProperties(google::protobuf::RepeatedPtrField< types::CustomProperty > *aOutput, const EDA_ITEM &aItem)
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackVector2(types::Vector2 &aOutput, const VECTOR2I &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void UnpackCustomProperties(const google::protobuf::RepeatedPtrField< types::CustomProperty > &aInput, EDA_ITEM &aItem)
#define _HKI(x)
Definition page_info.cpp:40
static GR_TEXT_H_ALIGN_T horizJustify(const char *horizontal)
#define TYPE_HASH(x)
Macro to generate unique identifier for a type.
Definition property.h:74
#define DECLARE_ENUM_TO_WXANY(type)
Definition property.h:860
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition property.h:63
#define REGISTER_TYPE(x)
Helper macro to map type hashes to names.
static const std::vector< wxString > & GetKnownNetclassFieldTranslations()
Translations of "Net Class" extracted from KiCad's .po catalogs.
Definition sch_field.cpp:61
static const std::vector< KICAD_T > labelTypes
Definition sch_field.cpp:49
static struct SCH_FIELD_DESC _SCH_FIELD_DESC
@ SYMBOL_FILTER_NON_POWER
wxString UnescapeString(const wxString &aSource)
bool IsURL(wxString aStr)
Performs a URL sniff-test on a string.
A simple container for sheet instance information.
std::map< wxString, SCH_SHEET_VARIANT > m_Variants
A list of sheet variants.
wxString GetDefaultFieldName(FIELD_T aFieldId, TRANSLATION aTranslation)
Return a default symbol field name for a mandatory field type.
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
@ USER
The field ID hasn't been set yet; field is invalid.
@ INTERSHEET_REFS
Global label cross-reference page numbers.
@ DESCRIPTION
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ DATASHEET
name of datasheet
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
@ UNTRANSLATED
@ TRANSLATED
KIBIS_MODEL * model
KIBIS_PIN * pin
VECTOR2I end
wxString result
Test unit parsing edge cases and error handling.
int delta
GR_TEXT_H_ALIGN_T
This is API surface mapped to common.types.HorizontalAlignment.
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_H_ALIGN_INDETERMINATE
GR_TEXT_V_ALIGN_T
This is API surface mapped to common.types.VertialAlignment.
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_INDETERMINATE
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
wxLogTrace helper definitions.
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:227
@ LIB_SYMBOL_T
Definition typeinfo.h:144
@ SCH_SYMBOL_T
Definition typeinfo.h:168
@ SCH_FIELD_T
Definition typeinfo.h:146
@ SCH_DIRECTIVE_LABEL_T
Definition typeinfo.h:167
@ SCH_LABEL_T
Definition typeinfo.h:163
@ SCH_SHEET_T
Definition typeinfo.h:171
@ SCH_LABEL_LOCATE_ANY_T
Definition typeinfo.h:187
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:164
Casted dyn_cast(From aObject)
A lightweight dynamic downcast.
Definition typeinfo.h:55
#define INDETERMINATE_STATE
Used for holding indeterminate values, such as with multiple selections holding different values or c...
Definition ui_common.h:47
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708