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>
31#include <sch_edit_frame.h>
32#include <tool/tool_manager.h>
33#include <gr_text.h>
34#include <confirm.h>
35#include <schematic.h>
38#include <string_utils.h>
39#include <kiface_base.h>
40#include <sch_label.h>
41#include <sch_commit.h>
42
43
45 SCH_LABEL_BASE* aLabel ) :
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{
55 COLOR_SETTINGS* colorSettings = m_Parent->GetColorSettings();
56 COLOR4D schematicBackground = colorSettings->GetColor( LAYER_SCHEMATIC_BACKGROUND );
57
58 m_fields = new FIELDS_GRID_TABLE( this, aParent, m_grid, m_currentLabel );
59 m_width = 100; // Will be later set to a better value
62
64 {
67
68 m_labelSingleLine->Show( false );
69 m_valueSingleLine->Show( false );
70
71 m_valueCombo->SetValidator( m_netNameValidator );
72 }
73 else if( m_currentLabel->Type() == SCH_HIER_LABEL_T )
74 {
77
78 m_labelCombo->Show( false );
79 m_valueCombo->Show( false );
80
82 }
84 {
87
88 m_labelSingleLine->Show( false );
89 m_valueSingleLine->Show( false );
90 m_labelCombo->Show( false );
91 m_valueCombo->Show( false );
92 m_syntaxHelp->Show( false );
93 m_textEntrySizer->Show( false );
94
95 m_textSizeLabel->SetLabel( _( "Pin length:" ) );
96 }
97
98 switch( m_currentLabel->Type() )
99 {
100 case SCH_GLOBAL_LABEL_T: SetTitle( _( "Global Label Properties" ) ); break;
101 case SCH_HIER_LABEL_T: SetTitle( _( "Hierarchical Label Properties" ) ); break;
102 case SCH_LABEL_T: SetTitle( _( "Label Properties" ) ); break;
103 case SCH_DIRECTIVE_LABEL_T: SetTitle( _( "Directive Label Properties" ) ); break;
104 case SCH_SHEET_PIN_T: SetTitle( _( "Hierarchical Sheet Pin Properties" ) ); break;
105 default: UNIMPLEMENTED_FOR( m_currentLabel->GetClass() ); break;
106 }
107
108 // Give a bit more room for combobox editors
109 m_grid->SetDefaultRowSize( m_grid->GetDefaultRowSize() + 4 );
110
112 m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this, nullptr,
113 [&]( wxCommandEvent& aEvent )
114 {
115 OnAddField( aEvent );
116 } ) );
117 m_grid->SetSelectionMode( wxGrid::wxGridSelectRows );
118
119 // Show/hide columns according to user's preference
120 if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
121 {
122 m_grid->ShowHideColumns( cfg->m_Appearance.edit_label_visible_columns );
124 }
125
126 // Configure button logos
127 m_bpAdd->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
128 m_bpDelete->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
129 m_bpMoveUp->SetBitmap( KiBitmapBundle( BITMAPS::small_up ) );
130 m_bpMoveDown->SetBitmap( KiBitmapBundle( BITMAPS::small_down ) );
131
133
135 m_bold->SetBitmap( KiBitmapBundle( BITMAPS::text_bold ) );
137 m_italic->SetBitmap( KiBitmapBundle( BITMAPS::text_italic ) );
138
140
145
147
148 m_textColorSwatch->SetDefaultColor( COLOR4D::UNSPECIFIED );
149 m_textColorSwatch->SetSwatchBackground( schematicBackground );
150
151 // Show/hide relevant controls
153 {
154 m_dot->Hide();
155 m_circle->Hide();
156 m_diamond->Hide();
157 m_rectangle->Hide();
158
159 m_spin0->SetBitmap( KiBitmapBundle( BITMAPS::label_align_left ) );
160 m_spin1->SetBitmap( KiBitmapBundle( BITMAPS::label_align_right ) );
161 m_spin2->SetBitmap( KiBitmapBundle( BITMAPS::label_align_bottom ) );
162 m_spin3->SetBitmap( KiBitmapBundle( BITMAPS::label_align_top ) );
163 }
165 {
166 m_input->Hide();
167 m_output->Hide();
168 m_bidirectional->Hide();
169 m_triState->Hide();
170 m_passive->Hide();
171
172 m_fontLabel->SetLabel( _( "Orientation:" ) );
173 m_fontCtrl->Hide();
174 m_separator1->Hide();
175 m_bold->Hide();
176 m_italic->Hide();
177 m_separator2->Hide();
178 m_spin0->SetBitmap( KiBitmapBundle( BITMAPS::pinorient_down ) );
179 m_spin1->SetBitmap( KiBitmapBundle( BITMAPS::pinorient_up ) );
180 m_spin2->SetBitmap( KiBitmapBundle( BITMAPS::pinorient_right ) );
181 m_spin3->SetBitmap( KiBitmapBundle( BITMAPS::pinorient_left ) );
182 m_separator3->Hide();
183
184 m_formattingGB->Detach( m_fontCtrl );
185 m_formattingGB->Detach( m_iconBar );
186 m_formattingGB->Add( m_iconBar, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ),
187 wxEXPAND | wxRIGHT, 5 );
188 }
189 else
190 {
191 m_shapeSizer->Show( false );
192
193 m_spin0->SetBitmap( KiBitmapBundle( BITMAPS::text_align_left ) );
194 m_spin1->SetBitmap( KiBitmapBundle( BITMAPS::text_align_right ) );
195 m_spin2->SetBitmap( KiBitmapBundle( BITMAPS::text_align_bottom ) );
196 m_spin3->SetBitmap( KiBitmapBundle( BITMAPS::text_align_top ) );
197 }
198
200 {
201 m_autoRotate->Hide();
202 wxSizer* parentSizer = m_autoRotate->GetContainingSizer();
203 parentSizer->Detach( m_autoRotate );
204 parentSizer->Layout();
205 }
206
208
209 // DIALOG_SHIM needs a unique hash_key because classname is not sufficient because the
210 // various versions have different controls so we want to store sizes for each version.
211 m_hash_key = TO_UTF8( GetTitle() );
212
213 m_spin0->Bind( wxEVT_BUTTON, &DIALOG_LABEL_PROPERTIES::onSpinButton, this );
214 m_spin1->Bind( wxEVT_BUTTON, &DIALOG_LABEL_PROPERTIES::onSpinButton, this );
215 m_spin2->Bind( wxEVT_BUTTON, &DIALOG_LABEL_PROPERTIES::onSpinButton, this );
216 m_spin3->Bind( wxEVT_BUTTON, &DIALOG_LABEL_PROPERTIES::onSpinButton, this );
217
218 // Now all widgets have the size fixed, call FinishDialogSettings
220
221 if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
222 {
223 if( cfg->m_Appearance.edit_label_width > 0 && cfg->m_Appearance.edit_label_height > 0 )
224 SetSize( cfg->m_Appearance.edit_label_width, cfg->m_Appearance.edit_label_height );
225 }
226}
227
228
230{
231 if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
232 {
233 cfg->m_Appearance.edit_label_visible_columns = m_grid->GetShownColumnsAsString();
234 cfg->m_Appearance.edit_label_width = GetSize().x;
235 cfg->m_Appearance.edit_label_height = GetSize().y;
236 }
237
238 // Prevents crash bug in wxGrid's d'tor
240
241 // Delete the GRID_TRICKS.
242 m_grid->PopEventHandler( true );
243
244 if( m_helpWindow )
245 m_helpWindow->Destroy();
246}
247
248
250{
251 if( !wxDialog::TransferDataToWindow() )
252 return false;
253
255 {
256 // show control characters in a human-readable format
257 wxString text = UnescapeString( m_currentLabel->GetText() );
258
259 // show text variable cross-references in a human-readable format
261
262 m_activeTextEntry->SetValue( text );
263 }
264
266 {
267 // Load the combobox with the existing labels of the same type
268 std::set<wxString> existingLabels;
269 std::vector<std::shared_ptr<BUS_ALIAS>> busAliases;
270 SCH_SCREENS allScreens( m_Parent->Schematic().Root() );
271
272 for( SCH_SCREEN* screen = allScreens.GetFirst(); screen; screen = allScreens.GetNext() )
273 {
274 for( SCH_ITEM* item : screen->Items().OfType( m_currentLabel->Type() ) )
275 {
276 const SCH_LABEL_BASE* label = static_cast<const SCH_LABEL_BASE*>( item );
277 existingLabels.insert( UnescapeString( label->GetText() ) );
278 }
279
280 // Add global power labels from power symbols
282 {
283 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_LOCATE_POWER_T ) )
284 {
285 const SCH_SYMBOL* power = static_cast<const SCH_SYMBOL*>( item );
286
287 // Ensure the symbol has the Power (i.e. equivalent to a global label
288 // before adding its value in list
289 if( power->IsSymbolLikePowerGlobalLabel() )
290 existingLabels.insert(
291 UnescapeString( power->GetField( VALUE_FIELD )->GetText() ) );
292 }
293 }
294
295 auto& sheetAliases = screen->GetBusAliases();
296 busAliases.insert( busAliases.end(), sheetAliases.begin(), sheetAliases.end() );
297 }
298
299 // Add bus aliases to label list
300 for( const std::shared_ptr<BUS_ALIAS>& busAlias : busAliases )
301 existingLabels.insert( wxT( "{" ) + busAlias->GetName() + wxT( "}" ) );
302
303 wxArrayString existingLabelArray;
304
305 for( const wxString& label : existingLabels )
306 existingLabelArray.push_back( label );
307
308 m_valueCombo->Append( existingLabelArray );
309 }
310
311 // Push a copy of each field into m_updateFields
312 for( SCH_FIELD& field : m_currentLabel->GetFields() )
313 {
314 SCH_FIELD field_copy( field );
315
316 // change offset to be symbol-relative
317 field_copy.Offset( -m_currentLabel->GetPosition() );
318
319 m_fields->push_back( field_copy );
320 }
321
322 // notify the grid
323 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, (int) m_fields->size() );
324 m_grid->ProcessTableMessage( msg );
325 AdjustGridColumns( m_grid->GetRect().GetWidth() );
326
327 if( m_shapeSizer->AreAnyItemsShown() )
328 {
329 switch( m_currentLabel->GetShape() )
330 {
331 case LABEL_FLAG_SHAPE::L_INPUT: m_input->SetValue( true ); break;
332 case LABEL_FLAG_SHAPE::L_OUTPUT: m_output->SetValue( true ); break;
333 case LABEL_FLAG_SHAPE::L_BIDI: m_bidirectional->SetValue( true ); break;
334 case LABEL_FLAG_SHAPE::L_TRISTATE: m_triState->SetValue( true ); break;
335 case LABEL_FLAG_SHAPE::L_UNSPECIFIED: m_passive->SetValue( true ); break;
336 case LABEL_FLAG_SHAPE::F_DOT: m_dot->SetValue( true ); break;
337 case LABEL_FLAG_SHAPE::F_ROUND: m_circle->SetValue( true ); break;
338 case LABEL_FLAG_SHAPE::F_DIAMOND: m_diamond->SetValue( true ); break;
339 case LABEL_FLAG_SHAPE::F_RECTANGLE: m_rectangle->SetValue( true ); break;
340 }
341 }
342
344
346 m_textSize.SetValue( static_cast<SCH_DIRECTIVE_LABEL*>( m_currentLabel )->GetPinLength() );
347 else
349
353
354 switch( m_currentLabel->GetSpinStyle() )
355 {
356 case SPIN_STYLE::RIGHT: m_spin0->Check( true ); break;
357 case SPIN_STYLE::LEFT: m_spin1->Check( true ); break;
358 case SPIN_STYLE::UP: m_spin2->Check( true ); break;
359 case SPIN_STYLE::BOTTOM: m_spin3->Check( true ); break;
360 }
361
364
365 return true;
366}
367
368
369void DIALOG_LABEL_PROPERTIES::OnEnterKey( wxCommandEvent& aEvent )
370{
371 wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
372}
373
374
376{
377 if( aEvent.GetKeyCode() == WXK_TAB )
378 {
379 if( aEvent.ShiftDown() )
380 {
381 m_textSizeCtrl->SetFocusFromKbd();
382 }
383 else if( !m_fields->empty() )
384 {
385 m_grid->SetFocusFromKbd();
386 m_grid->MakeCellVisible( 0, 0 );
387 m_grid->SetGridCursor( 0, 0 );
388 }
389 else
390 {
391 m_textSizeCtrl->SetFocusFromKbd();
392 }
393 }
394 else
395 {
396 aEvent.Skip();
397 }
398}
399
400
401static bool positioningChanged( const SCH_FIELD& a, const SCH_FIELD& b )
402{
403 return a.GetPosition() != b.GetPosition()
404 || a.GetHorizJustify() != b.GetHorizJustify()
405 || a.GetVertJustify() != b.GetVertJustify()
406 || a.GetTextAngle() != b.GetTextAngle();
407}
408
409
410static bool positioningChanged( FIELDS_GRID_TABLE* a, std::vector<SCH_FIELD>& b )
411{
412 for( size_t i = 0; i < a->size() && i < b.size(); ++i )
413 {
414 if( positioningChanged( a->at( i ), b.at( i ) ) )
415 return true;
416 }
417
418 return false;
419}
420
421
423{
425 return false;
426
427 if( !wxDialog::TransferDataFromWindow() )
428 return false;
429
430 // Don't allow text to disappear; it can be difficult to correct if you can't select it
431 if( !m_textSize.Validate( 0.01, 1000.0, EDA_UNITS::MILLIMETRES ) )
432 return false;
433
434 SCH_COMMIT commit( m_Parent );
435 wxString text;
436
437 /* save old text in undo list if not already in edit */
438 if( m_currentLabel->GetEditFlags() == 0 )
440
442
444 {
445 // labels need escaping
447
448 // convert any text variable cross-references to their UUIDs
450
451#ifdef __WXMAC__
452 // On macOS CTRL+Enter produces '\r' instead of '\n' regardless of EOL setting
453 text.Replace( wxS( "\r" ), wxS( "\n" ) );
454#endif
455
456 if( text.IsEmpty() && !m_currentLabel->IsNew() )
457 {
458 DisplayError( this, _( "Label can not be empty." ) );
459 return false;
460 }
461
463 }
464
465 // change all field positions from relative to absolute
466 for( SCH_FIELD& field : *m_fields )
467 {
468 field.Offset( m_currentLabel->GetPosition() );
469
470 if( field.GetCanonicalName() == wxT( "Netclass" ) )
471 {
472 field.SetLayer( LAYER_NETCLASS_REFS );
473 }
474 else if( field.GetCanonicalName() == wxT( "Intersheetrefs" ) )
475 {
476 if( field.IsVisible() != m_Parent->Schematic().Settings().m_IntersheetRefsShow )
477 {
478 DisplayInfoMessage( this, _( "Intersheet reference visibility is "
479 "controlled globally from "
480 "Schematic Setup > General > Formatting" ) );
481 }
482
483 field.SetLayer( LAYER_INTERSHEET_REFS );
484 }
485 else
486 {
487 field.SetLayer( LAYER_FIELDS );
488 }
489 }
490
493
494 for( int ii = m_fields->GetNumberRows() - 1; ii >= 0; ii-- )
495 {
496 SCH_FIELD& field = m_fields->at( ii );
497 const wxString& fieldName = field.GetCanonicalName();
498 const wxString& fieldText = field.GetText();
499
500 if( fieldName.IsEmpty() && fieldText.IsEmpty() )
501 {
502 // delete empty, unnamed fields
503 m_fields->erase( m_fields->begin() + ii );
504 }
505 else if( fieldName == wxT( "Netclass" ) && fieldText.IsEmpty() )
506 {
507 // delete empty Netclass fields if there are other Netclass fields present
508 int netclassFieldCount = 0;
509
510 for( int jj = 0; jj < m_fields->GetNumberRows(); ++jj )
511 {
512 if( m_fields->at( jj ).GetCanonicalName() == wxT( "Netclass" ) )
513 netclassFieldCount++;
514 }
515
516 if( netclassFieldCount > 1 )
517 m_fields->erase( m_fields->begin() + ii );
518 }
519 else if( fieldName.IsEmpty() )
520 {
521 // give non-empty, unnamed fields a name
522 field.SetName( _( "untitled" ) );
523 }
524 }
525
527
528 if( m_shapeSizer->AreAnyItemsShown() )
529 {
530 if( m_bidirectional->GetValue() )
531 m_currentLabel->SetShape( LABEL_FLAG_SHAPE::L_BIDI );
532 else if( m_input->GetValue() )
533 m_currentLabel->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
534 else if( m_output->GetValue() )
535 m_currentLabel->SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
536 else if( m_triState->GetValue() )
537 m_currentLabel->SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
538 else if( m_passive->GetValue() )
539 m_currentLabel->SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
540 else if( m_dot->GetValue() )
541 m_currentLabel->SetShape( LABEL_FLAG_SHAPE::F_DOT );
542 else if( m_circle->GetValue() )
543 m_currentLabel->SetShape( LABEL_FLAG_SHAPE::F_ROUND );
544 else if( m_diamond->GetValue() )
545 m_currentLabel->SetShape( LABEL_FLAG_SHAPE::F_DIAMOND );
546 else if( m_rectangle->GetValue() )
547 m_currentLabel->SetShape( LABEL_FLAG_SHAPE::F_RECTANGLE );
548 }
549
551 {
553 m_italic->IsChecked() ) );
554 }
555
557 static_cast<SCH_DIRECTIVE_LABEL*>( m_currentLabel )->SetPinLength( m_textSize.GetIntValue() );
561
562 // Must come after SetTextSize()
565
567
568 SPIN_STYLE selectedSpinStyle= SPIN_STYLE::LEFT;
569
570 if( m_spin0->IsChecked() ) selectedSpinStyle = SPIN_STYLE::RIGHT;
571 else if( m_spin1->IsChecked() ) selectedSpinStyle = SPIN_STYLE::LEFT;
572 else if( m_spin2->IsChecked() ) selectedSpinStyle = SPIN_STYLE::UP;
573 else if( m_spin3->IsChecked() ) selectedSpinStyle = SPIN_STYLE::BOTTOM;
574
576 {
577 SCH_EDIT_FRAME* frame = static_cast<SCH_EDIT_FRAME*>( m_parentFrame );
579 frame->AutoRotateItem( frame->GetScreen(), m_currentLabel );
580 }
581 else
582 {
584 }
585
587 && m_currentLabel->GetSpinStyle() != selectedSpinStyle )
588 {
589 m_currentLabel->SetSpinStyle( selectedSpinStyle );
590 }
591
593
594 if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
595 m_currentLabel->AutoplaceFields( m_Parent->GetScreen(), fieldsAutoplaced );
596
597 if( !commit.Empty() )
598 commit.Push( _( "Edit Label Properties" ) );
599
600 return true;
601}
602
603
604void DIALOG_LABEL_PROPERTIES::onSpinButton( wxCommandEvent& aEvent )
605{
606 for( BITMAP_BUTTON* btn : { m_spin0, m_spin1, m_spin2, m_spin3 } )
607 {
608 if( btn->IsChecked() && btn != aEvent.GetEventObject() )
609 btn->Check( false );
610 }
611}
612
613
614void DIALOG_LABEL_PROPERTIES::OnFormattingHelp( wxHyperlinkEvent& aEvent )
615{
617}
618
619
620void DIALOG_LABEL_PROPERTIES::OnAddField( wxCommandEvent& event )
621{
623 return;
624
625 int fieldID = (int) m_fields->size();
626 wxString fieldName;
627
628 if( (int) fieldID == m_currentLabel->GetMandatoryFieldCount()
629 || m_fields->at( m_fields->size()-1 ).GetCanonicalName() == wxT( "Netclass" ) )
630 {
631 fieldName = wxT( "Netclass" );
632 }
633 else
634 {
635 fieldName = SCH_LABEL_BASE::GetDefaultFieldName( fieldName, true );
636 }
637
638 SCH_FIELD newField( VECTOR2I( 0, 0 ), fieldID, m_currentLabel, fieldName );
639
640 if( m_fields->size() > 0 )
641 {
642 newField.SetVisible( m_fields->at( m_fields->size() - 1 ).IsVisible() );
643 newField.SetTextAngle( m_fields->at( m_fields->size() - 1 ).GetTextAngle() );
644 newField.SetItalic( m_fields->at( m_fields->size() - 1 ).IsItalic() );
645 newField.SetBold( m_fields->at( m_fields->size() - 1 ).IsBold() );
646 }
647 else
648 {
649 newField.SetVisible( true );
650 newField.SetItalic( true );
651 }
652
653 m_fields->push_back( newField );
654
655 // notify the grid
656 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
657 m_grid->ProcessTableMessage( msg );
658
659 m_grid->MakeCellVisible( (int) m_fields->size() - 1, 0 );
660 m_grid->SetGridCursor( (int) m_fields->size() - 1, 0 );
661
662 m_grid->EnableCellEditControl();
663 m_grid->ShowCellEditControl();
664}
665
666
667void DIALOG_LABEL_PROPERTIES::OnDeleteField( wxCommandEvent& event )
668{
669 wxArrayInt selectedRows = m_grid->GetSelectedRows();
670
671 if( selectedRows.empty() && m_grid->GetGridCursorRow() >= 0 )
672 selectedRows.push_back( m_grid->GetGridCursorRow() );
673
674 if( selectedRows.empty() )
675 return;
676
677 for( int row : selectedRows )
678 {
679 if( row < m_currentLabel->GetMandatoryFieldCount() )
680 {
681 DisplayError( this, _( "The first field is mandatory." ) );
682 return;
683 }
684 }
685
686 m_grid->CommitPendingChanges( true /* quiet mode */ );
687
688 // Reverse sort so deleting a row doesn't change the indexes of the other rows.
689 selectedRows.Sort( []( int* first, int* second )
690 {
691 return *second - *first;
692 } );
693
694 for( int row : selectedRows )
695 {
696 //avoids an assert if we deselect early here
697 m_grid->DeselectRow( row );
698 m_fields->erase( m_fields->begin() + row );
699
700 // notify the grid
701 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 );
702 m_grid->ProcessTableMessage( msg );
703
704 if( m_grid->GetNumberRows() > 0 )
705 {
706 m_grid->MakeCellVisible( std::max( 0, row-1 ), m_grid->GetGridCursorCol() );
707 m_grid->SetGridCursor( std::max( 0, row-1 ), m_grid->GetGridCursorCol() );
708 }
709 }
710}
711
712
713void DIALOG_LABEL_PROPERTIES::OnMoveUp( wxCommandEvent& event )
714{
716 return;
717
718 int i = m_grid->GetGridCursorRow();
719
721 {
722 SCH_FIELD tmp = m_fields->at( (unsigned) i );
723 m_fields->erase( m_fields->begin() + i, m_fields->begin() + i + 1 );
724 m_fields->insert( m_fields->begin() + i - 1, tmp );
725 m_grid->ForceRefresh();
726
727 m_grid->SetGridCursor( i - 1, m_grid->GetGridCursorCol() );
728 m_grid->MakeCellVisible( m_grid->GetGridCursorRow(), m_grid->GetGridCursorCol() );
729 }
730 else
731 {
732 wxBell();
733 }
734}
735
736
737void DIALOG_LABEL_PROPERTIES::OnMoveDown( wxCommandEvent& event )
738{
740 return;
741
742 int i = m_grid->GetGridCursorRow();
743
744 if( i >= m_currentLabel->GetMandatoryFieldCount() && i < m_grid->GetNumberRows() - 1 )
745 {
746 SCH_FIELD tmp = m_fields->at( (unsigned) i );
747 m_fields->erase( m_fields->begin() + i, m_fields->begin() + i + 1 );
748 m_fields->insert( m_fields->begin() + i + 1, tmp );
749 m_grid->ForceRefresh();
750
751 m_grid->SetGridCursor( i + 1, m_grid->GetGridCursorCol() );
752 m_grid->MakeCellVisible( m_grid->GetGridCursorRow(), m_grid->GetGridCursorCol() );
753 }
754 else
755 {
756 wxBell();
757 }
758}
759
760
762{
763 m_width = aWidth;
764 // Account for scroll bars
765 aWidth -= ( m_grid->GetSize().x - m_grid->GetClientSize().x );
766
767 m_grid->AutoSizeColumn( 0 );
768 m_grid->SetColSize( 0, std::max( 72, m_grid->GetColSize( 0 ) ) );
769
770 int fixedColsWidth = m_grid->GetColSize( 0 );
771
772 for( int i = 2; i < m_grid->GetNumberCols(); i++ )
773 fixedColsWidth += m_grid->GetColSize( i );
774
775 m_grid->SetColSize( 1, std::max( 120, aWidth - fixedColsWidth ) );
776}
777
778
779void DIALOG_LABEL_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
780{
781 std::bitset<64> shownColumns = m_grid->GetShownColumns();
782
783 if( shownColumns != m_shownColumns )
784 {
785 m_shownColumns = shownColumns;
786
787 if( !m_grid->IsCellEditControlShown() )
788 AdjustGridColumns( m_grid->GetRect().GetWidth() );
789 }
790
791 // Handle a delayed focus
792 if( m_delayedFocusRow >= 0 && m_delayedFocusRow < m_grid->GetNumberRows() )
793 {
794 m_grid->SetFocus();
795 m_grid->MakeCellVisible( m_delayedFocusRow, m_delayedFocusColumn );
797 }
798
801}
802
803
804void DIALOG_LABEL_PROPERTIES::OnSizeGrid( wxSizeEvent& event )
805{
806 int new_size = event.GetSize().GetX();
807
808 if( m_width != new_size )
809 AdjustGridColumns( new_size );
810
811 // Always propagate for a grid repaint (needed if the height changes, as well as width)
812 event.Skip();
813}
814
815
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
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.
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Modify a given item in the model.
Definition: commit.h:108
bool Empty() const
Definition: commit.h:150
Class DIALOG_LABEL_PROPERTIES_BASE.
void OnSizeGrid(wxSizeEvent &event) override
void OnMoveUp(wxCommandEvent &event) override
void OnMoveDown(wxCommandEvent &event) override
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
DIALOG_LABEL_PROPERTIES(SCH_EDIT_FRAME *parent, SCH_LABEL_BASE *aLabel)
void OnUpdateUI(wxUpdateUIEvent &event) override
void onSpinButton(wxCommandEvent &aEvent)
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:102
void SetupStandardButtons(std::map< int, wxString > aLabels={})
std::string m_hash_key
Definition: dialog_shim.h:230
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:248
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:133
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
bool IsNew() const
Definition: eda_item.h:107
void SetTextColor(const COLOR4D &aColor)
Definition: eda_text.h:256
COLOR4D GetTextColor() const
Definition: eda_text.h:257
bool IsItalic() const
Definition: eda_text.h:156
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:134
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition: eda_text.cpp:524
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:98
KIFONT::FONT * GetFont() const
Definition: eda_text.h:234
int GetTextWidth() const
Definition: eda_text.h:251
void Offset(const VECTOR2I &aOffset)
Definition: eda_text.cpp:587
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition: eda_text.h:187
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:377
void SetBold(bool aBold)
Set the text to be bold - this will also update the font if needed.
Definition: eda_text.cpp:326
bool IsBold() const
Definition: eda_text.h:171
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition: eda_text.h:190
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:268
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:290
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
Definition: eda_text.cpp:298
void SetFont(KIFONT::FONT *aFont)
Definition: eda_text.cpp:490
int GetNumberRows() override
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:312
wxString ConvertKIIDsToRefs(const wxString &aSource) const
Definition: schematic.cpp:581
wxString ConvertRefsToKIIDs(const wxString &aSource) const
Definition: schematic.cpp:511
SCH_SHEET & Root() const
Definition: schematic.h:130
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:432
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)
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:51
VECTOR2I GetPosition() const override
Definition: sch_field.cpp:1485
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:1254
void SetName(const wxString &aName)
Definition: sch_field.cpp:1204
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:167
SCHEMATIC * Schematic() const
Searches the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:150
void SetFieldsAutoplaced(AUTOPLACE_ALGO aAlgo)
Definition: sch_item.h:550
AUTOPLACE_ALGO GetFieldsAutoplaced() const
Return whether the fields have been automatically placed.
Definition: sch_item.h:549
void SetFields(const std::vector< SCH_FIELD > &aFields)
Set multiple schematic fields.
Definition: sch_label.h:209
bool AutoRotateOnPlacement() const
autoRotateOnPlacement
Definition: sch_label.cpp:1400
SPIN_STYLE GetSpinStyle() const
Definition: sch_label.cpp:331
void SetShape(LABEL_FLAG_SHAPE aShape)
Definition: sch_label.h:178
LABEL_FLAG_SHAPE GetShape() const
Definition: sch_label.h:177
virtual bool AutoRotateOnPlacementSupported() const =0
AutoRotateOnPlacementSupported.
void SetAutoRotateOnPlacement(bool autoRotate=true)
setAutoRotateOnPlacement
Definition: sch_label.cpp:1406
static const wxString GetDefaultFieldName(const wxString &aName, bool aUseDefaultName)
Definition: sch_label.cpp:202
void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo) override
Definition: sch_label.cpp:560
virtual int GetMandatoryFieldCount()
Definition: sch_label.h:199
std::vector< SCH_FIELD > & GetFields()
Definition: sch_label.h:201
virtual wxString GetClass() const override=0
Return the class name.
virtual void SetSpinStyle(SPIN_STYLE aSpinStyle)
Definition: sch_label.cpp:296
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:712
SCH_SCREEN * GetNext()
SCH_SCREEN * GetFirst()
Schematic symbol object.
Definition: sch_symbol.h:77
bool IsSymbolLikePowerGlobalLabel() const
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:906
static HTML_MESSAGE_BOX * ShowSyntaxHelp(wxWindow *aParentWindow)
Definition: sch_label.cpp:2155
VECTOR2I GetPosition() const override
Definition: sch_text.h:141
void SetBitmap(const wxBitmapBundle &aBmp)
int GetIntValue()
Definition: unit_binder.h:129
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:496
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:277
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:451
wxString GetShownColumnsAsString()
Get a tokenized string containing the shown column indexes.
Definition: wx_grid.cpp:466
std::bitset< 64 > GetShownColumns()
Definition: wx_grid.cpp:485
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:646
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:170
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:222
This file is part of the common library.
static bool positioningChanged(const SCH_FIELD &a, const SCH_FIELD &b)
#define _(s)
@ FDC_VALUE
@ LAYER_FIELDS
Definition: layer_ids.h:414
@ LAYER_NETCLASS_REFS
Definition: layer_ids.h:416
@ LAYER_SCHEMATIC_BACKGROUND
Definition: layer_ids.h:440
@ LAYER_INTERSHEET_REFS
Definition: layer_ids.h:415
#define UNIMPLEMENTED_FOR(type)
Definition: macros.h:96
AUTOPLACE_ALGO
Definition: sch_item.h:68
@ AUTOPLACE_MANUAL
Definition: sch_item.h:71
@ AUTOPLACE_NONE
Definition: sch_item.h:69
@ AUTOPLACE_AUTO
Definition: sch_item.h:70
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:398
@ CTX_NETNAME
Definition: string_utils.h:53
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ SCH_DIRECTIVE_LABEL_T
Definition: typeinfo.h:171
@ SCH_LABEL_T
Definition: typeinfo.h:167
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:169
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:173
@ SCH_SYMBOL_LOCATE_POWER_T
Definition: typeinfo.h:195
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:168
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695