KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_footprint_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) 2016 Mario Luzeiro <[email protected]>
5 * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
6 * Copyright (C) 2015 Dick Hollenbeck, [email protected]
7 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
24#include <bitmaps.h>
25#include <board_commit.h>
27#include <board.h>
28#include <footprint.h>
29#include <eda_group.h>
30#include <confirm.h>
32#include <filename_resolver.h>
33#include <pcb_edit_frame.h>
34#include <pcbnew_settings.h>
36#include <pgm_base.h>
37#include <project_pcb.h>
38#include <kiplatform/ui.h>
47#include <tool/tool_manager.h>
49
50
51int DIALOG_FOOTPRINT_PROPERTIES::m_page = 0; // remember the last open page during session
52
53
56 m_frame( aParent ),
57 m_footprint( aFootprint ),
65 m_initialized( false )
66{
67 // Create the extra panels. Embedded files is referenced by the 3D model panel.
70
71 m_NoteBook->AddPage( m_3dPanel, _("3D Models"), false );
72 m_NoteBook->AddPage( m_embeddedFiles, _( "Embedded Files" ) );
73
74 // Configure display origin transforms
77
78 std::vector<EMBEDDED_FILES*> embeddedFilesStack;
79 embeddedFilesStack.push_back( m_embeddedFiles->GetLocalFiles() );
80 embeddedFilesStack.push_back( m_frame->GetBoard()->GetEmbeddedFiles() );
81
82 m_fields = new PCB_FIELDS_GRID_TABLE( m_frame, this, std::move( embeddedFilesStack ) );
83
84 m_delayedErrorMessage = wxEmptyString;
85 m_delayedFocusGrid = nullptr;
88 m_initialFocus = false;
89
90 // Give an icon
91 wxIcon icon;
92 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_modedit ) );
93 SetIcon( icon );
94
95 m_itemsGrid->SetTable( m_fields );
96 m_itemsGrid->OverrideMinSize( 1.0, 1.0 );
97 m_itemsGrid->PushEventHandler( new GRID_TRICKS( m_itemsGrid ) );
98 m_itemsGrid->SetupColumnAutosizer( PFC_VALUE );
99 m_itemsGrid->ShowHideColumns( "0 1 2 3 4 5 7" );
100
102 m_orientation.SetPrecision( 3 );
103
104 // Set predefined rotations in combo dropdown, according to the locale floating point
105 // separator notation
106 double rot_list[] = { 0.0, 90.0, -90.0, 180.0 };
107
108 for( size_t ii = 0; ii < m_orientationCtrl->GetCount() && ii < 4; ++ii )
109 m_orientationCtrl->SetString( ii, wxString::Format( "%.1f", rot_list[ii] ) );
110
111 // Set font size for items showing long strings:
112 wxFont infoFont = KIUI::GetSmallInfoFont( this );
113 m_libraryIDLabel->SetFont( infoFont );
114 m_tcLibraryID->SetFont( infoFont );
115
116 infoFont = KIUI::GetInfoFont( this ).Italic();
117 m_staticTextInfoCopper->SetFont( infoFont );
118 m_staticTextInfoPaste->SetFont( infoFont );
119
120 m_NoteBook->SetSelection( m_page );
121
122 if( m_page == 0 )
123 {
127 }
128 else if( m_page == 1 )
129 {
131 }
132
133 // Update label text and tooltip for combined offset + ratio field
134 m_SolderPasteMarginLabel->SetLabel( _( "Solder paste clearance:" ) );
135 m_SolderPasteMarginLabel->SetToolTip( _( "Local solder paste clearance for this footprint.\n"
136 "Enter an absolute value (e.g., -0.1mm), a percentage "
137 "(e.g., -5%), or both (e.g., -0.1mm - 5%).\n"
138 "If blank, the global value is used." ) );
139
140 // Configure button logos
143
144 m_tcLibraryID->SetBackgroundColour( KIPLATFORM::UI::GetDialogBGColour() );
145
146 // We can't set the tab order through wxWidgets due to shortcomings in their mnemonics
147 // implementation on MSW
148 m_tabOrder = {
157 m_cbDNP,
165 };
166
168
169 // The 3D model tab was added after the base dtor. The final dialog size needs to be set
170 // accordingly.
171 SetSizer( m_GeneralBoxSizer );
172 Layout();
173 m_GeneralBoxSizer->Fit( this );
174
176}
177
178
180{
181 // Prevents crash bug in wxGrid's d'tor
182 m_itemsGrid->DestroyTable( m_fields );
183
184 // Delete the GRID_TRICKS.
185 m_itemsGrid->PopEventHandler( true );
186
187 // free the memory used by all models, otherwise models which were
188 // browsed but not used would consume memory
190
191 // the GL canvas has to be visible before it is destroyed
192 m_page = m_NoteBook->GetSelection();
193 m_NoteBook->SetSelection( 1 );
194}
195
196
198{
200 {
202 Close();
203 }
204}
205
206
208{
210 {
212 Close();
213 }
214}
215
216
218{
220 {
222 Close();
223 }
224}
225
226
228{
230 {
232 Close();
233 }
234}
235
236
238{
239 if( !wxDialog::TransferDataToWindow() )
240 return false;
241
242 if( !m_PanelGeneral->TransferDataToWindow() )
243 return false;
244
245 // Add the models to the panel
246 if( !m_3dPanel->TransferDataToWindow() )
247 return false;
248
249 if( !m_embeddedFiles->TransferDataToWindow() )
250 return false;
251
252 wxString variantName;
253
254 if( m_footprint->GetBoard() )
255 variantName = m_footprint->GetBoard()->GetCurrentVariant();
256
257 // Footprint Fields
258 for( PCB_FIELD* srcField : m_footprint->GetFields() )
259 {
260 wxCHECK2( srcField, continue );
261
262 PCB_FIELD field( *srcField );
263 wxString text = m_footprint->GetFieldValueForVariant( variantName, field.GetName() );
264 field.SetText( m_footprint->GetBoard()->ConvertKIIDsToCrossReferences( text ) );
265
266 m_fields->push_back( field );
267 }
268
269 // notify the grid
270 wxGridTableMessage tmsg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->GetNumberRows() );
271 m_itemsGrid->ProcessTableMessage( tmsg );
272
273 // Footprint Properties
274
275 m_posX.SetValue( m_footprint->GetPosition().x );
276 m_posY.SetValue( m_footprint->GetPosition().y );
277
278 m_BoardSideCtrl->SetSelection( (m_footprint->GetLayer() == B_Cu) ? 1 : 0 );
279
280 EDA_ANGLE orientation = m_footprint->GetOrientation();
281 m_orientation.SetAngleValue( orientation.Normalize180() );
282
283 m_cbLocked->SetValue( m_footprint->IsLocked() );
284 m_cbLocked->SetToolTip( _( "Locked footprints cannot be freely moved or oriented on the canvas and can only be "
285 "selected when the 'Locked items' checkbox is checked in the selection filter." ) );
286
287 if( m_footprint->GetAttributes() & FP_THROUGH_HOLE )
288 m_componentType->SetSelection( 0 );
289 else if( m_footprint->GetAttributes() & FP_SMD )
290 m_componentType->SetSelection( 1 );
291 else
292 m_componentType->SetSelection( 2 );
293
294 m_boardOnly->SetValue( m_footprint->GetAttributes() & FP_BOARD_ONLY );
295
296 m_excludeFromPosFiles->SetValue( m_footprint->GetExcludedFromPosFilesForVariant( variantName ) );
297 m_excludeFromBOM->SetValue( m_footprint->GetExcludedFromBOMForVariant( variantName ) );
298 m_cbDNP->SetValue( m_footprint->GetDNPForVariant( variantName ) );
299
300 // Local Clearances
301
302 if( m_footprint->GetLocalClearance().has_value() )
303 m_netClearance.SetValue( m_footprint->GetLocalClearance().value() );
304 else
305 m_netClearance.SetValue( wxEmptyString );
306
307 if( m_footprint->GetLocalSolderMaskMargin().has_value() )
308 m_solderMask.SetValue( m_footprint->GetLocalSolderMaskMargin().value() );
309 else
310 m_solderMask.SetValue( wxEmptyString );
311
312 m_solderPaste.SetOffsetValue( m_footprint->GetLocalSolderPasteMargin() );
313 m_solderPaste.SetRatioValue( m_footprint->GetLocalSolderPasteMarginRatio() );
314
315 m_allowSolderMaskBridges->SetValue( m_footprint->AllowSolderMaskBridges() );
316
317 switch( m_footprint->GetLocalZoneConnection() )
318 {
319 default:
320 case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
321 case ZONE_CONNECTION::FULL: m_ZoneConnectionChoice->SetSelection( 1 ); break;
322 case ZONE_CONNECTION::THERMAL: m_ZoneConnectionChoice->SetSelection( 2 ); break;
323 case ZONE_CONNECTION::NONE: m_ZoneConnectionChoice->SetSelection( 3 ); break;
324 }
325
326 wxString jumperGroups;
327
328 if( m_footprint->GetDuplicatePadNumbersAreJumpers() )
329 jumperGroups = _( "all pads with duplicate numbers" );
330
331 for( const std::set<wxString>& group : m_footprint->JumperPadGroups() )
332 {
333 wxString groupTxt;
334
335 for( const wxString& pinNumber : group )
336 {
337 if( !groupTxt.IsEmpty() )
338 groupTxt << ", ";
339
340 groupTxt << pinNumber;
341 }
342
343 if( !jumperGroups.IsEmpty() )
344 jumperGroups << "; ";
345
346 jumperGroups << "(" << groupTxt << ")";
347 }
348
349 if( jumperGroups.IsEmpty() )
350 {
351 m_jumperGroupsText->SetLabel( _( "none" ) );
353 }
354 else
355 {
356 m_jumperGroupsText->SetLabel( jumperGroups );
357 }
358
359 // Show the footprint's FPID.
360 m_tcLibraryID->SetValue( m_footprint->GetFPID().Format() );
361
362 for( int col = 0; col < m_itemsGrid->GetNumberCols(); col++ )
363 {
364 m_itemsGrid->SetColMinimalWidth( col, m_itemsGrid->GetVisibleWidth( col, true, false ) );
365
366 // Adjust the column size.
367 int col_size = m_itemsGrid->GetVisibleWidth( col );
368
369 if( col == PFC_LAYER ) // This one's a drop-down. Check all possible values.
370 {
371 BOARD* board = m_footprint->GetBoard();
372
373 for( PCB_LAYER_ID layer : board->GetEnabledLayers() )
374 col_size = std::max( col_size, GetTextExtent( board->GetLayerName( layer ) ).x );
375
376 // Swatch and gaps:
377 col_size += KiROUND( 14 * GetDPIScaleFactor() ) + 12;
378 }
379
380 if( m_itemsGrid->IsColShown( col ) )
381 m_itemsGrid->SetColSize( col, col_size );
382 }
383
384 m_itemsGrid->SetRowLabelSize( 0 );
385
386 Layout();
387 m_itemsGrid->SetMinVisibleRows( this, 4 );
388 m_initialized = true;
389
390 return true;
391}
392
393
395{
396 if( !m_itemsGrid->CommitPendingChanges() )
397 return false;
398
399 if( !DIALOG_SHIM::Validate() )
400 return false;
401
402 // Validate texts.
403 for( size_t i = 0; i < m_fields->size(); ++i )
404 {
405 PCB_FIELD& field = m_fields->at( i );
406
407 // Check for missing field names.
408 if( field.GetName( false ).IsEmpty() )
409 {
411 m_delayedErrorMessage = wxString::Format( _( "Fields must have a name." ) );
414
415 return false;
416 }
417
418 int minSize = pcbIUScale.mmToIU( TEXT_MIN_SIZE_MM );
419 int maxSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
420 int width = m_frame->ValueFromString( m_itemsGrid->GetCellValue( i, PFC_WIDTH ) );
421 int height = m_frame->ValueFromString( m_itemsGrid->GetCellValue( i, PFC_HEIGHT ) );
422
423 if( width < minSize )
424 {
425 wxString min = m_frame->StringFromValue( minSize, true );
426
427 m_itemsGrid->SetCellValue( i, PFC_WIDTH, min );
428
430 m_delayedErrorMessage = wxString::Format( _( "Text width must be at least %s." ), min );
433
434 return false;
435 }
436 else if( width > maxSize )
437 {
438 wxString max = m_frame->StringFromValue( maxSize, true );
439
440 m_itemsGrid->SetCellValue( i, PFC_WIDTH, max );
441
443 m_delayedErrorMessage = wxString::Format( _( "Text width must be at most %s." ), max );
446
447 return false;
448 }
449
450 if( height < minSize )
451 {
452 wxString min = m_frame->StringFromValue( minSize, true );
453
454 m_itemsGrid->SetCellValue( i, PFC_HEIGHT, min );
455
457 m_delayedErrorMessage = wxString::Format( _( "Text height must be at least %s." ), min );
460
461 return false;
462 }
463 else if( height > maxSize )
464 {
465 wxString max = m_frame->StringFromValue( maxSize, true );
466
467 m_itemsGrid->SetCellValue( i, PFC_HEIGHT, max );
468
470 m_delayedErrorMessage = wxString::Format( _( "Text height must be at most %s." ), max );
473
474 return false;
475 }
476
477 // Test for acceptable values for thickness and size and clamp if fails
478 int maxPenWidth = ClampTextPenSize( field.GetTextThickness(), field.GetTextSize() );
479
480 if( field.GetTextThickness() > maxPenWidth )
481 {
482 wxString clamped = m_frame->StringFromValue( maxPenWidth, true );
483
484 m_itemsGrid->SetCellValue( i, PFC_THICKNESS, clamped );
485
487 m_delayedErrorMessage = wxString::Format( _( "Text thickness is too large for the text size.\n"
488 "It will be clamped at %s." ),
489 clamped );
492
493 return false;
494 }
495 }
496
497 if( !m_netClearance.Validate( 0, INT_MAX ) )
498 return false;
499
500 return true;
501}
502
503
505{
506 if( !Validate() )
507 return false;
508
509 if( !m_itemsGrid->CommitPendingChanges() )
510 return false;
511
512 KIGFX::PCB_VIEW* view = m_frame->GetCanvas()->GetView();
513 PCB_SELECTION_TOOL* selectionTool = m_frame->GetToolManager()->GetTool<PCB_SELECTION_TOOL>();
514 BOARD_COMMIT commit( m_frame );
515 commit.Modify( m_footprint );
516
517 // Make sure this happens inside a commit to capture any changed files
518 if( !m_3dPanel->TransferDataFromWindow() )
519 return false;
520
521 if( !m_embeddedFiles->TransferDataFromWindow() )
522 return false;
523
524 // Clear out embedded files that are no longer in use
525 std::set<wxString> files;
526 std::set<wxString> files_to_delete;
527
528 // Get the new files from the footprint fields
529 for( PCB_FIELD& field : *m_fields )
530 {
531 if( field.GetText().StartsWith( FILEEXT::KiCadUriPrefix ) )
532 files.insert( field.GetText() );
533 }
534
535 // Find any files referenced in the old fields that are not in the new fields
536 for( PCB_FIELD* field : m_footprint->GetFields() )
537 {
538 wxCHECK2( field, continue );
539
540 if( field->GetText().StartsWith( FILEEXT::KiCadUriPrefix ) )
541 {
542 if( files.find( field->GetText() ) == files.end() )
543 files_to_delete.insert( field->GetText() );
544 }
545 }
546
547 for( const wxString& file : files_to_delete )
548 {
549 wxString name = file.Mid( FILEEXT::KiCadUriPrefix.size() + 3 ); // Skip "kicad-embed://"
550 m_footprint->RemoveFile( name );
551 }
552
553 // Update fields
554 BOARD* board = m_footprint->GetBoard();
555
556 wxString variantName;
557
558 if( board )
559 variantName = board->GetCurrentVariant();
560
561 // Save base field values before deletion so we can detect variant changes
562 std::map<wxString, wxString> baseFieldValues;
563
564 for( PCB_FIELD* existing : m_footprint->GetFields() )
565 baseFieldValues[existing->GetName()] = existing->GetText();
566
567 for( PCB_FIELD* existing : m_footprint->GetFields() )
568 {
569 if( board )
570 board->UncacheItemById( existing->m_Uuid );
571
572 if( EDA_GROUP* parentGroup = existing->GetParentGroup() )
573 parentGroup->RemoveItem( existing );
574
575 delete existing;
576 }
577
578 m_footprint->GetFields().clear();
579
580 int ordinal = 42; // Arbitrarily larger than any mandatory FIELD_T ids.
581
582 for( PCB_FIELD& field : *m_fields )
583 {
584 PCB_FIELD* newField = field.CloneField();
585 wxString newText = commit.GetBoard()->ConvertCrossReferencesToKIIDs( field.GetText() );
586
587 if( !variantName.IsEmpty() )
588 {
589 auto it = baseFieldValues.find( field.GetName() );
590 wxString baseText = ( it != baseFieldValues.end() ) ? it->second : wxString();
591
592 FOOTPRINT_VARIANT* variant = m_footprint->GetVariant( variantName );
593
594 if( !variant )
595 variant = m_footprint->AddVariant( variantName );
596
597 if( variant )
598 variant->SetFieldValue( field.GetName(), newText );
599
600 newField->SetText( baseText );
601 }
602 else
603 {
604 newField->SetText( newText );
605 }
606
607 if( !field.IsMandatory() )
608 newField->SetOrdinal( ordinal++ );
609
610 m_footprint->Add( newField );
611 view->Add( newField );
612
613 if( EDA_GROUP* parentGroup = newField->GetParentGroup() )
614 parentGroup->AddItem( newField );
615
616 if( newField->IsSelected() )
617 {
618 // The old copy was in the selection list, but this one is not. Remove the
619 // out-of-sync selection flag so we can re-add the field to the selection.
620 newField->ClearSelected();
621 selectionTool->AddItemToSel( newField, true );
622 }
623 }
624
625 // Initialize masks clearances
626 if( m_netClearance.IsNull() )
627 m_footprint->SetLocalClearance( {} );
628 else
629 m_footprint->SetLocalClearance( m_netClearance.GetValue() );
630
631 if( m_solderMask.IsNull() )
632 m_footprint->SetLocalSolderMaskMargin( {} );
633 else
634 m_footprint->SetLocalSolderMaskMargin( m_solderMask.GetValue() );
635
636 m_footprint->SetLocalSolderPasteMargin( m_solderPaste.GetOffsetValue() );
637 m_footprint->SetLocalSolderPasteMarginRatio( m_solderPaste.GetRatioValue() );
638
639 switch( m_ZoneConnectionChoice->GetSelection() )
640 {
641 default:
642 case 0: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::INHERITED ); break;
643 case 1: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::FULL ); break;
644 case 2: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::THERMAL ); break;
645 case 3: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::NONE ); break;
646 }
647
648 // Set Footprint Position
649 VECTOR2I pos( m_posX.GetValue(), m_posY.GetValue() );
650 m_footprint->SetPosition( pos );
651 m_footprint->SetLocked( m_cbLocked->GetValue() );
652
653 int attributes = 0;
654
655 switch( m_componentType->GetSelection() )
656 {
657 case 0: attributes |= FP_THROUGH_HOLE; break;
658 case 1: attributes |= FP_SMD; break;
659 default: break;
660 }
661
662 if( m_boardOnly->GetValue() )
663 attributes |= FP_BOARD_ONLY;
664
665 if( !variantName.IsEmpty() )
666 {
667 FOOTPRINT_VARIANT* variant = m_footprint->GetVariant( variantName );
668
669 if( !variant )
670 variant = m_footprint->AddVariant( variantName );
671
672 if( variant )
673 {
674 variant->SetExcludedFromPosFiles( m_excludeFromPosFiles->GetValue() );
675 variant->SetExcludedFromBOM( m_excludeFromBOM->GetValue() );
676 variant->SetDNP( m_cbDNP->GetValue() );
677 }
678
679 // Preserve base attribute flags for these three properties
680 if( m_footprint->GetAttributes() & FP_EXCLUDE_FROM_POS_FILES )
681 attributes |= FP_EXCLUDE_FROM_POS_FILES;
682
683 if( m_footprint->GetAttributes() & FP_EXCLUDE_FROM_BOM )
684 attributes |= FP_EXCLUDE_FROM_BOM;
685
686 if( m_footprint->GetAttributes() & FP_DNP )
687 attributes |= FP_DNP;
688 }
689 else
690 {
691 if( m_excludeFromPosFiles->GetValue() )
692 attributes |= FP_EXCLUDE_FROM_POS_FILES;
693
694 if( m_excludeFromBOM->GetValue() )
695 attributes |= FP_EXCLUDE_FROM_BOM;
696
697 if( m_cbDNP->GetValue() )
698 attributes |= FP_DNP;
699 }
700
701 m_footprint->SetAttributes( attributes );
702
703 m_footprint->SetAllowSolderMaskBridges( m_allowSolderMaskBridges->GetValue() );
704
705 EDA_ANGLE orient = m_orientation.GetAngleValue().Normalize();
706
707 if( m_footprint->GetOrientation() != orient )
708 m_footprint->Rotate( m_footprint->GetPosition(), orient - m_footprint->GetOrientation() );
709
710 // Set component side, that also have effect on the fields positions on board
711 bool change_layer = false;
712
713 if( m_BoardSideCtrl->GetSelection() == 0 ) // layer req = COMPONENT
714 {
715 if( m_footprint->GetLayer() == B_Cu )
716 change_layer = true;
717 }
718 else if( m_footprint->GetLayer() == F_Cu )
719 {
720 change_layer = true;
721 }
722
723 if( change_layer )
724 m_footprint->Flip( m_footprint->GetPosition(), m_frame->GetPcbNewSettings()->m_FlipDirection );
725
726 // Copy the models from the panel to the footprint
727 std::vector<FP_3DMODEL>& panelList = m_3dPanel->GetModelList();
728 std::vector<FP_3DMODEL>* fpList = &m_footprint->Models();
729 fpList->clear();
730 fpList->insert( fpList->end(), panelList.begin(), panelList.end() );
731
732 // This is a simple edit, we must create an undo entry
733 if( m_footprint->GetEditFlags() == 0 ) // i.e. not edited, or moved
734 commit.Push( _( "Edit Footprint Properties" ) );
735
737 return true;
738}
739
740
742{
743 m_itemsGrid->OnAddRow(
744 [&]() -> std::pair<int, int>
745 {
747
748 newField.SetVisible( false );
749 newField.SetLayer( m_footprint->GetLayer() == F_Cu ? F_Fab : B_Fab );
750 newField.SetFPRelativePosition( { 0, 0 } );
751 newField.StyleFromSettings( m_frame->GetDesignSettings(), true );
752
753 m_fields->push_back( newField );
754
755 // notify the grid
756 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
757 m_itemsGrid->ProcessTableMessage( msg );
758 OnModify();
759
760 return { m_fields->size() - 1, PFC_NAME };
761 } );
762}
763
764
766{
767 m_itemsGrid->OnDeleteRows(
768 [&]( int row )
769 {
770 if( row < m_fields->GetMandatoryRowCount() )
771 {
772 DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
773 m_fields->GetMandatoryRowCount() ) );
774 return false;
775 }
776
777 return true;
778 },
779 [&]( int row )
780 {
781 m_fields->erase( m_fields->begin() + row );
782
783 // notify the grid
784 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 );
785 m_itemsGrid->ProcessTableMessage( msg );
786 } );
787
788 OnModify();
789}
790
791
793{
794 if( !m_initialized )
795 return;
796
797 // Handle a grid error. This is delayed to OnUpdateUI so that we can change focus
798 // even when the original validation was triggered from a killFocus event, and so
799 // that the corresponding notebook page can be shown in the background when triggered
800 // from an OK.
801 if( m_delayedFocusRow >= 0 )
802 {
803 // We will re-enter this routine if an error dialog is displayed, so make sure we
804 // zero out our member variables first.
805 wxGrid* grid = m_delayedFocusGrid;
806 int row = m_delayedFocusRow;
807 int col = m_delayedFocusColumn;
808 wxString msg = m_delayedErrorMessage;
809
810 m_delayedFocusGrid = nullptr;
813 m_delayedErrorMessage = wxEmptyString;
814
815 if( !msg.IsEmpty() )
816 {
817 // Do not use DisplayErrorMessage(); it screws up window order on Mac
818 DisplayError( nullptr, msg );
819 }
820
821 grid->SetFocus();
822 grid->MakeCellVisible( row, col );
823
824 // Selecting the first grid item only makes sense for the
825 // items grid
826 if( !m_initialFocus || grid == m_itemsGrid )
827 {
828 grid->SetGridCursor( row, col );
829
830 if( !( col == 0 && row < m_fields->GetMandatoryRowCount() ) )
831 grid->EnableCellEditControl( true );
832
833 grid->ShowCellEditControl();
834
835 if( grid == m_itemsGrid && row == 0 && col == 0 )
836 {
837 wxGridCellEditor* referenceEditor = grid->GetCellEditor( 0, 0 );
838
839 if( wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( referenceEditor->GetControl() ) )
840 KIUI::SelectReferenceNumber( textEntry );
841
842 referenceEditor->DecRef();
843 }
844 }
845
846 m_initialFocus = false;
847 }
848}
849
850
851void DIALOG_FOOTPRINT_PROPERTIES::OnPageChanging( wxNotebookEvent& aEvent )
852{
853 if( !m_itemsGrid->CommitPendingChanges() )
854 aEvent.Veto();
855}
856
857
858void DIALOG_FOOTPRINT_PROPERTIES::OnCheckBox( wxCommandEvent& event )
859{
860 if( m_initialized )
861 OnModify();
862}
863
864
865void DIALOG_FOOTPRINT_PROPERTIES::OnCombobox( wxCommandEvent& event )
866{
867 if( m_initialized )
868 OnModify();
869}
870
871
872void DIALOG_FOOTPRINT_PROPERTIES::OnText( wxCommandEvent& event )
873{
874 if( m_initialized )
875 OnModify();
876}
877
878
879void DIALOG_FOOTPRINT_PROPERTIES::OnChoice( wxCommandEvent& event )
880{
881 if( m_initialized )
882 OnModify();
883}
const char * name
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition bitmap.cpp:100
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:986
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition board_item.h:343
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
void SetFPRelativePosition(const VECTOR2I &aPos)
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:373
void UncacheItemById(const KIID &aId) const
Remove an item from the item-by-id cache.
Definition board.cpp:2108
wxString ConvertCrossReferencesToKIIDs(const wxString &aSource) const
Convert cross-references back and forth between ${refDes:field} and ${kiid:field}.
Definition board.cpp:2340
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition board.cpp:802
wxString GetCurrentVariant() const
Definition board.h:473
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition board.cpp:1043
DIALOG_FOOTPRINT_PROPERTIES_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Footprint Properties"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
void OnDeleteField(wxCommandEvent &) override
void OnUpdateUI(wxUpdateUIEvent &) override
void OnAddField(wxCommandEvent &) override
void OnText(wxCommandEvent &event) override
void OnCombobox(wxCommandEvent &event) override
PANEL_FP_PROPERTIES_3D_MODEL * m_3dPanel
void OnPageChanging(wxNotebookEvent &event) override
void EditLibraryFootprint(wxCommandEvent &) override
DIALOG_FOOTPRINT_PROPERTIES(PCB_EDIT_FRAME *aParent, FOOTPRINT *aFootprint)
void OnChoice(wxCommandEvent &event) override
void EditFootprint(wxCommandEvent &) override
void OnCheckBox(wxCommandEvent &event) override
void UpdateFootprint(wxCommandEvent &) override
void ChangeFootprint(wxCommandEvent &) override
std::vector< wxWindow * > m_tabOrder
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition dialog_shim.h:94
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
EDA_ANGLE Normalize180()
Definition eda_angle.h:268
A set of EDA_ITEMs (i.e., without duplicates).
Definition eda_group.h:42
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:114
void ClearSelected()
Definition eda_item.h:147
bool IsSelected() const
Definition eda_item.h:132
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:381
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:265
Variant information for a footprint.
Definition footprint.h:215
void SetExcludedFromPosFiles(bool aExclude)
Definition footprint.h:235
void SetDNP(bool aDNP)
Definition footprint.h:229
void SetFieldValue(const wxString &aFieldName, const wxString &aValue)
Set a field value override for this variant.
Definition footprint.h:257
void SetExcludedFromBOM(bool aExclude)
Definition footprint.h:232
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition grid_tricks.h:57
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1) override
Add a VIEW_ITEM to the view.
Definition pcb_view.cpp:53
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
The main frame for Pcbnew.
void SetOrdinal(int aOrdinal)
Definition pcb_field.h:116
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
PCB_FIELD * CloneField() const
Same as Clone, but returns a PCB_FIELD item.
Definition pcb_field.h:90
The selection tool: currently supports:
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings, bool aCheckSide) override
Definition pcb_text.cpp:355
int GetTextThickness() const override
Definition pcb_text.cpp:481
VECTOR2I GetTextSize() const override
Definition pcb_text.cpp:454
static S3D_CACHE * Get3DCacheManager(PROJECT *aProject, bool updateProjDir=false)
Return a pointer to an instance of the 3D cache manager.
void FlushCache(bool closePlugins=true)
Free all data in the cache and by default closes all plugins.
Definition 3d_cache.cpp:553
int AddItemToSel(const TOOL_EVENT &aEvent)
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:192
This file is part of the common library.
const int minSize
Push and Shove router track width and via size dialog.
#define _(s)
Declaration of the eda_3d_viewer class.
#define TEXT_MIN_SIZE_MM
Minimum text size (1 micron).
Definition eda_text.h:56
#define TEXT_MAX_SIZE_MM
Maximum text size in mm (~10 inches)
Definition eda_text.h:57
@ FP_SMD
Definition footprint.h:84
@ FP_DNP
Definition footprint.h:89
@ FP_EXCLUDE_FROM_POS_FILES
Definition footprint.h:85
@ FP_BOARD_ONLY
Definition footprint.h:87
@ FP_EXCLUDE_FROM_BOM
Definition footprint.h:86
@ FP_THROUGH_HOLE
Definition footprint.h:83
int ClampTextPenSize(int aPenSize, int aSize, bool aStrict)
Pen width should not allow characters to become cluttered up in their own fatness.
Definition gr_text.cpp:69
static const std::string KiCadUriPrefix
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ B_Cu
Definition layer_ids.h:61
@ F_Fab
Definition layer_ids.h:115
@ F_Cu
Definition layer_ids.h:60
@ B_Fab
Definition layer_ids.h:114
wxColour GetDialogBGColour()
Definition wxgtk/ui.cpp:64
KICOMMON_API wxFont GetInfoFont(wxWindow *aWindow)
KICOMMON_API wxFont GetSmallInfoFont(wxWindow *aWindow)
KICOMMON_API wxFont GetControlFont(wxWindow *aWindow)
KICOMMON_API void SelectReferenceNumber(wxTextEntry *aTextEntry)
Select the number (or "?") in a reference for ease of editing.
@ PFC_THICKNESS
see class PGM_BASE
wxString GetUserFieldName(int aFieldNdx, bool aTranslateForHI)
#define DO_TRANSLATE
@ USER
The field ID hasn't been set yet; field is invalid.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
@ THERMAL
Use thermal relief for pads.
Definition zones.h:46
@ NONE
Pads are not covered.
Definition zones.h:45
@ FULL
pads are covered by copper
Definition zones.h:47