KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_footprint_properties_fp_editor.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) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2015 Dick Hollenbeck, [email protected]
6 * Copyright (C) 2008 Wayne Stambaugh <[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, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
29#include <bitmaps.h>
30#include <board_commit.h>
32#include <confirm.h>
36#include <embedded_files.h>
37#include <filename_resolver.h>
38#include <footprint.h>
42#include <kiplatform/ui.h>
45#include <pgm_base.h>
47#include <tool/tool_manager.h>
48#include <tools/pcb_actions.h>
50#include <validators.h>
54#include <widgets/wx_grid.h>
55
56#include <fp_lib_table.h>
57#include <project_pcb.h>
58#include <kidialog.h>
59
61 m_frame( aFrame )
62{
63 m_layerColAttr = new wxGridCellAttr;
64 m_layerColAttr->SetRenderer( new GRID_CELL_LAYER_RENDERER( m_frame ) );
65
66 LSET forbiddenLayers = LSET::AllCuMask() | LSET::AllTechMask();
67 forbiddenLayers.set( Edge_Cuts );
68 forbiddenLayers.set( Margin );
69 m_layerColAttr->SetEditor( new GRID_CELL_LAYER_SELECTOR( m_frame, forbiddenLayers, true ) );
70}
71
72
74{
75 m_layerColAttr->DecRef();
76}
77
78
79bool PRIVATE_LAYERS_GRID_TABLE::CanGetValueAs( int aRow, int aCol, const wxString& aTypeName )
80{
81 return aTypeName == wxGRID_VALUE_NUMBER;
82}
83
84
85bool PRIVATE_LAYERS_GRID_TABLE::CanSetValueAs( int aRow, int aCol, const wxString& aTypeName )
86{
87 return aTypeName == wxGRID_VALUE_NUMBER;
88}
89
90
91wxGridCellAttr* PRIVATE_LAYERS_GRID_TABLE::GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind )
92{
93 m_layerColAttr->IncRef();
94 return enhanceAttr( m_layerColAttr, aRow, aCol, aKind );
95}
96
97
98wxString PRIVATE_LAYERS_GRID_TABLE::GetValue( int aRow, int aCol )
99{
100 return m_frame->GetBoard()->GetLayerName( this->at( (size_t) aRow ) );
101}
102
103
105{
106 return this->at( (size_t) aRow );
107}
108
109
110void PRIVATE_LAYERS_GRID_TABLE::SetValue( int aRow, int aCol, const wxString &aValue )
111{
112 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a string value" ), aCol ) );
113}
114
115
116void PRIVATE_LAYERS_GRID_TABLE::SetValueAsLong( int aRow, int aCol, long aValue )
117{
118 this->at( (size_t) aRow ) = ToLAYER_ID( (int) aValue );
119}
120
121
122// Remember the last open page during session.
123
125
126
128 FOOTPRINT* aFootprint ) :
130 m_frame( aParent ),
131 m_footprint( aFootprint ),
132 m_initialized( false ),
133 m_netClearance( aParent, m_NetClearanceLabel, m_NetClearanceCtrl, m_NetClearanceUnits ),
134 m_solderMask( aParent, m_SolderMaskMarginLabel, m_SolderMaskMarginCtrl, m_SolderMaskMarginUnits ),
135 m_solderPaste( aParent, m_SolderPasteMarginLabel, m_SolderPasteMarginCtrl, m_SolderPasteMarginUnits ),
136 m_solderPasteRatio( aParent, m_PasteMarginRatioLabel, m_PasteMarginRatioCtrl, m_PasteMarginRatioUnits ),
137 m_gridSize( 0, 0 ),
138 m_lastRequestedSize( 0, 0 )
139{
140 SetEvtHandlerEnabled( false );
141
142 // Create the extra panels.
145
146 m_NoteBook->AddPage( m_3dPanel, _("3D Models"), false );
147 m_NoteBook->AddPage( m_embeddedFiles, _( "Embedded Files" ) );
148
151
152 m_delayedErrorMessage = wxEmptyString;
153 m_delayedFocusCtrl = nullptr;
154 m_delayedFocusGrid = nullptr;
157 m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_UNKNOWN;
158
159 // Give an icon
160 wxIcon icon;
161 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_modedit ) );
162 SetIcon( icon );
163
166
167 m_itemsGrid->PushEventHandler( new GRID_TRICKS( m_itemsGrid ) );
169 [this]( wxCommandEvent& aEvent )
170 {
171 OnAddLayer( aEvent );
172 } ) );
173 m_nettieGroupsGrid->PushEventHandler( new GRID_TRICKS( m_nettieGroupsGrid,
174 [this]( wxCommandEvent& aEvent )
175 {
176 OnAddNettieGroup( aEvent );
177 } ) );
178 m_jumperGroupsGrid->PushEventHandler( new GRID_TRICKS( m_jumperGroupsGrid,
179 [this]( wxCommandEvent& aEvent )
180 {
181 OnAddJumperGroup( aEvent );
182 } ) );
183
184 m_itemsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
185 m_privateLayersGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
186 m_nettieGroupsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
187 m_jumperGroupsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
188
189 // Show/hide columns according to the user's preference
191
193
194 // Set font sizes
195 wxFont infoFont = KIUI::GetInfoFont( this ).Italic();
196 m_staticTextInfoCopper->SetFont( infoFont );
197 m_staticTextInfoPaste->SetFont( infoFont );
198
199 if( static_cast<int>( m_page ) >= 0 )
200 m_NoteBook->SetSelection( (unsigned) m_page );
201
202 if( m_page == NOTEBOOK_PAGES::PAGE_GENERAL )
203 {
207 m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_GENERAL;
208 }
209 else if( m_page == NOTEBOOK_PAGES::PAGE_CLEARANCES )
210 {
212 }
213
215
216 m_solderPasteRatio.SetUnits( EDA_UNITS::PERCENT );
218
219 // Configure button logos
220 m_bpAdd->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
221 m_bpDelete->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
222 m_bpAddLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
223 m_bpDeleteLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
224 m_bpAddNettieGroup->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
225 m_bpRemoveNettieGroup->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
226 m_bpAddJumperGroup->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
227 m_bpRemoveJumperGroup->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
228
230
232 SetEvtHandlerEnabled( true );
233}
234
235
237{
239
240 // Prevents crash bug in wxGrid's d'tor
243
244 // Delete the GRID_TRICKS.
245 m_itemsGrid->PopEventHandler( true );
246 m_privateLayersGrid->PopEventHandler( true );
247 m_nettieGroupsGrid->PopEventHandler( true );
248 m_jumperGroupsGrid->PopEventHandler( true );
249
250 m_page = static_cast<NOTEBOOK_PAGES>( m_NoteBook->GetSelection() );
251
252 // the GL canvas on the 3D models page has to be visible before it is destroyed
253 m_NoteBook->SetSelection( static_cast<int>( NOTEBOOK_PAGES::PAGE_3D_MODELS ) );
254}
255
256
258{
259 LIB_ID fpID = m_footprint->GetFPID();
260 wxString footprintName = fpID.GetLibItemName();
261
262 m_FootprintNameCtrl->ChangeValue( footprintName );
263
265 m_KeywordCtrl->SetValue( m_footprint->GetKeywords() );
266
267 if( !wxDialog::TransferDataToWindow() )
268 return false;
269
270 if( !m_PanelGeneral->TransferDataToWindow() )
271 return false;
272
273 // Add the models to the panel
275 return false;
276
278 return false;
279
280 // Footprint Fields
281 for( PCB_FIELD* field : m_footprint->GetFields() )
282 m_fields->push_back( *field );
283
284 // Notify the grid
285 wxGridTableMessage tmsg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->GetNumberRows() );
286 m_itemsGrid->ProcessTableMessage( tmsg );
287
289 m_componentType->SetSelection( 0 );
290 else if( m_footprint->GetAttributes() & FP_SMD )
291 m_componentType->SetSelection( 1 );
292 else
293 m_componentType->SetSelection( 2 );
294
295 // Private layers
296 for( PCB_LAYER_ID privateLayer : m_footprint->GetPrivateLayers().UIOrder() )
297 m_privateLayers->push_back( privateLayer );
298
299 // Notify the grid
300 wxGridTableMessage gridTableMessagesg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
302 m_privateLayersGrid->ProcessTableMessage( gridTableMessagesg );
303
307 m_cbDNP->SetValue( m_footprint->GetAttributes() & FP_DNP );
308
309 // Local Clearances
310
311 if( m_footprint->GetLocalClearance().has_value() )
313 else
314 m_netClearance.SetValue( wxEmptyString );
315
316 if( m_footprint->GetLocalSolderMaskMargin().has_value() )
318 else
319 m_solderMask.SetValue( wxEmptyString );
320
321 if( m_footprint->GetLocalSolderPasteMargin().has_value() )
323 else
324 m_solderPaste.SetValue( wxEmptyString );
325
328 else
329 m_solderPasteRatio.SetValue( wxEmptyString );
330
333
335 {
336 default:
337 case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
338 case ZONE_CONNECTION::FULL: m_ZoneConnectionChoice->SetSelection( 1 ); break;
339 case ZONE_CONNECTION::THERMAL: m_ZoneConnectionChoice->SetSelection( 2 ); break;
340 case ZONE_CONNECTION::NONE: m_ZoneConnectionChoice->SetSelection( 3 ); break;
341 }
342
343 for( const wxString& group : m_footprint->GetNetTiePadGroups() )
344 {
345 if( !group.IsEmpty() )
346 {
347 m_nettieGroupsGrid->AppendRows( 1 );
348 m_nettieGroupsGrid->SetCellValue( m_nettieGroupsGrid->GetNumberRows() - 1, 0, group );
349 }
350 }
351
353
354 for( const std::set<wxString>& group : m_footprint->JumperPadGroups() )
355 {
356 wxString groupTxt;
357
358 for( const wxString& pinNumber : group )
359 {
360 if( !groupTxt.IsEmpty() )
361 groupTxt << ", ";
362
363 groupTxt << pinNumber;
364 }
365
366 m_jumperGroupsGrid->AppendRows( 1 );
367 m_jumperGroupsGrid->SetCellValue( m_jumperGroupsGrid->GetNumberRows() - 1, 0, groupTxt );
368 }
369
370 // Items grid
371 for( int col = 0; col < m_itemsGrid->GetNumberCols(); col++ )
372 {
373 // Adjust min size to the column label size
374 m_itemsGrid->SetColMinimalWidth( col, m_itemsGrid->GetVisibleWidth( col, true, false ) );
375 // Adjust the column size.
376 int col_size = m_itemsGrid->GetVisibleWidth( col );
377
378 if( col == PFC_LAYER ) // This one's a drop-down. Check all possible values.
379 {
380 BOARD* board = m_footprint->GetBoard();
381
382 for( PCB_LAYER_ID layer : board->GetEnabledLayers() )
383 col_size = std::max( col_size, GetTextExtent( board->GetLayerName( layer ) ).x );
384
385 // Swatch and gaps:
386 col_size += KiROUND( 14 * GetDPIScaleFactor() ) + 12;
387 }
388
389 if( m_itemsGrid->IsColShown( col ) )
390 m_itemsGrid->SetColSize( col, col_size );
391 }
392
393 m_itemsGrid->SetRowLabelSize( 0 );
394
395 Layout();
397 m_initialized = true;
398
399 return true;
400}
401
402
404 LIB_ID* doOverwrite )
405{
406 if( aFootprintName.IsEmpty() )
407 {
408 m_delayedErrorMessage = _( "Footprint must have a name." );
409 return false;
410 }
411 else if( !FOOTPRINT::IsLibNameValid( aFootprintName ) )
412 {
413 m_delayedErrorMessage.Printf( _( "Footprint name may not contain '%s'." ),
415 return false;
416 }
417
418 LIB_ID fpID = m_footprint->GetFPID();
419 wxString libraryName = fpID.GetLibNickname();
420 wxString originalFPName = fpID.GetLibItemName();
422
423 if( aFootprintName != originalFPName && tbl->FootprintExists( libraryName, aFootprintName ) )
424 {
425 wxString msg = wxString::Format( _( "Footprint '%s' already exists in library '%s'." ),
426 aFootprintName, libraryName );
427
428 KIDIALOG errorDlg( m_frame, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
429 errorDlg.SetOKLabel( _( "Overwrite" ) );
430
431 if( errorDlg.ShowModal() == wxID_OK )
432 {
433 doOverwrite->SetLibNickname( libraryName );
434 doOverwrite->SetLibItemName( aFootprintName );
435 return true;
436 }
437 }
438
439 return true;
440}
441
442
444{
446 return false;
447
448 if( !DIALOG_SHIM::Validate() )
449 return false;
450
451 // First, test for invalid chars in footprint name
452 wxString footprintName = m_FootprintNameCtrl->GetValue();
453 LIB_ID overwrite;
454
455 if( !checkFootprintName( footprintName, &overwrite ) )
456 {
457 if( m_NoteBook->GetSelection() != 0 )
458 m_NoteBook->SetSelection( 0 );
459
461 m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_GENERAL;
462
463 return false;
464 }
465
466 // Check for valid field text properties
467 for( int i = 0; i < (int) m_fields->size(); ++i )
468 {
469 PCB_FIELD& field = m_fields->at( i );
470
471 // Check for missing field names.
472 if( field.GetName( false ).IsEmpty() )
473 {
475 m_delayedErrorMessage = wxString::Format( _( "Fields must have a name." ) );
478
479 return false;
480 }
481
483 int maxSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
484
485 if( field.GetTextWidth() < minSize || field.GetTextWidth() > maxSize )
486 {
488 m_delayedErrorMessage = wxString::Format( _( "The text width must be between %s and %s." ),
490 m_frame->StringFromValue( maxSize, true ) );
493
494 return false;
495 }
496
497 if( field.GetTextHeight() < minSize || field.GetTextHeight() > maxSize )
498 {
500 m_delayedErrorMessage = wxString::Format( _( "The text height must be between %s and %s." ),
502 m_frame->StringFromValue( maxSize, true ) );
505
506 return false;
507 }
508
509 // Test for acceptable values for thickness and size and clamp if fails
510 int maxPenWidth = ClampTextPenSize( field.GetTextThickness(), field.GetTextSize() );
511
512 if( field.GetTextThickness() > maxPenWidth )
513 {
514 m_itemsGrid->SetCellValue( i, PFC_THICKNESS, m_frame->StringFromValue( maxPenWidth, true ) );
515
517 m_delayedErrorMessage = _( "The text thickness is too large for the text size.\n"
518 "It will be clamped." );
521
522 return false;
523 }
524 }
525
526 if( !m_netClearance.Validate( 0, INT_MAX ) )
527 return false;
528
529 if( overwrite.IsValid() )
530 {
531 if( m_frame->DeleteFootprintFromLibrary( overwrite, false /* already confirmed */ ) )
532 m_frame->SyncLibraryTree( true );
533 }
534
535 return true;
536}
537
538
540{
545 {
546 return false;
547 }
548
551 BOARD_COMMIT commit( m_frame );
552 commit.Modify( m_footprint );
553
554 // Must be done inside the commit to capture the undo state
555 // This will call TransferDataToWindow() on the 3D panel and
556 // the embedded files panel.
557 if( !DIALOG_SHIM::TransferDataFromWindow() )
558 return false;
559
560 // Clear out embedded files that are no longer in use
561 std::set<wxString> files;
562 std::set<wxString> files_to_delete;
563
564 // Get the new files from the footprint fields
565 for( const PCB_FIELD& field : *m_fields )
566 {
567 if( field.GetText().StartsWith( FILEEXT::KiCadUriPrefix ) )
568 files.insert( field.GetText() );
569 }
570
571 // Find any files referenced in the old fields that are not in the new fields
572 for( PCB_FIELD* field : m_footprint->GetFields() )
573 {
574 if( field->GetText().StartsWith( FILEEXT::KiCadUriPrefix ) )
575 {
576 if( files.find( field->GetText() ) == files.end() )
577 files_to_delete.insert( field->GetText() );
578 }
579 }
580
581 for( const wxString& file : files_to_delete )
582 {
583 wxString name = file.Mid( FILEEXT::KiCadUriPrefix.size() + 3 ); // Skip "kicad-embed://"
585 }
586
587 LIB_ID fpID = m_footprint->GetFPID();
588 fpID.SetLibItemName( m_FootprintNameCtrl->GetValue() );
589 m_footprint->SetFPID( fpID );
590
592 m_footprint->SetKeywords( m_KeywordCtrl->GetValue() );
593
594 // Update fields
596
597 while( !m_footprint->GetFields().empty() )
598 {
599 PCB_FIELD* existing = m_footprint->GetFields().front();
600 view->Remove( existing );
601 m_footprint->Remove( existing );
602 delete existing;
603 }
604
605 for( PCB_FIELD& field : *m_fields )
606 {
607 PCB_FIELD* newField = field.CloneField();
608 m_footprint->Add( newField );
609 view->Add( newField );
610
611 if( newField->IsSelected() )
612 {
613 // The old copy was in the selection list, but this one is not. Remove the
614 // out-of-sync selection flag so we can re-add the field to the selection.
615 newField->ClearSelected();
616 selectionTool->AddItemToSel( newField, true );
617 }
618 }
619
620 LSET privateLayers;
621
622 for( PCB_LAYER_ID layer : *m_privateLayers )
623 privateLayers.set( layer );
624
625 m_footprint->SetPrivateLayers( privateLayers );
626
627 int attributes = 0;
628
629 switch( m_componentType->GetSelection() )
630 {
631 case 0: attributes |= FP_THROUGH_HOLE; break;
632 case 1: attributes |= FP_SMD; break;
633 default: break;
634 }
635
636 if( m_boardOnly->GetValue() )
637 attributes |= FP_BOARD_ONLY;
638
639 if( m_excludeFromPosFiles->GetValue() )
640 attributes |= FP_EXCLUDE_FROM_POS_FILES;
641
642 if( m_excludeFromBOM->GetValue() )
643 attributes |= FP_EXCLUDE_FROM_BOM;
644
645 if( m_cbDNP->GetValue() )
646 attributes |= FP_DNP;
647
648 m_footprint->SetAttributes( attributes );
649
652
653 // Initialize mask clearances
654 if( m_netClearance.IsNull() )
656 else
658
659 if( m_solderMask.IsNull() )
661 else
663
664 if( m_solderPaste.IsNull() )
666 else
668
671 else
673
674 switch( m_ZoneConnectionChoice->GetSelection() )
675 {
676 default:
677 case 0: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::INHERITED ); break;
678 case 1: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::FULL ); break;
679 case 2: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::THERMAL ); break;
680 case 3: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::NONE ); break;
681 }
682
684
685 for( int ii = 0; ii < m_nettieGroupsGrid->GetNumberRows(); ++ii )
686 {
687 wxString group = m_nettieGroupsGrid->GetCellValue( ii, 0 );
688
689 if( !group.IsEmpty() )
691 }
692
694
695 std::vector<std::set<wxString>>& jumpers = m_footprint->JumperPadGroups();
696 jumpers.clear();
697
698 for( int ii = 0; ii < m_jumperGroupsGrid->GetNumberRows(); ++ii )
699 {
700 wxStringTokenizer tokenizer( m_jumperGroupsGrid->GetCellValue( ii, 0 ), ", " );
701 std::set<wxString>& group = jumpers.emplace_back();
702
703 while( tokenizer.HasMoreTokens() )
704 {
705 if( wxString token = tokenizer.GetNextToken(); !token.IsEmpty() )
706 group.insert( token );
707 }
708 }
709
710 // Copy the models from the panel to the footprint
711 std::vector<FP_3DMODEL>& panelList = m_3dPanel->GetModelList();
712 std::vector<FP_3DMODEL>* fpList = &m_footprint->Models();
713 fpList->clear();
714 fpList->insert( fpList->end(), panelList.begin(), panelList.end() );
715
716 commit.Push( _( "Edit Footprint Properties" ) );
717
718 return true;
719}
720
721
723{
725 [&]() -> std::pair<int, int>
726 {
727 const BOARD_DESIGN_SETTINGS& dsnSettings = m_frame->GetDesignSettings();
728
729 PCB_FIELD newField( m_footprint, FIELD_T::USER, GetUserFieldName( m_fields->size(), DO_TRANSLATE ) );
730
731 // Set active layer if legal; otherwise copy layer from previous text item
733 newField.SetLayer( m_frame->GetActiveLayer() );
734 else
735 newField.SetLayer( m_fields->at( m_fields->size() - 1 ).GetLayer() );
736
737 newField.SetTextSize( dsnSettings.GetTextSize( newField.GetLayer() ) );
738 newField.SetTextThickness( dsnSettings.GetTextThickness( newField.GetLayer() ) );
739 newField.SetItalic( dsnSettings.GetTextItalic( newField.GetLayer() ) );
740
741 m_fields->push_back( newField );
742
743 // notify the grid
744 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
745 m_itemsGrid->ProcessTableMessage( msg );
746 OnModify();
747
748 return { m_fields->size() - 1, PFC_NAME };
749 } );
750}
751
752
754{
756 [&]( int row )
757 {
758 if( row < m_fields->GetMandatoryRowCount() )
759 {
760 DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
762 return false;
763 }
764
765 return true;
766 },
767 [&]( int row )
768 {
769 m_fields->erase( m_fields->begin() + row );
770
771 // notify the grid
772 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 );
773 m_itemsGrid->ProcessTableMessage( msg );
774 } );
775
776 OnModify();
777}
778
779
781{
783 [&]() -> std::pair<int, int>
784 {
785 PCB_LAYER_ID nextLayer = User_1;
786
787 while( alg::contains( *m_privateLayers, nextLayer ) && nextLayer < User_45 )
788 nextLayer = ToLAYER_ID( nextLayer + 1 );
789
790 m_privateLayers->push_back( nextLayer );
791
792 // notify the grid
793 wxGridTableMessage msg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
794 m_privateLayersGrid->ProcessTableMessage( msg );
795 OnModify();
796
797 return { m_privateLayers->size() - 1, 0 };
798 } );
799}
800
801
803{
805 [&]( int row )
806 {
807 m_privateLayers->erase( m_privateLayers->begin() + row );
808
809 // notify the grid
810 wxGridTableMessage msg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 );
811 m_privateLayersGrid->ProcessTableMessage( msg );
812
813 OnModify();
814 } );
815}
816
817
819{
821}
822
823
825{
827}
828
829
831{
833}
834
835
837{
839}
840
841
843{
844 aGrid->OnAddRow(
845 [&]() -> std::pair<int, int>
846 {
847 aGrid->AppendRows( 1 );
848 OnModify();
849
850 return { aGrid->GetNumberRows() - 1, 0 };
851 } );
852}
853
854
856{
857 aGrid->OnDeleteRows(
858 [&]( int row )
859 {
860 aGrid->DeleteRows( row, 1 );
861 } );
862
863 OnModify();
864}
865
866
868{
869 // Account for scroll bars
871
872 itemsWidth -= m_itemsGrid->GetRowLabelSize();
873
874 for( int i = 0; i < m_itemsGrid->GetNumberCols(); i++ )
875 {
876 if( i == 1 )
877 continue;
878
879 itemsWidth -= m_itemsGrid->GetColSize( i );
880 }
881
882 m_itemsGrid->SetColSize( 1, std::max( itemsWidth, m_itemsGrid->GetVisibleWidth( 0, true, false ) ) );
883
884 auto updateSingleColumnGrid =
885 []( WX_GRID* aGrid )
886 {
887 aGrid->SetColSize( 0, std::max( aGrid->GetClientSize().x, aGrid->GetVisibleWidth( 0 ) ) );
888 };
889
890 updateSingleColumnGrid( m_privateLayersGrid );
891 updateSingleColumnGrid( m_nettieGroupsGrid );
892 updateSingleColumnGrid( m_jumperGroupsGrid );
893
894 // Update the width of the 3D panel
896}
897
898
900{
901 // Handle a delayed focus. The delay allows us to:
902 // a) change focus when the error was triggered from within a killFocus handler
903 // b) show the correct notebook page in the background before the error dialog comes up
904 // when triggered from an OK or a notebook page change
905
906 if( static_cast<int>( m_delayedFocusPage ) >= 0 )
907 {
908 if( m_NoteBook->GetSelection() != static_cast<int>( m_delayedFocusPage ) )
909 m_NoteBook->ChangeSelection( static_cast<int>( m_delayedFocusPage ) );
910
911 m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_UNKNOWN;
912 }
913
914 if( !m_delayedErrorMessage.IsEmpty() )
915 {
916 // We will re-enter this routine when the error dialog is displayed, so make
917 // sure we don't keep putting up more dialogs.
918 wxString msg = m_delayedErrorMessage;
919 m_delayedErrorMessage = wxEmptyString;
920
921 // Do not use DisplayErrorMessage(); it screws up window order on Mac
922 DisplayError( nullptr, msg );
923 }
924
926 {
927 m_delayedFocusCtrl->SetFocus();
928
929 if( wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_delayedFocusCtrl ) )
930 textEntry->SelectAll();
931
932 m_delayedFocusCtrl = nullptr;
933 }
934 else if( m_delayedFocusGrid )
935 {
936 m_delayedFocusGrid->SetFocus();
939
940 if( !( m_delayedFocusColumn == 0 && m_delayedFocusRow < m_fields->GetMandatoryRowCount() ) )
941 m_delayedFocusGrid->EnableCellEditControl( true );
942
943 m_delayedFocusGrid->ShowCellEditControl();
944
945 m_delayedFocusGrid = nullptr;
948 }
949}
950
951
953{
954 wxSize new_size = aEvent.GetSize();
955
956 if( ( !m_itemsGrid->IsCellEditControlShown() || m_lastRequestedSize != new_size )
957 && m_gridSize != new_size )
958 {
959 m_gridSize = new_size;
960
961 // A trick to fix a cosmetic issue: when, in m_itemsGrid, a layer selector widget has
962 // the focus (is activated in column 6) when resizing the grid, the widget is not moved.
963 // So just change the widget having the focus in this case
964 if( m_NoteBook->GetSelection() == 0 && !m_itemsGrid->HasFocus() )
965 {
966 int col = m_itemsGrid->GetGridCursorCol();
967
968 if( col == 6 ) // a layer selector widget can be activated
969 m_itemsGrid->SetFocus();
970 }
971
973 }
974
975 // We store this value to check whether the dialog is changing size. This might indicate
976 // that the user is scaling the dialog with an editor shown. Some editors do not close
977 // (at least on GTK) when the user drags a dialog corner
978 m_lastRequestedSize = new_size;
979
980 // Always propagate for a grid repaint (needed if the height changes, as well as width)
981 aEvent.Skip();
982}
983
984
986{
988 aEvent.Veto();
989
991 aEvent.Veto();
992}
993
994
996{
997 if( m_initialized )
998 OnModify();
999}
1000
1001
1003{
1004 if( m_initialized )
1005 OnModify();
1006}
1007
1008
1010{
1011 if( m_initialized )
1012 OnModify();
1013}
1014
1015
const char * name
Definition: DXF_plotter.cpp:62
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:112
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:104
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition: bitmap.cpp:110
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: actions.h:221
BASE_SET & set(size_t pos)
Definition: base_set.h:116
Container for design settings for a BOARD object.
int GetTextThickness(PCB_LAYER_ID aLayer) const
Return the default text thickness from the layer class for the given layer.
bool GetTextItalic(PCB_LAYER_ID aLayer) const
VECTOR2I GetTextSize(PCB_LAYER_ID aLayer) const
Return the default text size from the layer class for the given layer.
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:232
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:280
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:79
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:317
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:680
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:907
Class DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE.
DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR(FOOTPRINT_EDIT_FRAME *aParent, FOOTPRINT *aFootprint)
bool checkFootprintName(const wxString &aFootprintName, LIB_ID *doOverwrite)
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={})
void OnModify()
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
void ClearSelected()
Definition: eda_item.h:137
bool IsSelected() const
Definition: eda_item.h:127
int GetTextHeight() const
Definition: eda_text.h:264
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition: eda_text.cpp:533
int GetTextWidth() const
Definition: eda_text.h:261
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:284
int GetTextThickness() const
Definition: eda_text.h:125
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
Definition: eda_text.cpp:307
VECTOR2I GetTextSize() const
Definition: eda_text.h:258
void RemoveFile(const wxString &name, bool aErase=true)
Remove a file from the collection and frees the memory.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const override
Return the BOARD_DESIGN_SETTINGS for the open project.
void SyncLibraryTree(bool aProgress)
Synchronize the footprint library tree to the current state of the footprint library table.
bool DeleteFootprintFromLibrary(const LIB_ID &aFPID, bool aConfirm)
Delete the given footprint from its library.
FOOTPRINT_EDITOR_SETTINGS * GetSettings()
Provide a custom wxValidator object for limiting the allowable characters when defining footprint nam...
Definition: validators.h:53
bool GetDuplicatePadNumbersAreJumpers() const
Definition: footprint.h:817
bool AllowSolderMaskBridges() const
Definition: footprint.h:299
void SetFPID(const LIB_ID &aFPID)
Definition: footprint.h:252
wxString GetLibDescription() const
Definition: footprint.h:260
ZONE_CONNECTION GetLocalZoneConnection() const
Definition: footprint.h:291
void Remove(BOARD_ITEM *aItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition: footprint.cpp:1149
void SetAllowSolderMaskBridges(bool aAllow)
Definition: footprint.h:300
static bool IsLibNameValid(const wxString &aName)
Test for validity of a name of a footprint to be used in a footprint library ( no spaces,...
Definition: footprint.cpp:2384
void SetLocalSolderPasteMarginRatio(std::optional< double > aRatio)
Definition: footprint.h:288
void SetKeywords(const wxString &aKeywords)
Definition: footprint.h:264
void SetAttributes(int aAttributes)
Definition: footprint.h:294
std::optional< int > GetLocalSolderPasteMargin() const
Definition: footprint.h:284
std::optional< int > GetLocalClearance() const
Definition: footprint.h:278
std::vector< std::set< wxString > > & JumperPadGroups()
Each jumper pad group is a set of pad numbers that should be treated as internally connected.
Definition: footprint.h:824
void SetDuplicatePadNumbersAreJumpers(bool aEnabled)
Definition: footprint.h:818
int GetAttributes() const
Definition: footprint.h:293
void SetLocalZoneConnection(ZONE_CONNECTION aType)
Definition: footprint.h:290
void ClearNetTiePadGroups()
Definition: footprint.h:350
LSET GetPrivateLayers() const
Definition: footprint.h:149
bool AllowMissingCourtyard() const
Definition: footprint.h:296
const std::vector< wxString > & GetNetTiePadGroups() const
Definition: footprint.h:348
const LIB_ID & GetFPID() const
Definition: footprint.h:251
void AddNetTiePadGroup(const wxString &aGroup)
Definition: footprint.h:355
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: footprint.cpp:1080
std::optional< double > GetLocalSolderPasteMarginRatio() const
Definition: footprint.h:287
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly) const
Populate a std::vector with PCB_TEXTs.
Definition: footprint.cpp:638
void SetAllowMissingCourtyard(bool aAllow)
Definition: footprint.h:297
std::vector< FP_3DMODEL > & Models()
Definition: footprint.h:223
static const wxChar * StringLibNameInvalidChars(bool aUserReadable)
Test for validity of the name in a library of the footprint ( no spaces, dir separators ....
Definition: footprint.cpp:2395
void SetLibDescription(const wxString &aDesc)
Definition: footprint.h:261
void SetLocalSolderMaskMargin(std::optional< int > aMargin)
Definition: footprint.h:282
void SetLocalClearance(std::optional< int > aClearance)
Definition: footprint.h:279
void SetPrivateLayers(const LSET &aLayers)
Adds an item to the container.
Definition: footprint.h:150
std::optional< int > GetLocalSolderMaskMargin() const
Definition: footprint.h:281
void SetLocalSolderPasteMargin(std::optional< int > aMargin)
Definition: footprint.h:285
wxString GetKeywords() const
Definition: footprint.h:263
bool FootprintExists(const wxString &aNickname, const wxString &aFootprintName)
Indicates whether or not the given footprint already exists in the given library.
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition: grid_tricks.h:61
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: kidialog.h:50
int ShowModal() override
Definition: kidialog.cpp:95
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1) override
Add a VIEW_ITEM to the view.
Definition: pcb_view.cpp:57
virtual void Remove(VIEW_ITEM *aItem) override
Remove a VIEW_ITEM from the view.
Definition: pcb_view.cpp:74
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
int SetLibItemName(const UTF8 &aLibItemName)
Override the library item name portion of the LIB_ID to aLibItemName.
Definition: lib_id.cpp:111
bool IsValid() const
Check if this LID_ID is valid.
Definition: lib_id.h:172
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition: lib_id.cpp:100
const UTF8 & GetLibItemName() const
Definition: lib_id.h:102
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:87
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:37
LSEQ UIOrder() const
Return the copper, technical and user layers in the order shown in layer widget.
Definition: lset.cpp:733
static const LSET & AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
Definition: lset.cpp:659
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition: lset.cpp:591
EMBEDDED_FILES * GetLocalFiles()
bool TransferDataToWindow() override
std::vector< FP_3DMODEL > & GetModelList()
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
virtual PCB_LAYER_ID GetActiveLayer() const
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
BOARD * GetBoard() const
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: pcb_field.cpp:106
PCB_FIELD * CloneField() const
Same as Clone, but returns a PCB_FIELD item.
Definition: pcb_field.h:92
The selection tool: currently supports:
wxString GetValue(int aRow, int aCol) override
bool CanGetValueAs(int aRow, int aCol, const wxString &aTypeName) override
long GetValueAsLong(int aRow, int aCol) override
bool CanSetValueAs(int aRow, int aCol, const wxString &aTypeName) override
wxGridCellAttr * GetAttr(int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind) override
void SetValue(int aRow, int aCol, const wxString &aValue) override
void SetValueAsLong(int aRow, int aCol, long aValue) override
static FP_LIB_TABLE * PcbFootprintLibs(PROJECT *aProject)
Return the table of footprint libraries without Kiway.
Definition: project_pcb.cpp:37
int AddItemToSel(const TOOL_EVENT &aEvent)
void SetBitmap(const wxBitmapBundle &aBmp)
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:150
wxString StringFromValue(double aValue, bool aAddUnitLabel=false, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
Converts aValue in internal units into a united string.
virtual long long int GetValue()
Return the current value in Internal Units.
virtual void SetUnits(EDA_UNITS aUnits)
Normally not needed (as the UNIT_BINDER inherits from the parent frame), but can be used to set to DE...
virtual void SetNegativeZero()
Definition: unit_binder.h:78
virtual double GetDoubleValue()
Return the current value in Internal Units.
virtual void SetDoubleValue(double aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
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.
bool IsNull() const
Return true if the control holds no value (ie: empty string, not 0).
wxGridCellAttr * enhanceAttr(wxGridCellAttr *aInputAttr, int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind)
Definition: wx_grid.cpp:45
int GetVisibleWidth(int aCol, bool aHeader=true, bool aContents=true, bool aKeep=false)
Calculate the specified column based on the actual size of the text on screen.
Definition: wx_grid.cpp:916
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 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
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:632
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.
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:46
#define TEXT_MAX_SIZE_MM
Maximum text size in mm (~10 inches)
Definition: eda_text.h:47
@ FP_SMD
Definition: footprint.h:81
@ FP_DNP
Definition: footprint.h:86
@ FP_EXCLUDE_FROM_POS_FILES
Definition: footprint.h:82
@ FP_BOARD_ONLY
Definition: footprint.h:84
@ FP_EXCLUDE_FROM_BOM
Definition: footprint.h:83
@ FP_THROUGH_HOLE
Definition: footprint.h:80
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:72
static const std::string KiCadUriPrefix
This file is part of the common library.
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ User_45
Definition: layer_ids.h:168
@ Edge_Cuts
Definition: layer_ids.h:112
@ Margin
Definition: layer_ids.h:113
@ User_1
Definition: layer_ids.h:124
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:744
wxSize GetUnobscuredSize(const wxWindow *aWindow)
Tries to determine the size of the viewport of a scrollable widget (wxDataViewCtrl,...
Definition: wxgtk/ui.cpp:258
KICOMMON_API wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:156
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:100
@ PFC_HEIGHT
@ PFC_THICKNESS
see class PGM_BASE
wxString UnescapeString(const wxString &aSource)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_LINE
Definition: string_utils.h:59
constexpr int mmToIU(double mm) const
Definition: base_units.h:92
wxString GetUserFieldName(int aFieldNdx, bool aTranslateForHI)
#define DO_TRANSLATE
Custom text control validator definitions.