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_netClearance( aParent, m_NetClearanceLabel, m_NetClearanceCtrl, m_NetClearanceUnits ),
130 m_solderMask( aParent, m_SolderMaskMarginLabel, m_SolderMaskMarginCtrl,
131 m_SolderMaskMarginUnits ),
132 m_solderPaste( aParent, m_SolderPasteMarginLabel, m_SolderPasteMarginCtrl,
133 m_SolderPasteMarginUnits ),
134 m_solderPasteRatio( aParent, m_PasteMarginRatioLabel, m_PasteMarginRatioCtrl,
135 m_PasteMarginRatioUnits ),
136 m_gridSize( 0, 0 ),
137 m_lastRequestedSize( 0, 0 )
138{
139 SetEvtHandlerEnabled( false );
140 // Create the 3D models page
142 m_NoteBook->AddPage( m_3dPanel, _("3D Models"), false );
143
146
147 m_delayedErrorMessage = wxEmptyString;
148 m_delayedFocusCtrl = nullptr;
149 m_delayedFocusGrid = nullptr;
152 m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_UNKNOWN;
153
154 // Give an icon
155 wxIcon icon;
156 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_modedit ) );
157 SetIcon( icon );
158
159 // Give a bit more room for combobox editors
160 m_itemsGrid->SetDefaultRowSize( m_itemsGrid->GetDefaultRowSize() + 4 );
161 m_privateLayersGrid->SetDefaultRowSize( m_privateLayersGrid->GetDefaultRowSize() + 4 );
162
165
166 m_itemsGrid->PushEventHandler( new GRID_TRICKS( m_itemsGrid ) );
168 [this]( wxCommandEvent& aEvent )
169 {
170 OnAddLayer( aEvent );
171 } ) );
172 m_padGroupsGrid->PushEventHandler( new GRID_TRICKS( m_padGroupsGrid,
173 [this]( wxCommandEvent& aEvent )
174 {
175 OnAddPadGroup( aEvent );
176 } ) );
177
178 m_itemsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
179 m_privateLayersGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
180 m_padGroupsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
181
182 // Show/hide columns according to the user's preference
184
186
187 // Set font sizes
188 wxFont infoFont = KIUI::GetInfoFont( this );
189 infoFont.SetStyle( wxFONTSTYLE_ITALIC );
190 m_staticTextInfoCopper->SetFont( infoFont );
191 m_staticTextInfoPaste->SetFont( infoFont );
192
193 if( static_cast<int>( m_page ) >= 0 )
194 m_NoteBook->SetSelection( (unsigned) m_page );
195
196 if( m_page == NOTEBOOK_PAGES::PAGE_GENERAL )
197 {
201 m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_GENERAL;
202 }
203 else if( m_page == NOTEBOOK_PAGES::PAGE_CLEARANCES )
204 {
206 }
207
209
210 m_solderPasteRatio.SetUnits( EDA_UNITS::PERCENT );
212
213 // Configure button logos
214 m_bpAdd->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
215 m_bpDelete->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
216 m_bpAddLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
217 m_bpDeleteLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
218 m_bpAddPadGroup->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
219 m_bpRemovePadGroup->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
220
222
224 SetEvtHandlerEnabled( true );
225}
226
227
229{
230 PCBNEW_SETTINGS* cfg = nullptr;
231
232 try
233 {
234 cfg = m_frame->GetPcbNewSettings();
235 }
236 catch( const std::runtime_error& e )
237 {
238 wxFAIL_MSG( e.what() );
239 }
240
241 if( cfg )
242 {
244 }
245
246 // Prevents crash bug in wxGrid's d'tor
249
250 // Delete the GRID_TRICKS.
251 m_itemsGrid->PopEventHandler( true );
252 m_privateLayersGrid->PopEventHandler( true );
253 m_padGroupsGrid->PopEventHandler( true );
254
255 m_page = static_cast<NOTEBOOK_PAGES>( m_NoteBook->GetSelection() );
256
257 // the GL canvas on the 3D models page has to be visible before it is destroyed
258 m_NoteBook->SetSelection( static_cast<int>( NOTEBOOK_PAGES::PAGE_3D_MODELS ) );
259}
260
261
263{
264 LIB_ID fpID = m_footprint->GetFPID();
265 wxString footprintName = fpID.GetLibItemName();
266
267 m_FootprintNameCtrl->ChangeValue( footprintName );
268
270 m_KeywordCtrl->SetValue( m_footprint->GetKeywords() );
271
272 if( !wxDialog::TransferDataToWindow() )
273 return false;
274
275 if( !m_PanelGeneral->TransferDataToWindow() )
276 return false;
277
278 // Add the models to the panel
280 return false;
281
282 // Footprint Fields
283 for( PCB_FIELD* field : m_footprint->GetFields() )
284 m_fields->push_back( *field );
285
286 // Notify the grid
287 wxGridTableMessage tmsg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
289 m_itemsGrid->ProcessTableMessage( tmsg );
290
292 m_componentType->SetSelection( 0 );
293 else if( m_footprint->GetAttributes() & FP_SMD )
294 m_componentType->SetSelection( 1 );
295 else
296 m_componentType->SetSelection( 2 );
297
298 // Private layers
299 for( PCB_LAYER_ID privateLayer : m_footprint->GetPrivateLayers().UIOrder() )
300 m_privateLayers->push_back( privateLayer );
301
302 // Notify the grid
303 wxGridTableMessage gridTableMessagesg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
305 m_privateLayersGrid->ProcessTableMessage( gridTableMessagesg );
306
311 m_cbDNP->SetValue( m_footprint->GetAttributes() & FP_DNP );
312
313 // Local Clearances
314
315 if( m_footprint->GetLocalClearance().has_value() )
317 else
318 m_netClearance.SetValue( wxEmptyString );
319
320 if( m_footprint->GetLocalSolderMaskMargin().has_value() )
322 else
323 m_solderMask.SetValue( wxEmptyString );
324
325 if( m_footprint->GetLocalSolderPasteMargin().has_value() )
327 else
328 m_solderPaste.SetValue( wxEmptyString );
329
332 else
333 m_solderPasteRatio.SetValue( wxEmptyString );
334
336
338 {
339 default:
340 case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
341 case ZONE_CONNECTION::FULL: m_ZoneConnectionChoice->SetSelection( 1 ); break;
342 case ZONE_CONNECTION::THERMAL: m_ZoneConnectionChoice->SetSelection( 2 ); break;
343 case ZONE_CONNECTION::NONE: m_ZoneConnectionChoice->SetSelection( 3 ); break;
344 }
345
346 for( const wxString& group : m_footprint->GetNetTiePadGroups() )
347 {
348 if( !group.IsEmpty() )
349 {
350 m_padGroupsGrid->AppendRows( 1 );
351 m_padGroupsGrid->SetCellValue( m_padGroupsGrid->GetNumberRows() - 1, 0, group );
352 }
353 }
354
355 // Items grid
356 for( int col = 0; col < m_itemsGrid->GetNumberCols(); col++ )
357 {
358 // Adjust min size to the column label size
359 m_itemsGrid->SetColMinimalWidth( col, m_itemsGrid->GetVisibleWidth( col, true, false ) );
360 // Adjust the column size.
361 int col_size = m_itemsGrid->GetVisibleWidth( col );
362
363 if( col == PFC_LAYER ) // This one's a drop-down. Check all possible values.
364 {
365 BOARD* board = m_footprint->GetBoard();
366
367 for( PCB_LAYER_ID layer : board->GetEnabledLayers().Seq() )
368 col_size = std::max( col_size, GetTextExtent( board->GetLayerName( layer ) ).x );
369
370 // Swatch and gaps:
371 col_size += KiROUND( 14 * GetDPIScaleFactor() ) + 12;
372 }
373
374 if( m_itemsGrid->IsColShown( col ) )
375 m_itemsGrid->SetColSize( col, col_size );
376 }
377
378 m_itemsGrid->SetRowLabelSize( 0 );
379
380 Layout();
382
383 return true;
384}
385
386
388{
389 if( aFootprintName.IsEmpty() )
390 {
391 m_delayedErrorMessage = _( "Footprint must have a name." );
392 return false;
393 }
394 else if( !FOOTPRINT::IsLibNameValid( aFootprintName ) )
395 {
396 m_delayedErrorMessage.Printf( _( "Footprint name may not contain '%s'." ),
398 return false;
399 }
400
401 return true;
402}
403
404
406{
408 return false;
409
410 if( !DIALOG_SHIM::Validate() )
411 return false;
412
413 // First, test for invalid chars in footprint name
414 wxString footprintName = m_FootprintNameCtrl->GetValue();
415
416 if( !checkFootprintName( footprintName ) )
417 {
418 if( m_NoteBook->GetSelection() != 0 )
419 m_NoteBook->SetSelection( 0 );
420
422 m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_GENERAL;
423
424 return false;
425 }
426
427 // Check for valid field text properties
428 for( size_t i = 0; i < m_fields->size(); ++i )
429 {
430 PCB_FIELD& field = m_fields->at( i );
431
432 // Check for missing field names.
433 if( field.GetName( false ).IsEmpty() )
434 {
436 m_delayedErrorMessage = wxString::Format( _( "Fields must have a name." ) );
439
440 return false;
441 }
442
444 int maxSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
445
446 if( field.GetTextWidth() < minSize || field.GetTextWidth() > maxSize )
447 {
449 m_delayedErrorMessage = wxString::Format( _( "The text width must be between %s and %s." ),
451 m_frame->StringFromValue( maxSize, true ) );
454
455 return false;
456 }
457
458 if( field.GetTextHeight() < minSize || field.GetTextHeight() > maxSize )
459 {
461 m_delayedErrorMessage = wxString::Format( _( "The text height must be between %s and %s." ),
463 m_frame->StringFromValue( maxSize, true ) );
466
467 return false;
468 }
469
470 // Test for acceptable values for thickness and size and clamp if fails
471 int maxPenWidth = Clamp_Text_PenSize( field.GetTextThickness(), field.GetTextSize() );
472
473 if( field.GetTextThickness() > maxPenWidth )
474 {
475 m_itemsGrid->SetCellValue( i, PFC_THICKNESS,
476 m_frame->StringFromValue( maxPenWidth, true ) );
477
479 m_delayedErrorMessage = _( "The text thickness is too large for the text size.\n"
480 "It will be clamped." );
483
484 return false;
485 }
486 }
487
488 if( !m_netClearance.Validate( 0, INT_MAX ) )
489 return false;
490
491 return true;
492}
493
494
496{
497 if( !Validate() )
498 return false;
499
500 if( !DIALOG_SHIM::TransferDataFromWindow() )
501 return false;
502
506 {
507 return false;
508 }
509
510 // This only commits the editor, model updating is done below so it is inside
511 // the commit
513 return false;
514
516 BOARD_COMMIT commit( m_frame );
517 commit.Modify( m_footprint );
518
519 LIB_ID fpID = m_footprint->GetFPID();
520 fpID.SetLibItemName( m_FootprintNameCtrl->GetValue() );
521 m_footprint->SetFPID( fpID );
522
524 m_footprint->SetKeywords( m_KeywordCtrl->GetValue() );
525
526 // Update fields
527
528 std::vector<PCB_FIELD*> items_to_remove;
529 size_t i = 0;
530
531 for( PCB_FIELD* field : m_footprint->GetFields() )
532 {
533 // copy grid table entries till we run out, then delete any remaining texts
534 if( i < m_fields->size() )
535 *field = m_fields->at( i++ );
536 else
537 items_to_remove.push_back( field );
538 }
539
540 // Remove text items:
542
543 for( PCB_TEXT* item : items_to_remove )
544 {
545 selTool->RemoveItemFromSel( item );
546 view->Remove( item );
547 item->DeleteStructure();
548 }
549
550
551 // if there are still grid table entries, create new fields for them
552 while( i < m_fields->size() )
553 {
554 view->Add( m_footprint->AddField( m_fields->at( i++ ) ) );
555 }
556
557 LSET privateLayers;
558
559 for( PCB_LAYER_ID layer : *m_privateLayers )
560 privateLayers.set( layer );
561
562 m_footprint->SetPrivateLayers( privateLayers );
563
564 int attributes = 0;
565
566 switch( m_componentType->GetSelection() )
567 {
568 case 0: attributes |= FP_THROUGH_HOLE; break;
569 case 1: attributes |= FP_SMD; break;
570 default: break;
571 }
572
573 if( m_boardOnly->GetValue() )
574 attributes |= FP_BOARD_ONLY;
575
576 if( m_excludeFromPosFiles->GetValue() )
577 attributes |= FP_EXCLUDE_FROM_POS_FILES;
578
579 if( m_excludeFromBOM->GetValue() )
580 attributes |= FP_EXCLUDE_FROM_BOM;
581
582 if( m_noCourtyards->GetValue() )
583 attributes |= FP_ALLOW_MISSING_COURTYARD;
584
585 if( m_cbDNP->GetValue() )
586 attributes |= FP_DNP;
587
588 if( m_allowBridges->GetValue() )
589 attributes |= FP_ALLOW_SOLDERMASK_BRIDGES;
590
591 m_footprint->SetAttributes( attributes );
592
593 // Initialize mask clearances
594 if( m_netClearance.IsNull() )
596 else
597 m_footprint->SetLocalClearance( m_netClearance.GetValue() );
598
599 if( m_solderMask.IsNull() )
600 m_footprint->SetLocalSolderMaskMargin( {} );
601 else
602 m_footprint->SetLocalSolderMaskMargin( m_solderMask.GetValue() );
603
604 if( m_solderPaste.IsNull() )
605 m_footprint->SetLocalSolderPasteMargin( {} );
606 else
607 m_footprint->SetLocalSolderPasteMargin( m_solderPaste.GetValue() );
608
609 if( m_solderPasteRatio.IsNull() )
610 m_footprint->SetLocalSolderPasteMarginRatio( {} );
611 else
612 m_footprint->SetLocalSolderPasteMarginRatio( m_solderPasteRatio.GetDoubleValue() / 100.0 );
613
614 switch( m_ZoneConnectionChoice->GetSelection() )
615 {
616 default:
617 case 0: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::INHERITED ); break;
618 case 1: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::FULL ); break;
619 case 2: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::THERMAL ); break;
620 case 3: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::NONE ); break;
621 }
622
623 m_footprint->ClearNetTiePadGroups();
624
625 for( int ii = 0; ii < m_padGroupsGrid->GetNumberRows(); ++ii )
626 {
627 wxString group = m_padGroupsGrid->GetCellValue( ii, 0 );
628
629 if( !group.IsEmpty() )
630 m_footprint->AddNetTiePadGroup( group );
631 }
632
633 // Copy the models from the panel to the footprint
634 std::vector<FP_3DMODEL>& panelList = m_3dPanel->GetModelList();
635 std::vector<FP_3DMODEL>* fpList = &m_footprint->Models();
636 fpList->clear();
637 fpList->insert( fpList->end(), panelList.begin(), panelList.end() );
638
639 commit.Push( _( "Edit Footprint Properties" ) );
640
641 return true;
642}
643
644
645static bool footprintIsFromBoard( FOOTPRINT* aFootprint )
646{
647 return aFootprint->GetLink() != niluuid;
648}
649
650
652{
654 {
655 // Currently: nothing to do
656 }
657}
658
659
661{
663 return;
664
665 int fieldId = (int) m_fields->size();
666 const BOARD_DESIGN_SETTINGS& dsnSettings = m_frame->GetDesignSettings();
667 PCB_FIELD newField =
670
671 // Set active layer if legal; otherwise copy layer from previous text item
673 newField.SetLayer( m_frame->GetActiveLayer() );
674 else
675 newField.SetLayer( m_fields->at( m_fields->size() - 1 ).GetLayer() );
676
677 newField.SetTextSize( dsnSettings.GetTextSize( newField.GetLayer() ) );
678 newField.SetTextThickness( dsnSettings.GetTextThickness( newField.GetLayer() ) );
679 newField.SetItalic( dsnSettings.GetTextItalic( newField.GetLayer() ) );
680
681 m_fields->push_back( newField );
682
683 // notify the grid
684 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
685 m_itemsGrid->ProcessTableMessage( msg );
686
687 m_itemsGrid->SetFocus();
688 m_itemsGrid->MakeCellVisible( m_fields->size() - 1, 0 );
689 m_itemsGrid->SetGridCursor( m_fields->size() - 1, 0 );
690
691 m_itemsGrid->EnableCellEditControl( true );
692 m_itemsGrid->ShowCellEditControl();
693}
694
695
697{
699 return;
700
701 wxArrayInt selectedRows = m_itemsGrid->GetSelectedRows();
702
703 if( selectedRows.empty() && m_itemsGrid->GetGridCursorRow() >= 0 )
704 selectedRows.push_back( m_itemsGrid->GetGridCursorRow() );
705
706 if( selectedRows.empty() )
707 return;
708
709 for( int row : selectedRows )
710 {
711 if( row < MANDATORY_FIELDS )
712 {
713 DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
715 return;
716 }
717 }
718
719 m_itemsGrid->CommitPendingChanges( true /* quiet mode */ );
720 m_itemsGrid->ClearSelection();
721
722 // Reverse sort so deleting a row doesn't change the indexes of the other rows.
723 selectedRows.Sort( []( int* first, int* second ) { return *second - *first; } );
724
725 for( int row : selectedRows )
726 {
727 m_fields->erase( m_fields->begin() + row );
728
729 // notify the grid
730 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 );
731 m_itemsGrid->ProcessTableMessage( msg );
732
733 if( m_itemsGrid->GetNumberRows() > 0 )
734 {
735 m_itemsGrid->MakeCellVisible( std::max( 0, row-1 ), m_itemsGrid->GetGridCursorCol() );
736 m_itemsGrid->SetGridCursor( std::max( 0, row-1 ), m_itemsGrid->GetGridCursorCol() );
737 }
738 }
739}
740
741
743{
745 return;
746
747 PCB_LAYER_ID nextLayer = User_1;
748
749 while( alg::contains( *m_privateLayers, nextLayer ) && nextLayer < User_9 )
750 nextLayer = ToLAYER_ID( nextLayer + 1 );
751
752 m_privateLayers->push_back( nextLayer );
753
754 // notify the grid
755 wxGridTableMessage msg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
756 m_privateLayersGrid->ProcessTableMessage( msg );
757
758 m_privateLayersGrid->SetFocus();
759 m_privateLayersGrid->MakeCellVisible( m_privateLayers->size() - 1, 0 );
760 m_privateLayersGrid->SetGridCursor( m_privateLayers->size() - 1, 0 );
761}
762
763
765{
767 return;
768
769 int curRow = m_privateLayersGrid->GetGridCursorRow();
770
771 if( curRow < 0 )
772 return;
773
774 m_privateLayers->erase( m_privateLayers->begin() + curRow );
775
776 // notify the grid
777 wxGridTableMessage msg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_DELETED, curRow, 1 );
778 m_privateLayersGrid->ProcessTableMessage( msg );
779
780 if( m_privateLayersGrid->GetNumberRows() > 0 )
781 {
782 m_privateLayersGrid->MakeCellVisible( std::max( 0, curRow-1 ),
783 m_privateLayersGrid->GetGridCursorCol() );
784 m_privateLayersGrid->SetGridCursor( std::max( 0, curRow-1 ),
785 m_privateLayersGrid->GetGridCursorCol() );
786 }
787}
788
789
791{
793 return;
794
795 m_padGroupsGrid->AppendRows( 1 );
796
797 m_padGroupsGrid->SetFocus();
798 m_padGroupsGrid->MakeCellVisible( m_padGroupsGrid->GetNumberRows() - 1, 0 );
799 m_padGroupsGrid->SetGridCursor( m_padGroupsGrid->GetNumberRows() - 1, 0 );
800
801 m_padGroupsGrid->EnableCellEditControl( true );
802 m_padGroupsGrid->ShowCellEditControl();
803}
804
805
807{
809 return;
810
811 wxArrayInt selectedRows = m_padGroupsGrid->GetSelectedRows();
812 int curRow = m_padGroupsGrid->GetGridCursorRow();
813
814 if( selectedRows.empty() && curRow >= 0 && curRow < m_padGroupsGrid->GetNumberRows() )
815 selectedRows.Add( curRow );
816
817 for( int ii = selectedRows.Count() - 1; ii >= 0; --ii )
818 {
819 int row = selectedRows.Item( ii );
820 m_padGroupsGrid->DeleteRows( row, 1 );
821 curRow = std::min( curRow, row );
822 }
823
824 curRow = std::max( 0, curRow - 1 );
825 m_padGroupsGrid->MakeCellVisible( curRow, m_padGroupsGrid->GetGridCursorCol() );
826 m_padGroupsGrid->SetGridCursor( curRow, m_padGroupsGrid->GetGridCursorCol() );
827}
828
829
831{
832 // Account for scroll bars
834
835 itemsWidth -= m_itemsGrid->GetRowLabelSize();
836
837 for( int i = 0; i < m_itemsGrid->GetNumberCols(); i++ )
838 {
839 if( i == 1 )
840 continue;
841
842 itemsWidth -= m_itemsGrid->GetColSize( i );
843 }
844
845 m_itemsGrid->SetColSize(
846 1, std::max( itemsWidth, m_itemsGrid->GetVisibleWidth( 0, true, false ) ) );
847
848 // Update the width private layers grid
849 m_privateLayersGrid->SetColSize( 0, std::max( m_privateLayersGrid->GetClientSize().x,
851
852 // Update the width net tie pad groups grid
853 m_padGroupsGrid->SetColSize( 0, std::max( m_padGroupsGrid->GetClientSize().x,
855
856 // Update the width of the 3D panel
858}
859
860
862{
863 // Handle a delayed focus. The delay allows us to:
864 // a) change focus when the error was triggered from within a killFocus handler
865 // b) show the correct notebook page in the background before the error dialog comes up
866 // when triggered from an OK or a notebook page change
867
868 if( static_cast<int>( m_delayedFocusPage ) >= 0 )
869 {
870 if( m_NoteBook->GetSelection() != static_cast<int>( m_delayedFocusPage ) )
871 m_NoteBook->ChangeSelection( static_cast<int>( m_delayedFocusPage ) );
872
873 m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_UNKNOWN;
874 }
875
876 if( !m_delayedErrorMessage.IsEmpty() )
877 {
878 // We will re-enter this routine when the error dialog is displayed, so make
879 // sure we don't keep putting up more dialogs.
880 wxString msg = m_delayedErrorMessage;
881 m_delayedErrorMessage = wxEmptyString;
882
883 // Do not use DisplayErrorMessage(); it screws up window order on Mac
884 DisplayError( nullptr, msg );
885 }
886
888 {
889 m_delayedFocusCtrl->SetFocus();
890
891 if( wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_delayedFocusCtrl ) )
892 textEntry->SelectAll();
893
894 m_delayedFocusCtrl = nullptr;
895 }
896 else if( m_delayedFocusGrid )
897 {
898 m_delayedFocusGrid->SetFocus();
901
903 m_delayedFocusGrid->EnableCellEditControl( true );
904
905 m_delayedFocusGrid->ShowCellEditControl();
906
907 m_delayedFocusGrid = nullptr;
910 }
911}
912
913
915{
916 wxSize new_size = aEvent.GetSize();
917
918 if( ( !m_itemsGrid->IsCellEditControlShown() || m_lastRequestedSize != new_size )
919 && m_gridSize != new_size )
920 {
921 m_gridSize = new_size;
922
923 // A trick to fix a cosmetic issue: when, in m_itemsGrid, a layer selector widget has
924 // the focus (is activated in column 6) when resizing the grid, the widget is not moved.
925 // So just change the widget having the focus in this case
926 if( m_NoteBook->GetSelection() == 0 && !m_itemsGrid->HasFocus() )
927 {
928 int col = m_itemsGrid->GetGridCursorCol();
929
930 if( col == 6 ) // a layer selector widget can be activated
931 m_itemsGrid->SetFocus();
932 }
933
935 }
936
937 // We store this value to check whether the dialog is changing size. This might indicate
938 // that the user is scaling the dialog with an editor shown. Some editors do not close
939 // (at least on GTK) when the user drags a dialog corner
940 m_lastRequestedSize = new_size;
941
942 // Always propagate for a grid repaint (needed if the height changes, as well as width)
943 aEvent.Skip();
944}
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
BASE_SET & set(size_t pos=std::numeric_limits< size_t >::max(), bool value=true)
Definition: base_set.h:61
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:240
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:276
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:289
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:757
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:575
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 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:224
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition: eda_text.cpp:373
int GetTextWidth() const
Definition: eda_text.h:221
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:196
int GetTextThickness() const
Definition: eda_text.h:122
void SetItalic(bool aItalic)
Definition: eda_text.cpp:212
VECTOR2I GetTextSize() const
Definition: eda_text.h:218
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:238
wxString GetLibDescription() const
Definition: footprint.h:246
ZONE_CONNECTION GetLocalZoneConnection() const
Definition: footprint.h:277
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:2209
PCB_FIELD * AddField(const PCB_FIELD &aField)
Add a field to the symbol.
Definition: footprint.cpp:590
void SetKeywords(const wxString &aKeywords)
Definition: footprint.h:250
void SetAttributes(int aAttributes)
Definition: footprint.h:280
std::optional< int > GetLocalSolderPasteMargin() const
Definition: footprint.h:270
void SetPrivateLayers(LSET aLayers)
Adds an item to the container.
Definition: footprint.h:131
std::optional< int > GetLocalClearance() const
Definition: footprint.h:264
int GetAttributes() const
Definition: footprint.h:279
LSET GetPrivateLayers() const
Definition: footprint.h:130
const std::vector< wxString > & GetNetTiePadGroups() const
Definition: footprint.h:328
const LIB_ID & GetFPID() const
Definition: footprint.h:237
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with PCB_TEXTs.
Definition: footprint.cpp:575
std::optional< double > GetLocalSolderPasteMarginRatio() const
Definition: footprint.h:273
KIID GetLink() const
Definition: footprint.h:841
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:2220
void SetLibDescription(const wxString &aDesc)
Definition: footprint.h:247
void SetLocalClearance(std::optional< int > aClearance)
Definition: footprint.h:265
std::optional< int > GetLocalSolderMaskMargin() const
Definition: footprint.h:267
wxString GetKeywords() const
Definition: footprint.h:249
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:66
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:35
LSEQ UIOrder() const
Definition: lset.cpp:865
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:392
static LSET AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
Definition: lset.cpp:800
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:732
wxString m_FootprintTextShownColumns
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
PCBNEW_SETTINGS * GetPcbNewSettings() const
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:71
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:42
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:691
void ShowHideColumns(const wxString &shownColumns)
Show/hide the grid columns based on a tokenized string of shown column indexes.
Definition: wx_grid.cpp:444
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:267
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:400
wxString GetShownColumnsAsString()
Get a tokenized string containing the shown column indexes.
Definition: wx_grid.cpp:414
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:594
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.
static bool footprintIsFromBoard(FOOTPRINT *aFootprint)
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:75
@ FP_DNP
Definition: footprint.h:82
@ FP_ALLOW_MISSING_COURTYARD
Definition: footprint.h:81
@ FP_EXCLUDE_FROM_POS_FILES
Definition: footprint.h:76
@ FP_BOARD_ONLY
Definition: footprint.h:78
@ FP_EXCLUDE_FROM_BOM
Definition: footprint.h:77
@ FP_THROUGH_HOLE
Definition: footprint.h:74
@ FP_ALLOW_SOLDERMASK_BRIDGES
Definition: footprint.h:80
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
KIID niluuid(0)
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ Edge_Cuts
Definition: layer_ids.h:113
@ User_9
Definition: layer_ids.h:131
@ Margin
Definition: layer_ids.h:114
@ User_1
Definition: layer_ids.h:123
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:875
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.
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:121
Custom text control validator definitions.
@ THERMAL
Use thermal relief for pads.
@ NONE
Pads are not covered.
@ FULL
pads are covered by copper