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 (C) 2004-2024 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
27#include <confirm.h>
30#include <validators.h>
32#include <board_commit.h>
33#include <bitmaps.h>
34#include <kiplatform/ui.h>
36#include <widgets/wx_grid.h>
39#include <footprint.h>
45#include "filename_resolver.h"
46#include <pgm_base.h>
49#include <tool/tool_manager.h>
52
53#include <fp_lib_table.h>
54
56 m_frame( aFrame )
57{
58 m_layerColAttr = new wxGridCellAttr;
59 m_layerColAttr->SetRenderer( new GRID_CELL_LAYER_RENDERER( m_frame ) );
60
61 LSET forbiddenLayers = LSET::AllCuMask() | LSET::AllTechMask();
62 forbiddenLayers.set( Edge_Cuts );
63 forbiddenLayers.set( Margin );
64 m_layerColAttr->SetEditor( new GRID_CELL_LAYER_SELECTOR( m_frame, forbiddenLayers ) );
65}
66
67
69{
70 m_layerColAttr->DecRef();
71}
72
73
74bool PRIVATE_LAYERS_GRID_TABLE::CanGetValueAs( int aRow, int aCol, const wxString& aTypeName )
75{
76 return aTypeName == wxGRID_VALUE_NUMBER;
77}
78
79
80bool PRIVATE_LAYERS_GRID_TABLE::CanSetValueAs( int aRow, int aCol, const wxString& aTypeName )
81{
82 return aTypeName == wxGRID_VALUE_NUMBER;
83}
84
85
86wxGridCellAttr* PRIVATE_LAYERS_GRID_TABLE::GetAttr( int aRow, int aCol,
87 wxGridCellAttr::wxAttrKind aKind )
88{
89 m_layerColAttr->IncRef();
90 return enhanceAttr( m_layerColAttr, aRow, aCol, aKind );
91}
92
93
94wxString PRIVATE_LAYERS_GRID_TABLE::GetValue( int aRow, int aCol )
95{
96 return m_frame->GetBoard()->GetLayerName( this->at( (size_t) aRow ) );
97}
98
99
101{
102 return this->at( (size_t) aRow );
103}
104
105
106void PRIVATE_LAYERS_GRID_TABLE::SetValue( int aRow, int aCol, const wxString &aValue )
107{
108 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a string value" ), aCol ) );
109}
110
111
112void PRIVATE_LAYERS_GRID_TABLE::SetValueAsLong( int aRow, int aCol, long aValue )
113{
114 this->at( (size_t) aRow ) = ToLAYER_ID( (int) aValue );
115}
116
117
118// Remember the last open page during session.
119
121
122
124 FOOTPRINT_EDIT_FRAME* aParent,
125 FOOTPRINT* aFootprint ) :
127 m_frame( aParent ),
128 m_footprint( aFootprint ),
129 m_initialized( false ),
130 m_netClearance( aParent, m_NetClearanceLabel, m_NetClearanceCtrl, m_NetClearanceUnits ),
131 m_solderMask( aParent, m_SolderMaskMarginLabel, m_SolderMaskMarginCtrl,
132 m_SolderMaskMarginUnits ),
133 m_solderPaste( aParent, m_SolderPasteMarginLabel, m_SolderPasteMarginCtrl,
134 m_SolderPasteMarginUnits ),
135 m_solderPasteRatio( aParent, m_PasteMarginRatioLabel, m_PasteMarginRatioCtrl,
136 m_PasteMarginRatioUnits ),
137 m_gridSize( 0, 0 ),
138 m_lastRequestedSize( 0, 0 )
139{
140 SetEvtHandlerEnabled( false );
141 // Create the 3D models page
143 m_NoteBook->AddPage( m_3dPanel, _("3D Models"), false );
144
147
148 m_delayedErrorMessage = wxEmptyString;
149 m_delayedFocusCtrl = nullptr;
150 m_delayedFocusGrid = nullptr;
153 m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_UNKNOWN;
154
155 // Give an icon
156 wxIcon icon;
157 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_modedit ) );
158 SetIcon( icon );
159
160 // Give a bit more room for combobox editors
161 m_itemsGrid->SetDefaultRowSize( m_itemsGrid->GetDefaultRowSize() + 4 );
162 m_privateLayersGrid->SetDefaultRowSize( m_privateLayersGrid->GetDefaultRowSize() + 4 );
163
166
167 m_itemsGrid->PushEventHandler( new GRID_TRICKS( m_itemsGrid ) );
169 [this]( wxCommandEvent& aEvent )
170 {
171 OnAddLayer( aEvent );
172 } ) );
173 m_padGroupsGrid->PushEventHandler( new GRID_TRICKS( m_padGroupsGrid,
174 [this]( wxCommandEvent& aEvent )
175 {
176 OnAddPadGroup( aEvent );
177 } ) );
178
179 m_itemsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
180 m_privateLayersGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
181 m_padGroupsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
182
183 // Show/hide columns according to the user's preference
185
187
188 // Set font sizes
189 wxFont infoFont = KIUI::GetInfoFont( this );
190 infoFont.SetStyle( wxFONTSTYLE_ITALIC );
191 m_staticTextInfoCopper->SetFont( infoFont );
192 m_staticTextInfoPaste->SetFont( infoFont );
193
194 if( static_cast<int>( m_page ) >= 0 )
195 m_NoteBook->SetSelection( (unsigned) m_page );
196
197 if( m_page == NOTEBOOK_PAGES::PAGE_GENERAL )
198 {
202 m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_GENERAL;
203 }
204 else if( m_page == NOTEBOOK_PAGES::PAGE_CLEARANCES )
205 {
207 }
208
210
211 m_solderPasteRatio.SetUnits( EDA_UNITS::PERCENT );
213
214 // Configure button logos
215 m_bpAdd->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
216 m_bpDelete->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
217 m_bpAddLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
218 m_bpDeleteLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
219 m_bpAddPadGroup->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
220 m_bpRemovePadGroup->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
221
223
225 SetEvtHandlerEnabled( true );
226}
227
228
230{
232
233 // Prevents crash bug in wxGrid's d'tor
236
237 // Delete the GRID_TRICKS.
238 m_itemsGrid->PopEventHandler( true );
239 m_privateLayersGrid->PopEventHandler( true );
240 m_padGroupsGrid->PopEventHandler( true );
241
242 m_page = static_cast<NOTEBOOK_PAGES>( m_NoteBook->GetSelection() );
243
244 // the GL canvas on the 3D models page has to be visible before it is destroyed
245 m_NoteBook->SetSelection( static_cast<int>( NOTEBOOK_PAGES::PAGE_3D_MODELS ) );
246}
247
248
250{
251 LIB_ID fpID = m_footprint->GetFPID();
252 wxString footprintName = fpID.GetLibItemName();
253
254 m_FootprintNameCtrl->ChangeValue( footprintName );
255
257 m_KeywordCtrl->SetValue( m_footprint->GetKeywords() );
258
259 if( !wxDialog::TransferDataToWindow() )
260 return false;
261
262 if( !m_PanelGeneral->TransferDataToWindow() )
263 return false;
264
265 // Add the models to the panel
267 return false;
268
269 // Footprint Fields
270 for( PCB_FIELD* field : m_footprint->GetFields() )
271 m_fields->push_back( *field );
272
273 // Notify the grid
274 wxGridTableMessage tmsg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
276 m_itemsGrid->ProcessTableMessage( tmsg );
277
279 m_componentType->SetSelection( 0 );
280 else if( m_footprint->GetAttributes() & FP_SMD )
281 m_componentType->SetSelection( 1 );
282 else
283 m_componentType->SetSelection( 2 );
284
285 // Private layers
286 for( PCB_LAYER_ID privateLayer : m_footprint->GetPrivateLayers().UIOrder() )
287 m_privateLayers->push_back( privateLayer );
288
289 // Notify the grid
290 wxGridTableMessage gridTableMessagesg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
292 m_privateLayersGrid->ProcessTableMessage( gridTableMessagesg );
293
298 m_cbDNP->SetValue( m_footprint->GetAttributes() & FP_DNP );
299
300 // Local Clearances
301
302 if( m_footprint->GetLocalClearance().has_value() )
304 else
305 m_netClearance.SetValue( wxEmptyString );
306
307 if( m_footprint->GetLocalSolderMaskMargin().has_value() )
309 else
310 m_solderMask.SetValue( wxEmptyString );
311
312 if( m_footprint->GetLocalSolderPasteMargin().has_value() )
314 else
315 m_solderPaste.SetValue( wxEmptyString );
316
319 else
320 m_solderPasteRatio.SetValue( wxEmptyString );
321
323
325 {
326 default:
327 case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
328 case ZONE_CONNECTION::FULL: m_ZoneConnectionChoice->SetSelection( 1 ); break;
329 case ZONE_CONNECTION::THERMAL: m_ZoneConnectionChoice->SetSelection( 2 ); break;
330 case ZONE_CONNECTION::NONE: m_ZoneConnectionChoice->SetSelection( 3 ); break;
331 }
332
333 for( const wxString& group : m_footprint->GetNetTiePadGroups() )
334 {
335 if( !group.IsEmpty() )
336 {
337 m_padGroupsGrid->AppendRows( 1 );
338 m_padGroupsGrid->SetCellValue( m_padGroupsGrid->GetNumberRows() - 1, 0, group );
339 }
340 }
341
342 // Items grid
343 for( int col = 0; col < m_itemsGrid->GetNumberCols(); col++ )
344 {
345 // Adjust min size to the column label size
346 m_itemsGrid->SetColMinimalWidth( col, m_itemsGrid->GetVisibleWidth( col, true, false ) );
347 // Adjust the column size.
348 int col_size = m_itemsGrid->GetVisibleWidth( col );
349
350 if( col == PFC_LAYER ) // This one's a drop-down. Check all possible values.
351 {
352 BOARD* board = m_footprint->GetBoard();
353
354 for( PCB_LAYER_ID layer : board->GetEnabledLayers().Seq() )
355 col_size = std::max( col_size, GetTextExtent( board->GetLayerName( layer ) ).x );
356
357 // Swatch and gaps:
358 col_size += KiROUND( 14 * GetDPIScaleFactor() ) + 12;
359 }
360
361 if( m_itemsGrid->IsColShown( col ) )
362 m_itemsGrid->SetColSize( col, col_size );
363 }
364
365 m_itemsGrid->SetRowLabelSize( 0 );
366
367 Layout();
369 m_initialized = true;
370
371 return true;
372}
373
374
376{
377 if( aFootprintName.IsEmpty() )
378 {
379 m_delayedErrorMessage = _( "Footprint must have a name." );
380 return false;
381 }
382 else if( !FOOTPRINT::IsLibNameValid( aFootprintName ) )
383 {
384 m_delayedErrorMessage.Printf( _( "Footprint name may not contain '%s'." ),
386 return false;
387 }
388
389 return true;
390}
391
392
394{
396 return false;
397
398 if( !DIALOG_SHIM::Validate() )
399 return false;
400
401 // First, test for invalid chars in footprint name
402 wxString footprintName = m_FootprintNameCtrl->GetValue();
403
404 if( !checkFootprintName( footprintName ) )
405 {
406 if( m_NoteBook->GetSelection() != 0 )
407 m_NoteBook->SetSelection( 0 );
408
410 m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_GENERAL;
411
412 return false;
413 }
414
415 // Check for valid field text properties
416 for( size_t i = 0; i < m_fields->size(); ++i )
417 {
418 PCB_FIELD& field = m_fields->at( i );
419
420 // Check for missing field names.
421 if( field.GetName( false ).IsEmpty() )
422 {
424 m_delayedErrorMessage = wxString::Format( _( "Fields must have a name." ) );
427
428 return false;
429 }
430
432 int maxSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
433
434 if( field.GetTextWidth() < minSize || field.GetTextWidth() > maxSize )
435 {
437 m_delayedErrorMessage = wxString::Format( _( "The text width must be between %s and %s." ),
439 m_frame->StringFromValue( maxSize, true ) );
442
443 return false;
444 }
445
446 if( field.GetTextHeight() < minSize || field.GetTextHeight() > maxSize )
447 {
449 m_delayedErrorMessage = wxString::Format( _( "The text height must be between %s and %s." ),
451 m_frame->StringFromValue( maxSize, true ) );
454
455 return false;
456 }
457
458 // Test for acceptable values for thickness and size and clamp if fails
459 int maxPenWidth = Clamp_Text_PenSize( field.GetTextThickness(), field.GetTextSize() );
460
461 if( field.GetTextThickness() > maxPenWidth )
462 {
463 m_itemsGrid->SetCellValue( i, PFC_THICKNESS,
464 m_frame->StringFromValue( maxPenWidth, true ) );
465
467 m_delayedErrorMessage = _( "The text thickness is too large for the text size.\n"
468 "It will be clamped." );
471
472 return false;
473 }
474 }
475
476 if( !m_netClearance.Validate( 0, INT_MAX ) )
477 return false;
478
479 return true;
480}
481
482
484{
485 if( !Validate() )
486 return false;
487
488 if( !DIALOG_SHIM::TransferDataFromWindow() )
489 return false;
490
494 {
495 return false;
496 }
497
498 // This only commits the editor, model updating is done below so it is inside
499 // the commit
501 return false;
502
504 BOARD_COMMIT commit( m_frame );
505 commit.Modify( m_footprint );
506
507 LIB_ID fpID = m_footprint->GetFPID();
508 fpID.SetLibItemName( m_FootprintNameCtrl->GetValue() );
509 m_footprint->SetFPID( fpID );
510
512 m_footprint->SetKeywords( m_KeywordCtrl->GetValue() );
513
514 // Update fields
515
516 std::vector<PCB_FIELD*> items_to_remove;
517 size_t i = 0;
518
519 for( PCB_FIELD* field : m_footprint->GetFields() )
520 {
521 // copy grid table entries till we run out, then delete any remaining texts
522 if( i < m_fields->size() )
523 *field = m_fields->at( i++ );
524 else
525 items_to_remove.push_back( field );
526 }
527
528 // Remove text items:
530
531 for( PCB_TEXT* item : items_to_remove )
532 {
533 selTool->RemoveItemFromSel( item );
534 view->Remove( item );
535 item->DeleteStructure();
536 }
537
538 // if there are still grid table entries, create new fields for them
539 while( i < m_fields->size() )
540 view->Add( m_footprint->AddField( m_fields->at( i++ ) ) );
541
542 LSET privateLayers;
543
544 for( PCB_LAYER_ID layer : *m_privateLayers )
545 privateLayers.set( layer );
546
547 m_footprint->SetPrivateLayers( privateLayers );
548
549 int attributes = 0;
550
551 switch( m_componentType->GetSelection() )
552 {
553 case 0: attributes |= FP_THROUGH_HOLE; break;
554 case 1: attributes |= FP_SMD; break;
555 default: break;
556 }
557
558 if( m_boardOnly->GetValue() )
559 attributes |= FP_BOARD_ONLY;
560
561 if( m_excludeFromPosFiles->GetValue() )
562 attributes |= FP_EXCLUDE_FROM_POS_FILES;
563
564 if( m_excludeFromBOM->GetValue() )
565 attributes |= FP_EXCLUDE_FROM_BOM;
566
567 if( m_noCourtyards->GetValue() )
568 attributes |= FP_ALLOW_MISSING_COURTYARD;
569
570 if( m_cbDNP->GetValue() )
571 attributes |= FP_DNP;
572
573 if( m_allowBridges->GetValue() )
574 attributes |= FP_ALLOW_SOLDERMASK_BRIDGES;
575
576 m_footprint->SetAttributes( attributes );
577
578 // Initialize mask clearances
579 if( m_netClearance.IsNull() )
581 else
582 m_footprint->SetLocalClearance( m_netClearance.GetValue() );
583
584 if( m_solderMask.IsNull() )
585 m_footprint->SetLocalSolderMaskMargin( {} );
586 else
587 m_footprint->SetLocalSolderMaskMargin( m_solderMask.GetValue() );
588
589 if( m_solderPaste.IsNull() )
590 m_footprint->SetLocalSolderPasteMargin( {} );
591 else
592 m_footprint->SetLocalSolderPasteMargin( m_solderPaste.GetValue() );
593
594 if( m_solderPasteRatio.IsNull() )
595 m_footprint->SetLocalSolderPasteMarginRatio( {} );
596 else
597 m_footprint->SetLocalSolderPasteMarginRatio( m_solderPasteRatio.GetDoubleValue() / 100.0 );
598
599 switch( m_ZoneConnectionChoice->GetSelection() )
600 {
601 default:
602 case 0: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::INHERITED ); break;
603 case 1: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::FULL ); break;
604 case 2: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::THERMAL ); break;
605 case 3: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::NONE ); break;
606 }
607
608 m_footprint->ClearNetTiePadGroups();
609
610 for( int ii = 0; ii < m_padGroupsGrid->GetNumberRows(); ++ii )
611 {
612 wxString group = m_padGroupsGrid->GetCellValue( ii, 0 );
613
614 if( !group.IsEmpty() )
615 m_footprint->AddNetTiePadGroup( group );
616 }
617
618 // Copy the models from the panel to the footprint
619 std::vector<FP_3DMODEL>& panelList = m_3dPanel->GetModelList();
620 std::vector<FP_3DMODEL>* fpList = &m_footprint->Models();
621 fpList->clear();
622 fpList->insert( fpList->end(), panelList.begin(), panelList.end() );
623
624 commit.Push( _( "Edit Footprint Properties" ) );
625
626 return true;
627}
628
629
631{
633 return;
634
635 const BOARD_DESIGN_SETTINGS& dsnSettings = m_frame->GetDesignSettings();
636
637 int fieldId = (int) m_fields->size();
638 PCB_FIELD newField( m_footprint, m_fields->size(),
640
641 // Set active layer if legal; otherwise copy layer from previous text item
643 newField.SetLayer( m_frame->GetActiveLayer() );
644 else
645 newField.SetLayer( m_fields->at( m_fields->size() - 1 ).GetLayer() );
646
647 newField.SetTextSize( dsnSettings.GetTextSize( newField.GetLayer() ) );
648 newField.SetTextThickness( dsnSettings.GetTextThickness( newField.GetLayer() ) );
649 newField.SetItalic( dsnSettings.GetTextItalic( newField.GetLayer() ) );
650
651 m_fields->push_back( newField );
652
653 // notify the grid
654 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
655 m_itemsGrid->ProcessTableMessage( msg );
656
657 m_itemsGrid->SetFocus();
658 m_itemsGrid->MakeCellVisible( m_fields->size() - 1, 0 );
659 m_itemsGrid->SetGridCursor( m_fields->size() - 1, 0 );
660
661 m_itemsGrid->EnableCellEditControl( true );
662 m_itemsGrid->ShowCellEditControl();
663
664 OnModify();
665}
666
667
669{
671 return;
672
673 wxArrayInt selectedRows = m_itemsGrid->GetSelectedRows();
674
675 if( selectedRows.empty() && m_itemsGrid->GetGridCursorRow() >= 0 )
676 selectedRows.push_back( m_itemsGrid->GetGridCursorRow() );
677
678 if( selectedRows.empty() )
679 return;
680
681 for( int row : selectedRows )
682 {
683 if( row < MANDATORY_FIELDS )
684 {
685 DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
687 return;
688 }
689 }
690
691 m_itemsGrid->CommitPendingChanges( true /* quiet mode */ );
692 m_itemsGrid->ClearSelection();
693
694 // Reverse sort so deleting a row doesn't change the indexes of the other rows.
695 selectedRows.Sort( []( int* first, int* second )
696 {
697 return *second - *first;
698 } );
699
700 for( int row : selectedRows )
701 {
702 m_fields->erase( m_fields->begin() + row );
703
704 // notify the grid
705 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 );
706 m_itemsGrid->ProcessTableMessage( msg );
707
708 if( m_itemsGrid->GetNumberRows() > 0 )
709 {
710 m_itemsGrid->MakeCellVisible( std::max( 0, row-1 ), m_itemsGrid->GetGridCursorCol() );
711 m_itemsGrid->SetGridCursor( std::max( 0, row-1 ), m_itemsGrid->GetGridCursorCol() );
712 }
713 }
714
715 OnModify();
716}
717
718
720{
722 return;
723
724 PCB_LAYER_ID nextLayer = User_1;
725
726 while( alg::contains( *m_privateLayers, nextLayer ) && nextLayer < User_9 )
727 nextLayer = ToLAYER_ID( nextLayer + 1 );
728
729 m_privateLayers->push_back( nextLayer );
730
731 // notify the grid
732 wxGridTableMessage msg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
733 m_privateLayersGrid->ProcessTableMessage( msg );
734
735 m_privateLayersGrid->SetFocus();
736 m_privateLayersGrid->MakeCellVisible( m_privateLayers->size() - 1, 0 );
737 m_privateLayersGrid->SetGridCursor( m_privateLayers->size() - 1, 0 );
738
739 OnModify();
740}
741
742
744{
746 return;
747
748 int curRow = m_privateLayersGrid->GetGridCursorRow();
749
750 if( curRow < 0 )
751 return;
752
753 m_privateLayers->erase( m_privateLayers->begin() + curRow );
754
755 // notify the grid
756 wxGridTableMessage msg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_DELETED, curRow, 1 );
757 m_privateLayersGrid->ProcessTableMessage( msg );
758
759 if( m_privateLayersGrid->GetNumberRows() > 0 )
760 {
761 m_privateLayersGrid->MakeCellVisible( std::max( 0, curRow-1 ),
762 m_privateLayersGrid->GetGridCursorCol() );
763 m_privateLayersGrid->SetGridCursor( std::max( 0, curRow-1 ),
764 m_privateLayersGrid->GetGridCursorCol() );
765 }
766
767 OnModify();
768}
769
770
772{
774 return;
775
776 m_padGroupsGrid->AppendRows( 1 );
777
778 m_padGroupsGrid->SetFocus();
779 m_padGroupsGrid->MakeCellVisible( m_padGroupsGrid->GetNumberRows() - 1, 0 );
780 m_padGroupsGrid->SetGridCursor( m_padGroupsGrid->GetNumberRows() - 1, 0 );
781
782 m_padGroupsGrid->EnableCellEditControl( true );
783 m_padGroupsGrid->ShowCellEditControl();
784
785 OnModify();
786}
787
788
790{
792 return;
793
794 wxArrayInt selectedRows = m_padGroupsGrid->GetSelectedRows();
795 int curRow = m_padGroupsGrid->GetGridCursorRow();
796
797 if( selectedRows.empty() && curRow >= 0 && curRow < m_padGroupsGrid->GetNumberRows() )
798 selectedRows.Add( curRow );
799
800 for( int ii = selectedRows.Count() - 1; ii >= 0; --ii )
801 {
802 int row = selectedRows.Item( ii );
803 m_padGroupsGrid->DeleteRows( row, 1 );
804 curRow = std::min( curRow, row );
805 }
806
807 curRow = std::max( 0, curRow - 1 );
808 m_padGroupsGrid->MakeCellVisible( curRow, m_padGroupsGrid->GetGridCursorCol() );
809 m_padGroupsGrid->SetGridCursor( curRow, m_padGroupsGrid->GetGridCursorCol() );
810
811 OnModify();
812}
813
814
816{
817 // Account for scroll bars
819
820 itemsWidth -= m_itemsGrid->GetRowLabelSize();
821
822 for( int i = 0; i < m_itemsGrid->GetNumberCols(); i++ )
823 {
824 if( i == 1 )
825 continue;
826
827 itemsWidth -= m_itemsGrid->GetColSize( i );
828 }
829
830 m_itemsGrid->SetColSize(
831 1, std::max( itemsWidth, m_itemsGrid->GetVisibleWidth( 0, true, false ) ) );
832
833 // Update the width private layers grid
834 m_privateLayersGrid->SetColSize( 0, std::max( m_privateLayersGrid->GetClientSize().x,
836
837 // Update the width net tie pad groups grid
838 m_padGroupsGrid->SetColSize( 0, std::max( m_padGroupsGrid->GetClientSize().x,
840
841 // Update the width of the 3D panel
843}
844
845
847{
848 // Handle a delayed focus. The delay allows us to:
849 // a) change focus when the error was triggered from within a killFocus handler
850 // b) show the correct notebook page in the background before the error dialog comes up
851 // when triggered from an OK or a notebook page change
852
853 if( static_cast<int>( m_delayedFocusPage ) >= 0 )
854 {
855 if( m_NoteBook->GetSelection() != static_cast<int>( m_delayedFocusPage ) )
856 m_NoteBook->ChangeSelection( static_cast<int>( m_delayedFocusPage ) );
857
858 m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_UNKNOWN;
859 }
860
861 if( !m_delayedErrorMessage.IsEmpty() )
862 {
863 // We will re-enter this routine when the error dialog is displayed, so make
864 // sure we don't keep putting up more dialogs.
865 wxString msg = m_delayedErrorMessage;
866 m_delayedErrorMessage = wxEmptyString;
867
868 // Do not use DisplayErrorMessage(); it screws up window order on Mac
869 DisplayError( nullptr, msg );
870 }
871
873 {
874 m_delayedFocusCtrl->SetFocus();
875
876 if( wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_delayedFocusCtrl ) )
877 textEntry->SelectAll();
878
879 m_delayedFocusCtrl = nullptr;
880 }
881 else if( m_delayedFocusGrid )
882 {
883 m_delayedFocusGrid->SetFocus();
886
888 m_delayedFocusGrid->EnableCellEditControl( true );
889
890 m_delayedFocusGrid->ShowCellEditControl();
891
892 m_delayedFocusGrid = nullptr;
895 }
896}
897
898
900{
901 wxSize new_size = aEvent.GetSize();
902
903 if( ( !m_itemsGrid->IsCellEditControlShown() || m_lastRequestedSize != new_size )
904 && m_gridSize != new_size )
905 {
906 m_gridSize = new_size;
907
908 // A trick to fix a cosmetic issue: when, in m_itemsGrid, a layer selector widget has
909 // the focus (is activated in column 6) when resizing the grid, the widget is not moved.
910 // So just change the widget having the focus in this case
911 if( m_NoteBook->GetSelection() == 0 && !m_itemsGrid->HasFocus() )
912 {
913 int col = m_itemsGrid->GetGridCursorCol();
914
915 if( col == 6 ) // a layer selector widget can be activated
916 m_itemsGrid->SetFocus();
917 }
918
920 }
921
922 // We store this value to check whether the dialog is changing size. This might indicate
923 // that the user is scaling the dialog with an editor shown. Some editors do not close
924 // (at least on GTK) when the user drags a dialog corner
925 m_lastRequestedSize = new_size;
926
927 // Always propagate for a grid repaint (needed if the height changes, as well as width)
928 aEvent.Skip();
929}
930
931
933{
935 aEvent.Veto();
936
938 aEvent.Veto();
939}
940
941
943{
944 if( m_initialized )
945 OnModify();
946}
947
948
950{
951 if( m_initialized )
952 OnModify();
953}
954
955
957{
958 if( m_initialized )
959 OnModify();
960}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
Definition: bitmap.cpp:110
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
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
BASE_SET & set(size_t pos)
Definition: base_set.h:115
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:237
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:288
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:290
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:778
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:574
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Create an undo entry for an item that has been already modified.
Definition: commit.h:105
Class DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE.
DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR(FOOTPRINT_EDIT_FRAME *aParent, FOOTPRINT *aFootprint)
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:102
void SetupStandardButtons(std::map< int, wxString > aLabels={})
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:255
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition: eda_text.cpp:515
int GetTextWidth() const
Definition: eda_text.h:252
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:283
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:299
VECTOR2I GetTextSize() const
Definition: eda_text.h:249
BOARD_DESIGN_SETTINGS & GetDesignSettings() const override
Returns the BOARD_DESIGN_SETTINGS for the open project.
FOOTPRINT_EDITOR_SETTINGS * GetSettings()
This class provides a custom wxValidator object for limiting the allowable characters when defining f...
Definition: validators.h:60
void SetFPID(const LIB_ID &aFPID)
Definition: footprint.h:249
wxString GetLibDescription() const
Definition: footprint.h:257
ZONE_CONNECTION GetLocalZoneConnection() const
Definition: footprint.h:288
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:2256
PCB_FIELD * AddField(const PCB_FIELD &aField)
Add a field to the symbol.
Definition: footprint.cpp:637
void SetKeywords(const wxString &aKeywords)
Definition: footprint.h:261
void SetAttributes(int aAttributes)
Definition: footprint.h:291
std::optional< int > GetLocalSolderPasteMargin() const
Definition: footprint.h:281
void SetPrivateLayers(LSET aLayers)
Adds an item to the container.
Definition: footprint.h:142
std::optional< int > GetLocalClearance() const
Definition: footprint.h:275
int GetAttributes() const
Definition: footprint.h:290
LSET GetPrivateLayers() const
Definition: footprint.h:141
const std::vector< wxString > & GetNetTiePadGroups() const
Definition: footprint.h:339
const LIB_ID & GetFPID() const
Definition: footprint.h:248
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with PCB_TEXTs.
Definition: footprint.cpp:616
std::optional< double > GetLocalSolderPasteMarginRatio() const
Definition: footprint.h:284
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:2267
void SetLibDescription(const wxString &aDesc)
Definition: footprint.h:258
void SetLocalClearance(std::optional< int > aClearance)
Definition: footprint.h:276
std::optional< int > GetLocalSolderMaskMargin() const
Definition: footprint.h:278
wxString GetKeywords() const
Definition: footprint.h:260
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition: grid_tricks.h:61
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
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
const UTF8 & GetLibItemName() const
Definition: lib_id.h:102
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:36
LSEQ UIOrder() const
Returns the copper, technical and user layers in the order shown in layer widget.
Definition: lset.cpp:809
static LSET AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
Definition: lset.cpp:744
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:686
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:420
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: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
int RemoveItemFromSel(const TOOL_EVENT &aEvent)
void SetBitmap(const wxBitmapBundle &aBmp)
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
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 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 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)
Calculates the specified column based on the actual size of the text on screen.
Definition: wx_grid.cpp:769
void ShowHideColumns(const wxString &shownColumns)
Show/hide the grid columns based on a tokenized string of shown column indexes.
Definition: wx_grid.cpp:487
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:270
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:443
wxString GetShownColumnsAsString()
Get a tokenized string containing the shown column indexes.
Definition: wx_grid.cpp:457
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:637
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:76
@ FP_DNP
Definition: footprint.h:83
@ FP_ALLOW_MISSING_COURTYARD
Definition: footprint.h:82
@ FP_EXCLUDE_FROM_POS_FILES
Definition: footprint.h:77
@ FP_BOARD_ONLY
Definition: footprint.h:79
@ FP_EXCLUDE_FROM_BOM
Definition: footprint.h:78
@ FP_THROUGH_HOLE
Definition: footprint.h:75
@ FP_ALLOW_SOLDERMASK_BRIDGES
Definition: footprint.h:81
int Clamp_Text_PenSize(int aPenSize, int aSize, bool aStrict)
Pen width should not allow characters to become cluttered up in their own fatness.
Definition: gr_text.cpp:87
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ Edge_Cuts
Definition: layer_ids.h:112
@ User_9
Definition: layer_ids.h:132
@ Margin
Definition: layer_ids.h:113
@ User_1
Definition: layer_ids.h:124
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:820
wxSize GetUnobscuredSize(const wxWindow *aWindow)
Tries to determine the size of the viewport of a scrollable widget (wxDataViewCtrl,...
Definition: wxgtk/ui.cpp:195
KICOMMON_API wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:154
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
static const wxString GetDefaultFieldName(int aFieldNdx, bool aTranslateForHI=false)
Return a default symbol field name for field aFieldNdx for all components.
#define DO_TRANSLATE
@ MANDATORY_FIELDS
The first 5 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
Custom text control validator definitions.
@ THERMAL
Use thermal relief for pads.
@ NONE
Pads are not covered.
@ FULL
pads are covered by copper