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,
92 wxGridCellAttr::wxAttrKind aKind )
93{
94 m_layerColAttr->IncRef();
95 return enhanceAttr( m_layerColAttr, aRow, aCol, aKind );
96}
97
98
99wxString PRIVATE_LAYERS_GRID_TABLE::GetValue( int aRow, int aCol )
100{
101 return m_frame->GetBoard()->GetLayerName( this->at( (size_t) aRow ) );
102}
103
104
106{
107 return this->at( (size_t) aRow );
108}
109
110
111void PRIVATE_LAYERS_GRID_TABLE::SetValue( int aRow, int aCol, const wxString &aValue )
112{
113 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a string value" ), aCol ) );
114}
115
116
117void PRIVATE_LAYERS_GRID_TABLE::SetValueAsLong( int aRow, int aCol, long aValue )
118{
119 this->at( (size_t) aRow ) = ToLAYER_ID( (int) aValue );
120}
121
122
123// Remember the last open page during session.
124
126
127
129 FOOTPRINT_EDIT_FRAME* aParent,
130 FOOTPRINT* aFootprint ) :
132 m_frame( aParent ),
133 m_footprint( aFootprint ),
134 m_initialized( false ),
135 m_netClearance( aParent, m_NetClearanceLabel, m_NetClearanceCtrl, m_NetClearanceUnits ),
136 m_solderMask( aParent, m_SolderMaskMarginLabel, m_SolderMaskMarginCtrl,
137 m_SolderMaskMarginUnits ),
138 m_solderPaste( aParent, m_SolderPasteMarginLabel, m_SolderPasteMarginCtrl,
139 m_SolderPasteMarginUnits ),
140 m_solderPasteRatio( aParent, m_PasteMarginRatioLabel, m_PasteMarginRatioCtrl,
141 m_PasteMarginRatioUnits ),
142 m_gridSize( 0, 0 ),
143 m_lastRequestedSize( 0, 0 )
144{
145 SetEvtHandlerEnabled( false );
146
147 // Create the extra panels.
150
151 m_NoteBook->AddPage( m_3dPanel, _("3D Models"), false );
152 m_NoteBook->AddPage( m_embeddedFiles, _( "Embedded Files" ) );
153
156
157 m_delayedErrorMessage = wxEmptyString;
158 m_delayedFocusCtrl = nullptr;
159 m_delayedFocusGrid = nullptr;
162 m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_UNKNOWN;
163
164 // Give an icon
165 wxIcon icon;
166 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_modedit ) );
167 SetIcon( icon );
168
169 // Give a bit more room for combobox editors
170 m_itemsGrid->SetDefaultRowSize( m_itemsGrid->GetDefaultRowSize() + 4 );
171 m_privateLayersGrid->SetDefaultRowSize( m_privateLayersGrid->GetDefaultRowSize() + 4 );
172
175
176 m_itemsGrid->PushEventHandler( new GRID_TRICKS( m_itemsGrid ) );
178 [this]( wxCommandEvent& aEvent )
179 {
180 OnAddLayer( aEvent );
181 } ) );
182 m_padGroupsGrid->PushEventHandler( new GRID_TRICKS( m_padGroupsGrid,
183 [this]( wxCommandEvent& aEvent )
184 {
185 OnAddPadGroup( aEvent );
186 } ) );
187
188 m_itemsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
189 m_privateLayersGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
190 m_padGroupsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
191
192 // Show/hide columns according to the user's preference
194
196
197 // Set font sizes
198 wxFont infoFont = KIUI::GetInfoFont( this );
199 infoFont.SetStyle( wxFONTSTYLE_ITALIC );
200 m_staticTextInfoCopper->SetFont( infoFont );
201 m_staticTextInfoPaste->SetFont( infoFont );
202
203 if( static_cast<int>( m_page ) >= 0 )
204 m_NoteBook->SetSelection( (unsigned) m_page );
205
206 if( m_page == NOTEBOOK_PAGES::PAGE_GENERAL )
207 {
211 m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_GENERAL;
212 }
213 else if( m_page == NOTEBOOK_PAGES::PAGE_CLEARANCES )
214 {
216 }
217
219
220 m_solderPasteRatio.SetUnits( EDA_UNITS::PERCENT );
222
223 // Configure button logos
224 m_bpAdd->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
225 m_bpDelete->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
226 m_bpAddLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
227 m_bpDeleteLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
228 m_bpAddPadGroup->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
229 m_bpRemovePadGroup->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
230
232
234 SetEvtHandlerEnabled( true );
235}
236
237
239{
241
242 // Prevents crash bug in wxGrid's d'tor
245
246 // Delete the GRID_TRICKS.
247 m_itemsGrid->PopEventHandler( true );
248 m_privateLayersGrid->PopEventHandler( true );
249 m_padGroupsGrid->PopEventHandler( true );
250
251 m_page = static_cast<NOTEBOOK_PAGES>( m_NoteBook->GetSelection() );
252
253 // the GL canvas on the 3D models page has to be visible before it is destroyed
254 m_NoteBook->SetSelection( static_cast<int>( NOTEBOOK_PAGES::PAGE_3D_MODELS ) );
255}
256
257
259{
260 LIB_ID fpID = m_footprint->GetFPID();
261 wxString footprintName = fpID.GetLibItemName();
262
263 m_FootprintNameCtrl->ChangeValue( footprintName );
264
266 m_KeywordCtrl->SetValue( m_footprint->GetKeywords() );
267
268 if( !wxDialog::TransferDataToWindow() )
269 return false;
270
271 if( !m_PanelGeneral->TransferDataToWindow() )
272 return false;
273
274 // Add the models to the panel
276 return false;
277
279 return false;
280
281 // Footprint Fields
282 for( PCB_FIELD* field : m_footprint->GetFields() )
283 m_fields->push_back( *field );
284
285 // Notify the grid
286 wxGridTableMessage tmsg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
288 m_itemsGrid->ProcessTableMessage( tmsg );
289
291 m_componentType->SetSelection( 0 );
292 else if( m_footprint->GetAttributes() & FP_SMD )
293 m_componentType->SetSelection( 1 );
294 else
295 m_componentType->SetSelection( 2 );
296
297 // Private layers
298 for( PCB_LAYER_ID privateLayer : m_footprint->GetPrivateLayers().UIOrder() )
299 m_privateLayers->push_back( privateLayer );
300
301 // Notify the grid
302 wxGridTableMessage gridTableMessagesg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
304 m_privateLayersGrid->ProcessTableMessage( gridTableMessagesg );
305
310 m_cbDNP->SetValue( m_footprint->GetAttributes() & FP_DNP );
311
312 // Local Clearances
313
314 if( m_footprint->GetLocalClearance().has_value() )
316 else
317 m_netClearance.SetValue( wxEmptyString );
318
319 if( m_footprint->GetLocalSolderMaskMargin().has_value() )
321 else
322 m_solderMask.SetValue( wxEmptyString );
323
324 if( m_footprint->GetLocalSolderPasteMargin().has_value() )
326 else
327 m_solderPaste.SetValue( wxEmptyString );
328
331 else
332 m_solderPasteRatio.SetValue( wxEmptyString );
333
335
337 {
338 default:
339 case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
340 case ZONE_CONNECTION::FULL: m_ZoneConnectionChoice->SetSelection( 1 ); break;
341 case ZONE_CONNECTION::THERMAL: m_ZoneConnectionChoice->SetSelection( 2 ); break;
342 case ZONE_CONNECTION::NONE: m_ZoneConnectionChoice->SetSelection( 3 ); break;
343 }
344
345 for( const wxString& group : m_footprint->GetNetTiePadGroups() )
346 {
347 if( !group.IsEmpty() )
348 {
349 m_padGroupsGrid->AppendRows( 1 );
350 m_padGroupsGrid->SetCellValue( m_padGroupsGrid->GetNumberRows() - 1, 0, group );
351 }
352 }
353
354 // Items grid
355 for( int col = 0; col < m_itemsGrid->GetNumberCols(); col++ )
356 {
357 // Adjust min size to the column label size
358 m_itemsGrid->SetColMinimalWidth( col, m_itemsGrid->GetVisibleWidth( col, true, false ) );
359 // Adjust the column size.
360 int col_size = m_itemsGrid->GetVisibleWidth( col );
361
362 if( col == PFC_LAYER ) // This one's a drop-down. Check all possible values.
363 {
364 BOARD* board = m_footprint->GetBoard();
365
366 for( PCB_LAYER_ID layer : board->GetEnabledLayers().Seq() )
367 col_size = std::max( col_size, GetTextExtent( board->GetLayerName( layer ) ).x );
368
369 // Swatch and gaps:
370 col_size += KiROUND( 14 * GetDPIScaleFactor() ) + 12;
371 }
372
373 if( m_itemsGrid->IsColShown( col ) )
374 m_itemsGrid->SetColSize( col, col_size );
375 }
376
377 m_itemsGrid->SetRowLabelSize( 0 );
378
379 Layout();
381 m_initialized = true;
382
383 return true;
384}
385
386
388 LIB_ID* doOverwrite )
389{
390 if( aFootprintName.IsEmpty() )
391 {
392 m_delayedErrorMessage = _( "Footprint must have a name." );
393 return false;
394 }
395 else if( !FOOTPRINT::IsLibNameValid( aFootprintName ) )
396 {
397 m_delayedErrorMessage.Printf( _( "Footprint name may not contain '%s'." ),
399 return false;
400 }
401
402 LIB_ID fpID = m_footprint->GetFPID();
403 wxString libraryName = fpID.GetLibNickname();
404 wxString originalFPName = fpID.GetLibItemName();
406
407 if( aFootprintName != originalFPName && tbl->FootprintExists( libraryName, aFootprintName ) )
408 {
409 wxString msg = wxString::Format( _( "Footprint '%s' already exists in library '%s'." ),
410 aFootprintName, libraryName );
411
412 KIDIALOG errorDlg( m_frame, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
413 errorDlg.SetOKLabel( _( "Overwrite" ) );
414
415 if( errorDlg.ShowModal() == wxID_OK )
416 {
417 doOverwrite->SetLibNickname( libraryName );
418 doOverwrite->SetLibItemName( aFootprintName );
419 return true;
420 }
421 }
422
423 return true;
424}
425
426
428{
430 return false;
431
432 if( !DIALOG_SHIM::Validate() )
433 return false;
434
435 // First, test for invalid chars in footprint name
436 wxString footprintName = m_FootprintNameCtrl->GetValue();
437 LIB_ID overwrite;
438
439 if( !checkFootprintName( footprintName, &overwrite ) )
440 {
441 if( m_NoteBook->GetSelection() != 0 )
442 m_NoteBook->SetSelection( 0 );
443
445 m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_GENERAL;
446
447 return false;
448 }
449
450 // Check for valid field text properties
451 for( int i = 0; i < (int) m_fields->size(); ++i )
452 {
453 PCB_FIELD& field = m_fields->at( i );
454
455 // Check for missing field names.
456 if( field.GetName( false ).IsEmpty() )
457 {
459 m_delayedErrorMessage = wxString::Format( _( "Fields must have a name." ) );
462
463 return false;
464 }
465
467 int maxSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
468
469 if( field.GetTextWidth() < minSize || field.GetTextWidth() > maxSize )
470 {
472 m_delayedErrorMessage = wxString::Format( _( "The text width must be between %s and %s." ),
474 m_frame->StringFromValue( maxSize, true ) );
477
478 return false;
479 }
480
481 if( field.GetTextHeight() < minSize || field.GetTextHeight() > maxSize )
482 {
484 m_delayedErrorMessage = wxString::Format( _( "The text height must be between %s and %s." ),
486 m_frame->StringFromValue( maxSize, true ) );
489
490 return false;
491 }
492
493 // Test for acceptable values for thickness and size and clamp if fails
494 int maxPenWidth = ClampTextPenSize( field.GetTextThickness(), field.GetTextSize() );
495
496 if( field.GetTextThickness() > maxPenWidth )
497 {
498 m_itemsGrid->SetCellValue( i, PFC_THICKNESS,
499 m_frame->StringFromValue( maxPenWidth, true ) );
500
502 m_delayedErrorMessage = _( "The text thickness is too large for the text size.\n"
503 "It will be clamped." );
506
507 return false;
508 }
509 }
510
511 if( !m_netClearance.Validate( 0, INT_MAX ) )
512 return false;
513
514 if( overwrite.IsValid() )
515 {
516 if( m_frame->DeleteFootprintFromLibrary( overwrite, false /* already confirmed */ ) )
517 m_frame->SyncLibraryTree( true );
518 }
519
520 return true;
521}
522
523
525{
529 {
530 return false;
531 }
532
534 BOARD_COMMIT commit( m_frame );
535 commit.Modify( m_footprint );
536
537 // Must be done inside the commit to capture the undo state
538 // This will call TransferDataToWindow() on the 3D panel and
539 // the embedded files panel.
540 if( !DIALOG_SHIM::TransferDataFromWindow() )
541 return false;
542
543 // Clear out embedded files that are no longer in use
544 std::set<wxString> files;
545 std::set<wxString> files_to_delete;
546
547 // Get the new files from the footprint fields
548 for( const PCB_FIELD& field : *m_fields )
549 {
550 if( field.GetText().StartsWith( FILEEXT::KiCadUriPrefix ) )
551 files.insert( field.GetText() );
552 }
553
554 // Find any files referenced in the old fields that are not in the new fields
555 for( PCB_FIELD* field : m_footprint->GetFields() )
556 {
557 if( field->GetText().StartsWith( FILEEXT::KiCadUriPrefix ) )
558 {
559 if( files.find( field->GetText() ) == files.end() )
560 files_to_delete.insert( field->GetText() );
561 }
562 }
563
564 for( const wxString& file : files_to_delete )
565 {
566 wxString name = file.Mid( FILEEXT::KiCadUriPrefix.size() + 3 ); // Skip "kicad-embed://"
568 }
569
570 LIB_ID fpID = m_footprint->GetFPID();
571 fpID.SetLibItemName( m_FootprintNameCtrl->GetValue() );
572 m_footprint->SetFPID( fpID );
573
575 m_footprint->SetKeywords( m_KeywordCtrl->GetValue() );
576
577 // Update fields
579
580 for( PCB_FIELD* existing : m_footprint->GetFields() )
581 {
582 m_footprint->Remove( existing );
583 view->Remove( existing );
584 delete existing;
585 }
586
587 for( PCB_FIELD& field : *m_fields )
588 {
589 PCB_FIELD* newField = field.CloneField();
590 m_footprint->Add( newField );
591 view->Add( newField );
592 }
593
594 LSET privateLayers;
595
596 for( PCB_LAYER_ID layer : *m_privateLayers )
597 privateLayers.set( layer );
598
599 m_footprint->SetPrivateLayers( privateLayers );
600
601 int attributes = 0;
602
603 switch( m_componentType->GetSelection() )
604 {
605 case 0: attributes |= FP_THROUGH_HOLE; break;
606 case 1: attributes |= FP_SMD; break;
607 default: break;
608 }
609
610 if( m_boardOnly->GetValue() )
611 attributes |= FP_BOARD_ONLY;
612
613 if( m_excludeFromPosFiles->GetValue() )
614 attributes |= FP_EXCLUDE_FROM_POS_FILES;
615
616 if( m_excludeFromBOM->GetValue() )
617 attributes |= FP_EXCLUDE_FROM_BOM;
618
619 if( m_noCourtyards->GetValue() )
620 attributes |= FP_ALLOW_MISSING_COURTYARD;
621
622 if( m_cbDNP->GetValue() )
623 attributes |= FP_DNP;
624
625 if( m_allowBridges->GetValue() )
626 attributes |= FP_ALLOW_SOLDERMASK_BRIDGES;
627
628 m_footprint->SetAttributes( attributes );
629
630 // Initialize mask clearances
631 if( m_netClearance.IsNull() )
633 else
635
636 if( m_solderMask.IsNull() )
638 else
640
641 if( m_solderPaste.IsNull() )
643 else
645
648 else
650
651 switch( m_ZoneConnectionChoice->GetSelection() )
652 {
653 default:
654 case 0: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::INHERITED ); break;
655 case 1: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::FULL ); break;
656 case 2: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::THERMAL ); break;
657 case 3: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::NONE ); break;
658 }
659
661
662 for( int ii = 0; ii < m_padGroupsGrid->GetNumberRows(); ++ii )
663 {
664 wxString group = m_padGroupsGrid->GetCellValue( ii, 0 );
665
666 if( !group.IsEmpty() )
668 }
669
670 // Copy the models from the panel to the footprint
671 std::vector<FP_3DMODEL>& panelList = m_3dPanel->GetModelList();
672 std::vector<FP_3DMODEL>* fpList = &m_footprint->Models();
673 fpList->clear();
674 fpList->insert( fpList->end(), panelList.begin(), panelList.end() );
675
676 commit.Push( _( "Edit Footprint Properties" ) );
677
678 return true;
679}
680
681
683{
685 return;
686
687 const BOARD_DESIGN_SETTINGS& dsnSettings = m_frame->GetDesignSettings();
688
689 PCB_FIELD newField( m_footprint, FIELD_T::USER,
691
692 // Set active layer if legal; otherwise copy layer from previous text item
694 newField.SetLayer( m_frame->GetActiveLayer() );
695 else
696 newField.SetLayer( m_fields->at( m_fields->size() - 1 ).GetLayer() );
697
698 newField.SetTextSize( dsnSettings.GetTextSize( newField.GetLayer() ) );
699 newField.SetTextThickness( dsnSettings.GetTextThickness( newField.GetLayer() ) );
700 newField.SetItalic( dsnSettings.GetTextItalic( newField.GetLayer() ) );
701
702 m_fields->push_back( newField );
703
704 // notify the grid
705 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
706 m_itemsGrid->ProcessTableMessage( msg );
707
708 m_itemsGrid->SetFocus();
709 m_itemsGrid->MakeCellVisible( (int) m_fields->size() - 1, 0 );
710 m_itemsGrid->SetGridCursor( (int) m_fields->size() - 1, 0 );
711
712 m_itemsGrid->EnableCellEditControl( true );
713 m_itemsGrid->ShowCellEditControl();
714
715 OnModify();
716}
717
718
720{
722 return;
723
724 wxArrayInt selectedRows = m_itemsGrid->GetSelectedRows();
725
726 if( selectedRows.empty() && m_itemsGrid->GetGridCursorRow() >= 0 )
727 selectedRows.push_back( m_itemsGrid->GetGridCursorRow() );
728
729 if( selectedRows.empty() )
730 return;
731
732 for( int row : selectedRows )
733 {
734 if( row < m_fields->GetMandatoryRowCount() )
735 {
736 DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
738 return;
739 }
740 }
741
742 m_itemsGrid->CommitPendingChanges( true /* quiet mode */ );
743 m_itemsGrid->ClearSelection();
744
745 // Reverse sort so deleting a row doesn't change the indexes of the other rows.
746 selectedRows.Sort( []( int* first, int* second )
747 {
748 return *second - *first;
749 } );
750
751 for( int row : selectedRows )
752 {
753 m_fields->erase( m_fields->begin() + row );
754
755 // notify the grid
756 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 );
757 m_itemsGrid->ProcessTableMessage( msg );
758
759 if( m_itemsGrid->GetNumberRows() > 0 )
760 {
761 m_itemsGrid->MakeCellVisible( std::max( 0, row-1 ), m_itemsGrid->GetGridCursorCol() );
762 m_itemsGrid->SetGridCursor( std::max( 0, row-1 ), m_itemsGrid->GetGridCursorCol() );
763 }
764 }
765
766 OnModify();
767}
768
769
771{
773 return;
774
775 PCB_LAYER_ID nextLayer = User_1;
776
777 while( alg::contains( *m_privateLayers, nextLayer ) && nextLayer < User_45 )
778 nextLayer = ToLAYER_ID( nextLayer + 1 );
779
780 m_privateLayers->push_back( nextLayer );
781
782 // notify the grid
783 wxGridTableMessage msg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
784 m_privateLayersGrid->ProcessTableMessage( msg );
785
786 m_privateLayersGrid->SetFocus();
787 m_privateLayersGrid->MakeCellVisible( (int) m_privateLayers->size() - 1, 0 );
788 m_privateLayersGrid->SetGridCursor( (int) m_privateLayers->size() - 1, 0 );
789
790 OnModify();
791}
792
793
795{
797 return;
798
799 int curRow = m_privateLayersGrid->GetGridCursorRow();
800
801 if( curRow < 0 )
802 return;
803
804 m_privateLayers->erase( m_privateLayers->begin() + curRow );
805
806 // notify the grid
807 wxGridTableMessage msg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_DELETED, curRow, 1 );
808 m_privateLayersGrid->ProcessTableMessage( msg );
809
810 if( m_privateLayersGrid->GetNumberRows() > 0 )
811 {
812 m_privateLayersGrid->MakeCellVisible( std::max( 0, curRow-1 ),
813 m_privateLayersGrid->GetGridCursorCol() );
814 m_privateLayersGrid->SetGridCursor( std::max( 0, curRow-1 ),
815 m_privateLayersGrid->GetGridCursorCol() );
816 }
817
818 OnModify();
819}
820
821
823{
825 return;
826
827 m_padGroupsGrid->AppendRows( 1 );
828
829 m_padGroupsGrid->SetFocus();
830 m_padGroupsGrid->MakeCellVisible( m_padGroupsGrid->GetNumberRows() - 1, 0 );
831 m_padGroupsGrid->SetGridCursor( m_padGroupsGrid->GetNumberRows() - 1, 0 );
832
833 m_padGroupsGrid->EnableCellEditControl( true );
834 m_padGroupsGrid->ShowCellEditControl();
835
836 OnModify();
837}
838
839
841{
843 return;
844
845 wxArrayInt selectedRows = m_padGroupsGrid->GetSelectedRows();
846 int curRow = m_padGroupsGrid->GetGridCursorRow();
847
848 if( selectedRows.empty() && curRow >= 0 && curRow < m_padGroupsGrid->GetNumberRows() )
849 selectedRows.Add( curRow );
850
851 for( int ii = (int) selectedRows.Count() - 1; ii >= 0; --ii )
852 {
853 int row = selectedRows.Item( ii );
854 m_padGroupsGrid->DeleteRows( row, 1 );
855 curRow = std::min( curRow, row );
856 }
857
858 curRow = std::max( 0, curRow - 1 );
859 m_padGroupsGrid->MakeCellVisible( curRow, m_padGroupsGrid->GetGridCursorCol() );
860 m_padGroupsGrid->SetGridCursor( curRow, m_padGroupsGrid->GetGridCursorCol() );
861
862 OnModify();
863}
864
865
867{
868 // Account for scroll bars
870
871 itemsWidth -= m_itemsGrid->GetRowLabelSize();
872
873 for( int i = 0; i < m_itemsGrid->GetNumberCols(); i++ )
874 {
875 if( i == 1 )
876 continue;
877
878 itemsWidth -= m_itemsGrid->GetColSize( i );
879 }
880
881 m_itemsGrid->SetColSize(
882 1, std::max( itemsWidth, m_itemsGrid->GetVisibleWidth( 0, true, false ) ) );
883
884 // Update the width private layers grid
885 m_privateLayersGrid->SetColSize( 0, std::max( m_privateLayersGrid->GetClientSize().x,
887
888 // Update the width net tie pad groups grid
889 m_padGroupsGrid->SetColSize( 0, std::max( m_padGroupsGrid->GetClientSize().x,
891
892 // Update the width of the 3D panel
894}
895
896
898{
899 // Handle a delayed focus. The delay allows us to:
900 // a) change focus when the error was triggered from within a killFocus handler
901 // b) show the correct notebook page in the background before the error dialog comes up
902 // when triggered from an OK or a notebook page change
903
904 if( static_cast<int>( m_delayedFocusPage ) >= 0 )
905 {
906 if( m_NoteBook->GetSelection() != static_cast<int>( m_delayedFocusPage ) )
907 m_NoteBook->ChangeSelection( static_cast<int>( m_delayedFocusPage ) );
908
909 m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_UNKNOWN;
910 }
911
912 if( !m_delayedErrorMessage.IsEmpty() )
913 {
914 // We will re-enter this routine when the error dialog is displayed, so make
915 // sure we don't keep putting up more dialogs.
916 wxString msg = m_delayedErrorMessage;
917 m_delayedErrorMessage = wxEmptyString;
918
919 // Do not use DisplayErrorMessage(); it screws up window order on Mac
920 DisplayError( nullptr, msg );
921 }
922
924 {
925 m_delayedFocusCtrl->SetFocus();
926
927 if( wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_delayedFocusCtrl ) )
928 textEntry->SelectAll();
929
930 m_delayedFocusCtrl = nullptr;
931 }
932 else if( m_delayedFocusGrid )
933 {
934 m_delayedFocusGrid->SetFocus();
937
938 if( !( m_delayedFocusColumn == 0 && m_delayedFocusRow < m_fields->GetMandatoryRowCount() ) )
939 m_delayedFocusGrid->EnableCellEditControl( true );
940
941 m_delayedFocusGrid->ShowCellEditControl();
942
943 m_delayedFocusGrid = nullptr;
946 }
947}
948
949
951{
952 wxSize new_size = aEvent.GetSize();
953
954 if( ( !m_itemsGrid->IsCellEditControlShown() || m_lastRequestedSize != new_size )
955 && m_gridSize != new_size )
956 {
957 m_gridSize = new_size;
958
959 // A trick to fix a cosmetic issue: when, in m_itemsGrid, a layer selector widget has
960 // the focus (is activated in column 6) when resizing the grid, the widget is not moved.
961 // So just change the widget having the focus in this case
962 if( m_NoteBook->GetSelection() == 0 && !m_itemsGrid->HasFocus() )
963 {
964 int col = m_itemsGrid->GetGridCursorCol();
965
966 if( col == 6 ) // a layer selector widget can be activated
967 m_itemsGrid->SetFocus();
968 }
969
971 }
972
973 // We store this value to check whether the dialog is changing size. This might indicate
974 // that the user is scaling the dialog with an editor shown. Some editors do not close
975 // (at least on GTK) when the user drags a dialog corner
976 m_lastRequestedSize = new_size;
977
978 // Always propagate for a grid repaint (needed if the height changes, as well as width)
979 aEvent.Skip();
980}
981
982
984{
986 aEvent.Veto();
987
989 aEvent.Veto();
990}
991
992
994{
995 if( m_initialized )
996 OnModify();
997}
998
999
1001{
1002 if( m_initialized )
1003 OnModify();
1004}
1005
1006
1008{
1009 if( m_initialized )
1010 OnModify();
1011}
const char * name
Definition: DXF_plotter.cpp:59
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
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
BASE_SET & set(size_t pos)
Definition: base_set.h:116
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
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:239
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:290
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:47
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:296
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:831
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:616
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Modify a given item in the model.
Definition: commit.h:108
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:66
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...
int GetTextHeight() const
Definition: eda_text.h:254
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition: eda_text.cpp:526
int GetTextWidth() const
Definition: eda_text.h:251
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:284
int GetTextThickness() const
Definition: eda_text.h:126
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
Definition: eda_text.cpp:300
VECTOR2I GetTextSize() const
Definition: eda_text.h:248
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
void SetFPID(const LIB_ID &aFPID)
Definition: footprint.h:248
wxString GetLibDescription() const
Definition: footprint.h:256
ZONE_CONNECTION GetLocalZoneConnection() const
Definition: footprint.h:287
void Remove(BOARD_ITEM *aItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition: footprint.cpp:1103
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:2330
void SetLocalSolderPasteMarginRatio(std::optional< double > aRatio)
Definition: footprint.h:284
void SetKeywords(const wxString &aKeywords)
Definition: footprint.h:260
void SetAttributes(int aAttributes)
Definition: footprint.h:290
std::optional< int > GetLocalSolderPasteMargin() const
Definition: footprint.h:280
void SetPrivateLayers(LSET aLayers)
Adds an item to the container.
Definition: footprint.h:146
std::optional< int > GetLocalClearance() const
Definition: footprint.h:274
int GetAttributes() const
Definition: footprint.h:289
void SetLocalZoneConnection(ZONE_CONNECTION aType)
Definition: footprint.h:286
void ClearNetTiePadGroups()
Definition: footprint.h:340
LSET GetPrivateLayers() const
Definition: footprint.h:145
const std::vector< wxString > & GetNetTiePadGroups() const
Definition: footprint.h:338
const LIB_ID & GetFPID() const
Definition: footprint.h:247
void AddNetTiePadGroup(const wxString &aGroup)
Definition: footprint.h:345
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: footprint.cpp:1046
std::optional< double > GetLocalSolderPasteMarginRatio() const
Definition: footprint.h:283
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly) const
Populate a std::vector with PCB_TEXTs.
Definition: footprint.cpp:625
std::vector< FP_3DMODEL > & Models()
Definition: footprint.h:219
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:2341
void SetLibDescription(const wxString &aDesc)
Definition: footprint.h:257
void SetLocalSolderMaskMargin(std::optional< int > aMargin)
Definition: footprint.h:278
void SetLocalClearance(std::optional< int > aClearance)
Definition: footprint.h:275
std::optional< int > GetLocalSolderMaskMargin() const
Definition: footprint.h:277
void SetLocalSolderPasteMargin(std::optional< int > aMargin)
Definition: footprint.h:281
wxString GetKeywords() const
Definition: footprint.h:259
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:43
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:110
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:99
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:711
static LSET AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
Definition: lset.cpp:636
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:572
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:297
EMBEDDED_FILES * GetLocalFiles()
bool TransferDataToWindow() override
std::vector< FP_3DMODEL > & GetModelList()
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:68
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:100
PCB_FIELD * CloneField() const
Same as Clone, but returns a PCB_FIELD item.
Definition: pcb_field.h:90
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
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:73
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:776
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:275
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:449
wxString GetShownColumnsAsString()
Get a tokenized string containing the shown column indexes.
Definition: wx_grid.cpp:464
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:644
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:170
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:47
#define TEXT_MAX_SIZE_MM
Maximum text size in mm (~10 inches)
Definition: eda_text.h:48
@ FP_SMD
Definition: footprint.h:80
@ FP_DNP
Definition: footprint.h:87
@ FP_ALLOW_MISSING_COURTYARD
Definition: footprint.h:86
@ FP_EXCLUDE_FROM_POS_FILES
Definition: footprint.h:81
@ FP_BOARD_ONLY
Definition: footprint.h:83
@ FP_EXCLUDE_FROM_BOM
Definition: footprint.h:82
@ FP_THROUGH_HOLE
Definition: footprint.h:79
@ FP_ALLOW_SOLDERMASK_BRIDGES
Definition: footprint.h:85
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:722
wxSize GetUnobscuredSize(const wxWindow *aWindow)
Tries to determine the size of the viewport of a scrollable widget (wxDataViewCtrl,...
Definition: wxgtk/ui.cpp:252
KICOMMON_API wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:155
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:88
wxString GetUserFieldName(int aFieldNdx, bool aTranslateForHI)
#define DO_TRANSLATE
Custom text control validator definitions.