KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_label_properties.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) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2013 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
27#include <widgets/font_choice.h>
32#include <sch_edit_frame.h>
33#include <tool/tool_manager.h>
34#include <gr_text.h>
35#include <confirm.h>
36#include <schematic.h>
39#include <string_utils.h>
40#include <kiface_base.h>
41#include <sch_label.h>
42#include <sch_commit.h>
43
44
47 m_Parent( aParent ),
48 m_currentLabel( aLabel ),
49 m_activeTextEntry( nullptr ),
50 m_netNameValidator( true ),
51 m_fields( nullptr ),
52 m_textSize( aParent, m_textSizeLabel, m_textSizeCtrl, m_textSizeUnits, false ),
53 m_helpWindow( nullptr ),
54 m_labelList( nullptr )
55{
56 COLOR_SETTINGS* colorSettings = m_Parent->GetColorSettings();
57 COLOR4D schematicBackground = colorSettings->GetColor( LAYER_SCHEMATIC_BACKGROUND );
58 bool multiLine = false;
59
60 if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
61 multiLine = cfg->m_Appearance.edit_label_multiple;
62
63 m_cbMultiLine->SetValue( multiLine );
64
65 m_fields = new FIELDS_GRID_TABLE( this, aParent, m_grid, m_currentLabel );
66 m_width = 100; // Will be later set to a better value
69
71 {
73 SetInitialFocus( m_valueCombo->GetTextCtrl() );
74
75 m_labelSingleLine->Show( false );
76 m_valueSingleLine->Show( false );
77
78 if( multiLine && aNew )
79 {
82 m_labelCombo->Show( false );
83 m_valueCombo->Show( false );
84 }
85 else
86 {
87 m_labelMultiLine->Show( false );
88 m_valueMultiLine->Show( false );
89 m_valueCombo->SetValidator( m_netNameValidator );
90 }
91 }
92 else if( m_currentLabel->Type() == SCH_HIER_LABEL_T )
93 {
96
97 m_labelCombo->Show( false );
98 m_valueCombo->Show( false );
99
100 if( multiLine && aNew )
101 {
104 m_labelSingleLine->Show( false );
105 m_valueSingleLine->Show( false );
106 }
107 else
108 {
109 m_labelMultiLine->Show( false );
110 m_valueMultiLine->Show( false );
111 m_valueSingleLine->SetValidator( m_netNameValidator );
112 }
113 }
115 {
118
119 m_labelSingleLine->Show( false );
120 m_valueSingleLine->Show( false );
121 m_labelCombo->Show( false );
122 m_valueCombo->Show( false );
123 m_syntaxHelp->Show( false );
124 m_textEntrySizer->Show( false );
125 m_labelCombo->Show( false );
126 m_valueCombo->Show( false );
127 m_cbMultiLine->Show( false );
128
129 m_textSizeLabel->SetLabel( _( "Pin length:" ) );
130 }
131
132 if( !aNew )
133 m_cbMultiLine->Show( false );
134
135 switch( m_currentLabel->Type() )
136 {
137 case SCH_GLOBAL_LABEL_T: SetTitle( _( "Global Label Properties" ) ); break;
138 case SCH_HIER_LABEL_T: SetTitle( _( "Hierarchical Label Properties" ) ); break;
139 case SCH_LABEL_T: SetTitle( _( "Label Properties" ) ); break;
140 case SCH_DIRECTIVE_LABEL_T: SetTitle( _( "Directive Label Properties" ) ); break;
141 case SCH_SHEET_PIN_T: SetTitle( _( "Hierarchical Sheet Pin Properties" ) ); break;
142 default: UNIMPLEMENTED_FOR( m_currentLabel->GetClass() ); break;
143 }
144
146 m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this, {},
147 [&]( wxCommandEvent& aEvent )
148 {
149 OnAddField( aEvent );
150 } ) );
151 m_grid->SetSelectionMode( wxGrid::wxGridSelectRows );
152
153 // Show/hide columns according to user's preference
154 if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
155 {
156 m_grid->ShowHideColumns( cfg->m_Appearance.edit_label_visible_columns );
158 }
159
160 // Configure button logos
161 m_bpAdd->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
162 m_bpDelete->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
163 m_bpMoveUp->SetBitmap( KiBitmapBundle( BITMAPS::small_up ) );
164 m_bpMoveDown->SetBitmap( KiBitmapBundle( BITMAPS::small_down ) );
165
167
169 m_bold->SetBitmap( KiBitmapBundle( BITMAPS::text_bold ) );
171 m_italic->SetBitmap( KiBitmapBundle( BITMAPS::text_italic ) );
172
174
179
181
182 m_textColorSwatch->SetDefaultColor( COLOR4D::UNSPECIFIED );
183 m_textColorSwatch->SetSwatchBackground( schematicBackground );
184
185 // Show/hide relevant controls
187 {
188 m_dot->Hide();
189 m_circle->Hide();
190 m_diamond->Hide();
191 m_rectangle->Hide();
192
193 m_spin0->SetBitmap( KiBitmapBundle( BITMAPS::label_align_left ) );
194 m_spin1->SetBitmap( KiBitmapBundle( BITMAPS::label_align_right ) );
195 m_spin2->SetBitmap( KiBitmapBundle( BITMAPS::label_align_bottom ) );
196 m_spin3->SetBitmap( KiBitmapBundle( BITMAPS::label_align_top ) );
197 }
199 {
200 m_input->Hide();
201 m_output->Hide();
202 m_bidirectional->Hide();
203 m_triState->Hide();
204 m_passive->Hide();
205
206 m_fontLabel->SetLabel( _( "Orientation:" ) );
207 m_fontCtrl->Hide();
208 m_separator1->Hide();
209 m_bold->Hide();
210 m_italic->Hide();
211 m_separator2->Hide();
212 m_spin0->SetBitmap( KiBitmapBundle( BITMAPS::pinorient_down ) );
213 m_spin1->SetBitmap( KiBitmapBundle( BITMAPS::pinorient_up ) );
214 m_spin2->SetBitmap( KiBitmapBundle( BITMAPS::pinorient_right ) );
215 m_spin3->SetBitmap( KiBitmapBundle( BITMAPS::pinorient_left ) );
216 m_separator3->Hide();
217
218 m_formattingGB->Detach( m_fontCtrl );
219 m_formattingGB->Detach( m_iconBar );
220 m_formattingGB->Add( m_iconBar, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxEXPAND | wxRIGHT, 5 );
221 }
222 else
223 {
224 m_shapeSizer->Show( false );
225
226 m_spin0->SetBitmap( KiBitmapBundle( BITMAPS::text_align_left ) );
227 m_spin1->SetBitmap( KiBitmapBundle( BITMAPS::text_align_right ) );
228 m_spin2->SetBitmap( KiBitmapBundle( BITMAPS::text_align_bottom ) );
229 m_spin3->SetBitmap( KiBitmapBundle( BITMAPS::text_align_top ) );
230 }
231
233 {
234 m_autoRotate->Hide();
235 wxSizer* parentSizer = m_autoRotate->GetContainingSizer();
236 parentSizer->Detach( m_autoRotate );
237 parentSizer->Layout();
238 }
239
241
242 // DIALOG_SHIM needs a unique hash_key because classname is not sufficient because the
243 // various versions have different controls so we want to store sizes for each version.
244 m_hash_key = TO_UTF8( GetTitle() );
245
246 m_spin0->Bind( wxEVT_BUTTON, &DIALOG_LABEL_PROPERTIES::onSpinButton, this );
247 m_spin1->Bind( wxEVT_BUTTON, &DIALOG_LABEL_PROPERTIES::onSpinButton, this );
248 m_spin2->Bind( wxEVT_BUTTON, &DIALOG_LABEL_PROPERTIES::onSpinButton, this );
249 m_spin3->Bind( wxEVT_BUTTON, &DIALOG_LABEL_PROPERTIES::onSpinButton, this );
250
251 // Now all widgets have the size fixed, call FinishDialogSettings
253
254 if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
255 {
256 if( cfg->m_Appearance.edit_label_width > 0 && cfg->m_Appearance.edit_label_height > 0 )
257 SetSize( cfg->m_Appearance.edit_label_width, cfg->m_Appearance.edit_label_height );
258 }
259}
260
261
263{
264 if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
265 {
266 cfg->m_Appearance.edit_label_visible_columns = m_grid->GetShownColumnsAsString();
267 cfg->m_Appearance.edit_label_width = GetSize().x;
268 cfg->m_Appearance.edit_label_height = GetSize().y;
269 cfg->m_Appearance.edit_label_multiple = m_cbMultiLine->IsChecked();
270 }
271
272 // Prevents crash bug in wxGrid's d'tor
274
275 // Delete the GRID_TRICKS.
276 m_grid->PopEventHandler( true );
277
278 if( m_helpWindow )
279 m_helpWindow->Destroy();
280}
281
282
284{
285 if( !wxDialog::TransferDataToWindow() )
286 return false;
287
288 wxString text;
289
291 {
292 // show control characters in a human-readable format
294
295 // show text variable cross-references in a human-readable format
297 }
298
300 {
301 // Load the combobox with the existing labels of the same type
302 std::set<wxString> existingLabels;
303 std::vector<std::shared_ptr<BUS_ALIAS>> busAliases;
304 SCH_SCREENS allScreens( m_Parent->Schematic().Root() );
305
306 for( SCH_SCREEN* screen = allScreens.GetFirst(); screen; screen = allScreens.GetNext() )
307 {
308 for( SCH_ITEM* item : screen->Items().OfType( m_currentLabel->Type() ) )
309 {
310 const SCH_LABEL_BASE* label = static_cast<const SCH_LABEL_BASE*>( item );
311 existingLabels.insert( UnescapeString( label->GetText() ) );
312 }
313
314 // Add global power labels from power symbols
316 {
317 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_LOCATE_POWER_T ) )
318 {
319 const SCH_SYMBOL* power = static_cast<const SCH_SYMBOL*>( item );
320
321 // Ensure the symbol has the Power (i.e. equivalent to a global label
322 // before adding its value in list
323 if( power->IsSymbolLikePowerGlobalLabel() )
324 {
325 const SCH_FIELD* valueField = power->GetField( FIELD_T::VALUE );
326 existingLabels.insert( UnescapeString( valueField->GetText() ) );
327 }
328 }
329 }
330
331 // Add local power labels from power symbols
333 {
334 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_LOCATE_POWER_T ) )
335 {
336 const SCH_SYMBOL* power = static_cast<const SCH_SYMBOL*>( item );
337
338 // Ensure the symbol has the Power (i.e. equivalent to a local label
339 // before adding its value in list
340 if( power->IsSymbolLikePowerLocalLabel() )
341 {
342 const SCH_FIELD* valueField = power->GetField( FIELD_T::VALUE );
343 existingLabels.insert( UnescapeString( valueField->GetText() ) );
344 }
345 }
346 }
347 // Add bus aliases from the current screen
348
349 auto& sheetAliases = screen->GetBusAliases();
350 busAliases.insert( busAliases.end(), sheetAliases.begin(), sheetAliases.end() );
351 }
352
353 // Add bus aliases to label list
354 for( const std::shared_ptr<BUS_ALIAS>& busAlias : busAliases )
355 existingLabels.insert( wxT( "{" ) + busAlias->GetName() + wxT( "}" ) );
356
357 for( const wxString& label : existingLabels )
358 m_existingLabelArray.push_back( label );
359
362 }
363 else if( m_activeTextEntry )
364 {
365 m_activeTextEntry->SetValue( text );
366 }
367
368 // Push a copy of each field into m_updateFields
369 for( SCH_FIELD& field : m_currentLabel->GetFields() )
370 {
371 SCH_FIELD field_copy( field );
372
373 // change offset to be symbol-relative
374 field_copy.Offset( -m_currentLabel->GetPosition() );
375
376 m_fields->push_back( field_copy );
377 }
378
379 // notify the grid
380 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, (int) m_fields->size() );
381 m_grid->ProcessTableMessage( msg );
382 AdjustGridColumns( m_grid->GetRect().GetWidth() );
383
384 if( m_shapeSizer->AreAnyItemsShown() )
385 {
386 switch( m_currentLabel->GetShape() )
387 {
388 case LABEL_FLAG_SHAPE::L_INPUT: m_input->SetValue( true ); break;
389 case LABEL_FLAG_SHAPE::L_OUTPUT: m_output->SetValue( true ); break;
390 case LABEL_FLAG_SHAPE::L_BIDI: m_bidirectional->SetValue( true ); break;
391 case LABEL_FLAG_SHAPE::L_TRISTATE: m_triState->SetValue( true ); break;
392 case LABEL_FLAG_SHAPE::L_UNSPECIFIED: m_passive->SetValue( true ); break;
393 case LABEL_FLAG_SHAPE::F_DOT: m_dot->SetValue( true ); break;
394 case LABEL_FLAG_SHAPE::F_ROUND: m_circle->SetValue( true ); break;
395 case LABEL_FLAG_SHAPE::F_DIAMOND: m_diamond->SetValue( true ); break;
396 case LABEL_FLAG_SHAPE::F_RECTANGLE: m_rectangle->SetValue( true ); break;
397 }
398 }
399
401
403 m_textSize.SetValue( static_cast<SCH_DIRECTIVE_LABEL*>( m_currentLabel )->GetPinLength() );
404 else
406
410
411 switch( m_currentLabel->GetSpinStyle() )
412 {
413 case SPIN_STYLE::RIGHT: m_spin0->Check( true ); break;
414 case SPIN_STYLE::LEFT: m_spin1->Check( true ); break;
415 case SPIN_STYLE::UP: m_spin2->Check( true ); break;
416 case SPIN_STYLE::BOTTOM: m_spin3->Check( true ); break;
417 }
418
421
422 return true;
423}
424
425
426void DIALOG_LABEL_PROPERTIES::OnEnterKey( wxCommandEvent& aEvent )
427{
428 wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
429}
430
431
433{
434 // If the key is WXK_RETURN because m_valueCombo is the source event, we do not skip
435 // the key event because the default action is to show the m_valueCombo dropdown list,
436 // and we only want to accept the entered string.
437 if( aEvent.GetKeyCode() == WXK_RETURN )
438 {
439 wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
440 }
441 else if( aEvent.GetKeyCode() == WXK_SPACE )
442 {
443 // our FILTER_COMBOBOX uses the space as special command, not wanted here,
444 // to open the dropdown list of labels.
445 // So just add the space char to the current text, at current insertion point,
446 // and do not skip this event
447 m_activeTextEntry->WriteText( wxT(" " ) );
448 }
449 else
450 {
451 aEvent.Skip();
452 }
453}
454
455
457{
458 if( aEvent.GetKeyCode() == WXK_TAB )
459 {
460 if( aEvent.ShiftDown() )
461 {
462 m_textSizeCtrl->SetFocusFromKbd();
463 }
464 else if( !m_fields->empty() )
465 {
466 m_grid->SetFocusFromKbd();
467 m_grid->MakeCellVisible( 0, 0 );
468 m_grid->SetGridCursor( 0, 0 );
469 }
470 else
471 {
472 m_textSizeCtrl->SetFocusFromKbd();
473 }
474 }
475 else
476 {
477 aEvent.Skip();
478 }
479}
480
481
482static bool positioningChanged( const SCH_FIELD& a, const SCH_FIELD& b )
483{
484 return a.GetPosition() != b.GetPosition()
485 || a.GetHorizJustify() != b.GetHorizJustify()
486 || a.GetVertJustify() != b.GetVertJustify()
487 || a.GetTextAngle() != b.GetTextAngle();
488}
489
490
491static bool positioningChanged( FIELDS_GRID_TABLE* a, std::vector<SCH_FIELD>& b )
492{
493 for( size_t i = 0; i < a->size() && i < b.size(); ++i )
494 {
495 if( positioningChanged( a->at( i ), b.at( i ) ) )
496 return true;
497 }
498
499 return false;
500}
501
502
504{
506 return false;
507
508 if( !wxDialog::TransferDataFromWindow() )
509 return false;
510
511 // Don't allow text to disappear; it can be difficult to correct if you can't select it
512 if( !m_textSize.Validate( 0.01, 1000.0, EDA_UNITS::MM ) )
513 return false;
514
515 SCH_COMMIT commit( m_Parent );
516 wxString text;
517
518 /* save old text in undo list if not already in edit */
519 if( m_currentLabel->GetEditFlags() == 0 )
521
523
525 {
526 // labels need escaping
528
529 // convert any text variable cross-references to their UUIDs
531
532#ifdef __WXMAC__
533 // On macOS CTRL+Enter produces '\r' instead of '\n' regardless of EOL setting
534 text.Replace( wxS( "\r" ), wxS( "\n" ) );
535#endif
536
537 if( text.IsEmpty() && !m_currentLabel->IsNew() )
538 {
539 DisplayError( this, _( "Label can not be empty." ) );
540 return false;
541 }
542
544 }
545
546 // change all field positions from relative to absolute
547 for( SCH_FIELD& field : *m_fields )
548 {
549 field.Offset( m_currentLabel->GetPosition() );
550
551 if( field.GetCanonicalName() == wxT( "Netclass" ) )
552 {
553 field.SetLayer( LAYER_NETCLASS_REFS );
554 }
555 else if( field.GetId() == FIELD_T::INTERSHEET_REFS )
556 {
557 if( field.IsVisible() != m_Parent->Schematic().Settings().m_IntersheetRefsShow )
558 {
559 DisplayInfoMessage( this, _( "Intersheet reference visibility is controlled globally from "
560 "Schematic Setup > General > Formatting" ) );
561 }
562
563 field.SetLayer( LAYER_INTERSHEET_REFS );
564 }
565 else
566 {
567 field.SetLayer( LAYER_FIELDS );
568 }
569 }
570
573
574 for( int ii = m_fields->GetNumberRows() - 1; ii >= 0; ii-- )
575 {
576 SCH_FIELD& field = m_fields->at( ii );
577 const wxString& fieldName = field.GetCanonicalName();
578 const wxString& fieldText = field.GetText();
579
580 if( fieldName.IsEmpty() && fieldText.IsEmpty() )
581 {
582 // delete empty, unnamed fields
583 m_fields->erase( m_fields->begin() + ii );
584 }
585 else if( fieldName == wxT( "Netclass" ) && fieldText.IsEmpty() )
586 {
587 // delete empty Netclass fields if there are other Netclass fields present
588 int netclassFieldCount = 0;
589
590 for( int jj = 0; jj < m_fields->GetNumberRows(); ++jj )
591 {
592 if( m_fields->at( jj ).GetCanonicalName() == wxT( "Netclass" ) )
593 netclassFieldCount++;
594 }
595
596 if( netclassFieldCount > 1 )
597 m_fields->erase( m_fields->begin() + ii );
598 }
599 else if( fieldName.IsEmpty() )
600 {
601 // give non-empty, unnamed fields a name
602 field.SetName( _( "untitled" ) );
603 }
604 }
605
606 int ordinal = 42; // Arbitrarily larger than any mandatory FIELD_T ids.
607
608 for( SCH_FIELD& field : *m_fields )
609 {
610 if( !field.IsMandatory() )
611 field.SetOrdinal( ordinal++ );
612 }
613
615
616 if( m_shapeSizer->AreAnyItemsShown() )
617 {
618 if( m_bidirectional->GetValue() ) m_currentLabel->SetShape( LABEL_FLAG_SHAPE::L_BIDI );
619 else if( m_input->GetValue() ) m_currentLabel->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
620 else if( m_output->GetValue() ) m_currentLabel->SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
621 else if( m_triState->GetValue() ) m_currentLabel->SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
622 else if( m_passive->GetValue() ) m_currentLabel->SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
623 else if( m_dot->GetValue() ) m_currentLabel->SetShape( LABEL_FLAG_SHAPE::F_DOT );
624 else if( m_circle->GetValue() ) m_currentLabel->SetShape( LABEL_FLAG_SHAPE::F_ROUND );
625 else if( m_diamond->GetValue() ) m_currentLabel->SetShape( LABEL_FLAG_SHAPE::F_DIAMOND );
626 else if( m_rectangle->GetValue() ) m_currentLabel->SetShape( LABEL_FLAG_SHAPE::F_RECTANGLE );
627 }
628
631
633 static_cast<SCH_DIRECTIVE_LABEL*>( m_currentLabel )->SetPinLength( m_textSize.GetIntValue() );
636
637 // Must come after SetTextSize()
640
642
643 SPIN_STYLE selectedSpinStyle= SPIN_STYLE::LEFT;
644
645 if( m_spin0->IsChecked() ) selectedSpinStyle = SPIN_STYLE::RIGHT;
646 else if( m_spin1->IsChecked() ) selectedSpinStyle = SPIN_STYLE::LEFT;
647 else if( m_spin2->IsChecked() ) selectedSpinStyle = SPIN_STYLE::UP;
648 else if( m_spin3->IsChecked() ) selectedSpinStyle = SPIN_STYLE::BOTTOM;
649
651 {
652 SCH_EDIT_FRAME* frame = static_cast<SCH_EDIT_FRAME*>( m_parentFrame );
654 frame->AutoRotateItem( frame->GetScreen(), m_currentLabel );
655 }
656 else
657 {
659 }
660
661 if( !m_currentLabel->AutoRotateOnPlacement() && m_currentLabel->GetSpinStyle() != selectedSpinStyle )
662 m_currentLabel->SetSpinStyle( selectedSpinStyle );
663
665
666 if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
667 m_currentLabel->AutoplaceFields( m_Parent->GetScreen(), fieldsAutoplaced );
668
669 if( !commit.Empty() )
670 {
671 commit.Push( _( "Edit Label Properties" ) );
672 }
673 else if( m_activeTextEntry && m_labelList )
674 {
675 text = m_activeTextEntry->GetValue();
676 // On macOS CTRL+Enter produces '\r' instead of '\n' regardless of EOL setting
677 text.Replace( wxS( "\r" ), wxS( "\n" ) );
678 wxArrayString lines = wxSplit( text, '\n' );
679
680 for( const wxString& line : lines )
681 {
682 text = EscapeString( line, CTX_NETNAME );
683 text.Trim( false ).Trim( true );
684
685 if( text.empty() )
686 continue;
687
688 // convert any text variable cross-references to their UUIDs
690
691 switch ( m_currentLabel->Type() )
692 {
694 {
695 SCH_GLOBALLABEL* label = new SCH_GLOBALLABEL( *static_cast<SCH_GLOBALLABEL*>( m_currentLabel ) );
696 label->SetText( text );
697 m_labelList->push_back( std::unique_ptr<SCH_LABEL_BASE>( label ) );
698 break;
699 }
700 case SCH_HIER_LABEL_T:
701 {
702 SCH_HIERLABEL* label = new SCH_HIERLABEL( *static_cast<SCH_HIERLABEL*>( m_currentLabel ) );
703 label->SetText( text );
704 m_labelList->push_back( std::unique_ptr<SCH_LABEL_BASE>( label ) );
705 break;
706 }
707 case SCH_LABEL_T:
708 {
709 SCH_LABEL* label = new SCH_LABEL( *static_cast<SCH_LABEL*>( m_currentLabel ) );
710 label->SetText( text );
711 m_labelList->push_back( std::unique_ptr<SCH_LABEL_BASE>( label ) );
712 break;
713 }
714 default:
715 break;
716 }
717 }
718 }
720 {
722 m_labelList->push_back( std::unique_ptr<SCH_LABEL_BASE>( label ) );
723 }
724
725 return true;
726}
727
728
729void DIALOG_LABEL_PROPERTIES::onSpinButton( wxCommandEvent& aEvent )
730{
731 for( BITMAP_BUTTON* btn : { m_spin0, m_spin1, m_spin2, m_spin3 } )
732 {
733 if( btn->IsChecked() && btn != aEvent.GetEventObject() )
734 btn->Check( false );
735 }
736}
737
738
739void DIALOG_LABEL_PROPERTIES::OnFormattingHelp( wxHyperlinkEvent& aEvent )
740{
742}
743
744
745void DIALOG_LABEL_PROPERTIES::OnAddField( wxCommandEvent& event )
746{
748 [&]() -> std::pair<int, int>
749 {
750 wxString fieldName = wxT( "Netclass" );
751
752 for( SCH_FIELD& field : *m_fields )
753 {
754 if( field.GetId() != FIELD_T::INTERSHEET_REFS && field.GetName() != wxT( "Netclass" ) )
755 {
756 fieldName = wxEmptyString;
757 break;
758 }
759 }
760
761 fieldName = SCH_LABEL_BASE::GetDefaultFieldName( fieldName, true );
762
763 SCH_FIELD newField( m_currentLabel, FIELD_T::USER, fieldName );
764
765 if( m_fields->size() > 0 )
766 {
767 // SetAttributes() also covers text angle, size, italic and bold
768 newField.SetAttributes( m_fields->at( m_fields->size() - 1 ) );
769 newField.SetVisible( m_fields->at( m_fields->size() - 1 ).IsVisible() );
770 }
771 else
772 {
773 newField.SetVisible( true );
774 newField.SetItalic( true );
775 }
776
777 m_fields->push_back( newField );
778
779 // notify the grid
780 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
781 m_grid->ProcessTableMessage( msg );
782 return { m_fields->size() - 1, FDC_NAME };
783 } );
784}
785
786
787void DIALOG_LABEL_PROPERTIES::OnDeleteField( wxCommandEvent& event )
788{
790 [&]( int row )
791 {
792 if( row < m_currentLabel->GetMandatoryFieldCount() )
793 {
794 DisplayError( this, _( "The first field is mandatory." ) );
795 return false;
796 }
797
798 return true;
799 },
800 [&]( int row )
801 {
802 m_fields->erase( m_fields->begin() + row );
803
804 // notify the grid
805 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 );
806 m_grid->ProcessTableMessage( msg );
807 } );
808}
809
810
811void DIALOG_LABEL_PROPERTIES::OnMoveUp( wxCommandEvent& event )
812{
814 [&]( int row )
815 {
817 },
818 [&]( int row )
819 {
820 std::swap( *( m_fields->begin() + row ), *( m_fields->begin() + row - 1 ) );
821 m_grid->ForceRefresh();
822 } );
823}
824
825
826void DIALOG_LABEL_PROPERTIES::OnMoveDown( wxCommandEvent& event )
827{
829 [&]( int row )
830 {
831 return row >= m_currentLabel->GetMandatoryFieldCount();
832 },
833 [&]( int row )
834 {
835 std::swap( *( m_fields->begin() + row ), *( m_fields->begin() + row + 1 ) );
836 m_grid->ForceRefresh();
837 } );
838}
839
840
842{
843 m_width = aWidth;
844 // Account for scroll bars
845 aWidth -= ( m_grid->GetSize().x - m_grid->GetClientSize().x );
846
847 m_grid->AutoSizeColumn( 0 );
848 m_grid->SetColSize( 0, std::max( 72, m_grid->GetColSize( 0 ) ) );
849
850 int fixedColsWidth = m_grid->GetColSize( 0 );
851
852 for( int i = 2; i < m_grid->GetNumberCols(); i++ )
853 fixedColsWidth += m_grid->GetColSize( i );
854
855 m_grid->SetColSize( 1, std::max( 120, aWidth - fixedColsWidth ) );
856}
857
858
859void DIALOG_LABEL_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
860{
861 std::bitset<64> shownColumns = m_grid->GetShownColumns();
862
863 if( shownColumns != m_shownColumns )
864 {
865 m_shownColumns = shownColumns;
866
867 if( !m_grid->IsCellEditControlShown() )
868 AdjustGridColumns( m_grid->GetRect().GetWidth() );
869 }
870
871 // Handle a delayed focus
872 if( m_delayedFocusRow >= 0 && m_delayedFocusRow < m_grid->GetNumberRows() )
873 {
874 m_grid->SetFocus();
875 m_grid->MakeCellVisible( m_delayedFocusRow, m_delayedFocusColumn );
877 }
878
881}
882
883
884void DIALOG_LABEL_PROPERTIES::OnSizeGrid( wxSizeEvent& event )
885{
886 int new_size = event.GetSize().GetX();
887
888 if( m_width != new_size )
889 AdjustGridColumns( new_size );
890
891 // Always propagate for a grid repaint (needed if the height changes, as well as width)
892 event.Skip();
893}
894
895
897{
899 {
900 m_labelCombo->Show( !m_cbMultiLine->IsChecked() );
901 m_valueCombo->Show( !m_cbMultiLine->IsChecked() );
902 m_labelMultiLine->Show( m_cbMultiLine->IsChecked() );
903 m_valueMultiLine->Show( m_cbMultiLine->IsChecked() );
904
905 if( m_cbMultiLine->IsChecked() )
906 {
907 m_valueMultiLine->SetValue( m_valueCombo->GetValue() );
910 }
911 else
912 {
913 wxString multiText = m_valueMultiLine->GetValue();
914 m_valueCombo->SetValue( multiText.BeforeFirst( '\n' ) );
917 }
918 }
919 else if( m_currentLabel->Type() == SCH_HIER_LABEL_T )
920 {
921 m_labelSingleLine->Show( !m_cbMultiLine->IsChecked() );
922 m_valueSingleLine->Show( !m_cbMultiLine->IsChecked() );
923 m_labelMultiLine->Show( m_cbMultiLine->IsChecked() );
924 m_valueMultiLine->Show( m_cbMultiLine->IsChecked() );
925
926 if( m_cbMultiLine->IsChecked() )
927 {
928 m_valueMultiLine->SetValue( m_valueSingleLine->GetValue() );
931 }
932 else
933 {
934 wxString multiText = m_valueMultiLine->GetValue();
935 m_valueSingleLine->SetValue( multiText.BeforeFirst( '\n' ) );
938 }
939 }
940
941 Layout();
942}
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition: bitmap.cpp:110
A bitmap button widget that behaves like an AUI toolbar item's button when it is drawn.
Definition: bitmap_button.h:42
void SetIsRadioButton()
bool IsChecked() const
void Check(bool aCheck=true)
Check the control.
void SetIsSeparator()
Render button as a toolbar separator.
void SetIsCheckButton()
Setup the control as a two-state button (checked or unchecked).
void SetBitmap(const wxBitmapBundle &aBmp)
Set the bitmap shown when the button is enabled.
Color settings are a bit different than most of the settings objects in that there can be more than o...
COLOR4D GetColor(int aLayer) const
void SetSwatchColor(const KIGFX::COLOR4D &aColor, bool aSendEvent)
Set the current swatch color directly.
KIGFX::COLOR4D GetSwatchColor() const
void SetDefaultColor(const KIGFX::COLOR4D &aColor)
Sets the color that will be chosen with the "Reset to Default" button in the chooser.
void SetSwatchBackground(const KIGFX::COLOR4D &aBackground)
Set the swatch background color.
bool Empty() const
Definition: commit.h:152
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition: commit.h:107
Class DIALOG_LABEL_PROPERTIES_BASE.
std::list< std::unique_ptr< SCH_LABEL_BASE > > * m_labelList
void OnSizeGrid(wxSizeEvent &event) override
void OnMoveUp(wxCommandEvent &event) override
void OnMoveDown(wxCommandEvent &event) override
DIALOG_LABEL_PROPERTIES(SCH_EDIT_FRAME *parent, SCH_LABEL_BASE *aLabel, bool aNew)
void OnEnterKey(wxCommandEvent &aEvent) override
wxEVT_COMMAND_ENTER event handler for single-line control.
void OnAddField(wxCommandEvent &event) override
SCH_NETNAME_VALIDATOR m_netNameValidator
void OnFormattingHelp(wxHyperlinkEvent &aEvent) override
void OnCBValueCharHook(wxKeyEvent &aEvent) override
void OnUpdateUI(wxUpdateUIEvent &event) override
void onSpinButton(wxCommandEvent &aEvent)
void onMultiLabelCheck(wxCommandEvent &aEvent) override
void OnDeleteField(wxCommandEvent &event) override
void OnValueCharHook(wxKeyEvent &aEvent) override
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:75
void SetupStandardButtons(std::map< int, wxString > aLabels={})
std::string m_hash_key
Definition: dialog_shim.h:236
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
EDA_BASE_FRAME * m_parentFrame
Definition: dialog_shim.h:254
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:148
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:110
bool IsNew() const
Definition: eda_item.h:124
void SetTextColor(const COLOR4D &aColor)
Definition: eda_text.h:266
COLOR4D GetTextColor() const
Definition: eda_text.h:267
bool IsItalic() const
Definition: eda_text.h:166
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:144
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition: eda_text.cpp:533
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:97
KIFONT::FONT * GetFont() const
Definition: eda_text.h:244
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
Definition: eda_text.cpp:433
int GetTextWidth() const
Definition: eda_text.h:261
void Offset(const VECTOR2I &aOffset)
Definition: eda_text.cpp:596
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition: eda_text.h:197
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:386
void SetBold(bool aBold)
Set the text to be bold - this will also update the font if needed.
Definition: eda_text.cpp:335
bool IsBold() const
Definition: eda_text.h:181
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition: eda_text.h:200
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:270
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
Definition: eda_text.cpp:307
void SetFont(KIFONT::FONT *aFont)
Definition: eda_text.cpp:499
int GetNumberRows() override
void push_back(const SCH_FIELD &field)
virtual void SetSelectedString(const wxString &aString)
virtual void SetStringList(const wxArrayString &aStringList)
void SetFontSelection(KIFONT::FONT *aFont, bool aSilentMode=false)
Set the selection in wxChoice widget.
Definition: font_choice.cpp:73
KIFONT::FONT * GetFontSelection(bool aBold, bool aItalic, bool aForDrawingSheet=false) const
bool HaveFontSelection() const
Definition: font_choice.cpp:95
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_base.h:95
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:356
wxString ConvertKIIDsToRefs(const wxString &aSource) const
Definition: schematic.cpp:625
wxString ConvertRefsToKIIDs(const wxString &aSource) const
Definition: schematic.cpp:555
SCH_SHEET & Root() const
Definition: schematic.h:140
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
COLOR_SETTINGS * GetColorSettings(bool aForceRefresh=false) const override
Returns a pointer to the active color theme settings.
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
Definition: sch_commit.cpp:489
Schematic editor (Eeschema) main window.
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
SCHEMATIC & Schematic() const
void AutoRotateItem(SCH_SCREEN *aScreen, SCH_ITEM *aItem)
Automatically set the rotation of an item (if the item supports it).
VECTOR2I GetPosition() const override
Definition: sch_field.cpp:1337
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
Definition: sch_field.cpp:1117
void SetName(const wxString &aName)
Definition: sch_field.cpp:1079
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:168
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:246
void SetFieldsAutoplaced(AUTOPLACE_ALGO aAlgo)
Definition: sch_item.h:598
AUTOPLACE_ALGO GetFieldsAutoplaced() const
Return whether the fields have been automatically placed.
Definition: sch_item.h:597
void SetFields(const std::vector< SCH_FIELD > &aFields)
Set multiple schematic fields.
Definition: sch_label.h:213
bool AutoRotateOnPlacement() const
autoRotateOnPlacement
Definition: sch_label.cpp:1472
SPIN_STYLE GetSpinStyle() const
Definition: sch_label.cpp:351
void SetShape(LABEL_FLAG_SHAPE aShape)
Definition: sch_label.h:177
LABEL_FLAG_SHAPE GetShape() const
Definition: sch_label.h:176
virtual bool AutoRotateOnPlacementSupported() const =0
void SetAutoRotateOnPlacement(bool autoRotate=true)
Definition: sch_label.cpp:1478
static const wxString GetDefaultFieldName(const wxString &aName, bool aUseDefaultName)
Definition: sch_label.cpp:216
void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo) override
Definition: sch_label.cpp:580
virtual int GetMandatoryFieldCount()
Definition: sch_label.h:203
std::vector< SCH_FIELD > & GetFields()
Definition: sch_label.h:205
virtual wxString GetClass() const override=0
Return the class name.
virtual void SetSpinStyle(SPIN_STYLE aSpinStyle)
Definition: sch_label.cpp:316
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:758
SCH_SCREEN * GetNext()
SCH_SCREEN * GetFirst()
Schematic symbol object.
Definition: sch_symbol.h:75
bool IsSymbolLikePowerGlobalLabel() const
bool IsSymbolLikePowerLocalLabel() const
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:760
static HTML_MESSAGE_BOX * ShowSyntaxHelp(wxWindow *aParentWindow)
Definition: sch_label.cpp:2256
VECTOR2I GetPosition() const override
Definition: sch_text.h:141
void SetBitmap(const wxBitmapBundle &aBmp)
int GetIntValue()
Definition: unit_binder.h:134
virtual bool Validate(double aMin, double aMax, EDA_UNITS aUnits=EDA_UNITS::UNSCALED)
Validate the control against the given range, informing the user of any errors found.
virtual void SetValue(long long int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
void ShowHideColumns(const wxString &shownColumns)
Show/hide the grid columns based on a tokenized string of shown column indexes.
Definition: wx_grid.cpp:494
void OnMoveRowUp(const std::function< void(int row)> &aMover)
Definition: wx_grid.cpp:766
void SetTable(wxGridTableBase *table, bool aTakeOwnership=false)
Hide wxGrid's SetTable() method with one which doesn't mess up the grid column widths when setting th...
Definition: wx_grid.cpp:273
void DestroyTable(wxGridTableBase *aTable)
Work-around for a bug in wxGrid which crashes when deleting the table if the cell edit control was no...
Definition: wx_grid.cpp:450
void OnDeleteRows(const std::function< void(int row)> &aDeleter)
Handles a row deletion event.
Definition: wx_grid.cpp:704
wxString GetShownColumnsAsString()
Get a tokenized string containing the shown column indexes.
Definition: wx_grid.cpp:464
void OnAddRow(const std::function< std::pair< int, int >()> &aAdder)
Definition: wx_grid.cpp:684
std::bitset< 64 > GetShownColumns()
Definition: wx_grid.cpp:483
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:632
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:222
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:169
This file is part of the common library.
static bool positioningChanged(const SCH_FIELD &a, const SCH_FIELD &b)
#define _(s)
@ FDC_NAME
@ FDC_VALUE
@ LAYER_FIELDS
Definition: layer_ids.h:452
@ LAYER_NETCLASS_REFS
Definition: layer_ids.h:454
@ LAYER_SCHEMATIC_BACKGROUND
Definition: layer_ids.h:478
@ LAYER_INTERSHEET_REFS
Definition: layer_ids.h:453
#define UNIMPLEMENTED_FOR(type)
Definition: macros.h:96
AUTOPLACE_ALGO
Definition: sch_item.h:69
@ AUTOPLACE_MANUAL
Definition: sch_item.h:72
@ AUTOPLACE_NONE
Definition: sch_item.h:70
@ AUTOPLACE_AUTO
Definition: sch_item.h:71
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:...
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: string_utils.h:429
@ CTX_NETNAME
Definition: string_utils.h:53
@ SCH_DIRECTIVE_LABEL_T
Definition: typeinfo.h:172
@ SCH_LABEL_T
Definition: typeinfo.h:168
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:170
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:175
@ SCH_SYMBOL_LOCATE_POWER_T
Definition: typeinfo.h:197
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:169