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{
231
232 // Prevents crash bug in wxGrid's d'tor
235
236 // Delete the GRID_TRICKS.
237 m_itemsGrid->PopEventHandler( true );
238 m_privateLayersGrid->PopEventHandler( true );
239 m_padGroupsGrid->PopEventHandler( true );
240
241 m_page = static_cast<NOTEBOOK_PAGES>( m_NoteBook->GetSelection() );
242
243 // the GL canvas on the 3D models page has to be visible before it is destroyed
244 m_NoteBook->SetSelection( static_cast<int>( NOTEBOOK_PAGES::PAGE_3D_MODELS ) );
245}
246
247
249{
250 LIB_ID fpID = m_footprint->GetFPID();
251 wxString footprintName = fpID.GetLibItemName();
252
253 m_FootprintNameCtrl->ChangeValue( footprintName );
254
256 m_KeywordCtrl->SetValue( m_footprint->GetKeywords() );
257
258 if( !wxDialog::TransferDataToWindow() )
259 return false;
260
261 if( !m_PanelGeneral->TransferDataToWindow() )
262 return false;
263
264 // Add the models to the panel
266 return false;
267
268 // Footprint Fields
269 for( PCB_FIELD* field : m_footprint->GetFields() )
270 m_fields->push_back( *field );
271
272 // Notify the grid
273 wxGridTableMessage tmsg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
275 m_itemsGrid->ProcessTableMessage( tmsg );
276
278 m_componentType->SetSelection( 0 );
279 else if( m_footprint->GetAttributes() & FP_SMD )
280 m_componentType->SetSelection( 1 );
281 else
282 m_componentType->SetSelection( 2 );
283
284 // Private layers
285 for( PCB_LAYER_ID privateLayer : m_footprint->GetPrivateLayers().UIOrder() )
286 m_privateLayers->push_back( privateLayer );
287
288 // Notify the grid
289 wxGridTableMessage gridTableMessagesg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
291 m_privateLayersGrid->ProcessTableMessage( gridTableMessagesg );
292
297 m_cbDNP->SetValue( m_footprint->GetAttributes() & FP_DNP );
298
299 // Local Clearances
300
301 if( m_footprint->GetLocalClearance().has_value() )
303 else
304 m_netClearance.SetValue( wxEmptyString );
305
306 if( m_footprint->GetLocalSolderMaskMargin().has_value() )
308 else
309 m_solderMask.SetValue( wxEmptyString );
310
311 if( m_footprint->GetLocalSolderPasteMargin().has_value() )
313 else
314 m_solderPaste.SetValue( wxEmptyString );
315
318 else
319 m_solderPasteRatio.SetValue( wxEmptyString );
320
322
324 {
325 default:
326 case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
327 case ZONE_CONNECTION::FULL: m_ZoneConnectionChoice->SetSelection( 1 ); break;
328 case ZONE_CONNECTION::THERMAL: m_ZoneConnectionChoice->SetSelection( 2 ); break;
329 case ZONE_CONNECTION::NONE: m_ZoneConnectionChoice->SetSelection( 3 ); break;
330 }
331
332 for( const wxString& group : m_footprint->GetNetTiePadGroups() )
333 {
334 if( !group.IsEmpty() )
335 {
336 m_padGroupsGrid->AppendRows( 1 );
337 m_padGroupsGrid->SetCellValue( m_padGroupsGrid->GetNumberRows() - 1, 0, group );
338 }
339 }
340
341 // Items grid
342 for( int col = 0; col < m_itemsGrid->GetNumberCols(); col++ )
343 {
344 // Adjust min size to the column label size
345 m_itemsGrid->SetColMinimalWidth( col, m_itemsGrid->GetVisibleWidth( col, true, false ) );
346 // Adjust the column size.
347 int col_size = m_itemsGrid->GetVisibleWidth( col );
348
349 if( col == PFC_LAYER ) // This one's a drop-down. Check all possible values.
350 {
351 BOARD* board = m_footprint->GetBoard();
352
353 for( PCB_LAYER_ID layer : board->GetEnabledLayers().Seq() )
354 col_size = std::max( col_size, GetTextExtent( board->GetLayerName( layer ) ).x );
355
356 // Swatch and gaps:
357 col_size += KiROUND( 14 * GetDPIScaleFactor() ) + 12;
358 }
359
360 if( m_itemsGrid->IsColShown( col ) )
361 m_itemsGrid->SetColSize( col, col_size );
362 }
363
364 m_itemsGrid->SetRowLabelSize( 0 );
365
366 Layout();
368
369 return true;
370}
371
372
374{
375 if( aFootprintName.IsEmpty() )
376 {
377 m_delayedErrorMessage = _( "Footprint must have a name." );
378 return false;
379 }
380 else if( !FOOTPRINT::IsLibNameValid( aFootprintName ) )
381 {
382 m_delayedErrorMessage.Printf( _( "Footprint name may not contain '%s'." ),
384 return false;
385 }
386
387 return true;
388}
389
390
392{
394 return false;
395
396 if( !DIALOG_SHIM::Validate() )
397 return false;
398
399 // First, test for invalid chars in footprint name
400 wxString footprintName = m_FootprintNameCtrl->GetValue();
401
402 if( !checkFootprintName( footprintName ) )
403 {
404 if( m_NoteBook->GetSelection() != 0 )
405 m_NoteBook->SetSelection( 0 );
406
408 m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_GENERAL;
409
410 return false;
411 }
412
413 // Check for valid field text properties
414 for( size_t i = 0; i < m_fields->size(); ++i )
415 {
416 PCB_FIELD& field = m_fields->at( i );
417
418 // Check for missing field names.
419 if( field.GetName( false ).IsEmpty() )
420 {
422 m_delayedErrorMessage = wxString::Format( _( "Fields must have a name." ) );
425
426 return false;
427 }
428
430 int maxSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
431
432 if( field.GetTextWidth() < minSize || field.GetTextWidth() > maxSize )
433 {
435 m_delayedErrorMessage = wxString::Format( _( "The text width must be between %s and %s." ),
437 m_frame->StringFromValue( maxSize, true ) );
440
441 return false;
442 }
443
444 if( field.GetTextHeight() < minSize || field.GetTextHeight() > maxSize )
445 {
447 m_delayedErrorMessage = wxString::Format( _( "The text height must be between %s and %s." ),
449 m_frame->StringFromValue( maxSize, true ) );
452
453 return false;
454 }
455
456 // Test for acceptable values for thickness and size and clamp if fails
457 int maxPenWidth = Clamp_Text_PenSize( field.GetTextThickness(), field.GetTextSize() );
458
459 if( field.GetTextThickness() > maxPenWidth )
460 {
461 m_itemsGrid->SetCellValue( i, PFC_THICKNESS,
462 m_frame->StringFromValue( maxPenWidth, true ) );
463
465 m_delayedErrorMessage = _( "The text thickness is too large for the text size.\n"
466 "It will be clamped." );
469
470 return false;
471 }
472 }
473
474 if( !m_netClearance.Validate( 0, INT_MAX ) )
475 return false;
476
477 return true;
478}
479
480
482{
483 if( !Validate() )
484 return false;
485
486 if( !DIALOG_SHIM::TransferDataFromWindow() )
487 return false;
488
492 {
493 return false;
494 }
495
496 // This only commits the editor, model updating is done below so it is inside
497 // the commit
499 return false;
500
502 BOARD_COMMIT commit( m_frame );
503 commit.Modify( m_footprint );
504
505 LIB_ID fpID = m_footprint->GetFPID();
506 fpID.SetLibItemName( m_FootprintNameCtrl->GetValue() );
507 m_footprint->SetFPID( fpID );
508
510 m_footprint->SetKeywords( m_KeywordCtrl->GetValue() );
511
512 // Update fields
513
514 std::vector<PCB_FIELD*> items_to_remove;
515 size_t i = 0;
516
517 for( PCB_FIELD* field : m_footprint->GetFields() )
518 {
519 // copy grid table entries till we run out, then delete any remaining texts
520 if( i < m_fields->size() )
521 *field = m_fields->at( i++ );
522 else
523 items_to_remove.push_back( field );
524 }
525
526 // Remove text items:
528
529 for( PCB_TEXT* item : items_to_remove )
530 {
531 selTool->RemoveItemFromSel( item );
532 view->Remove( item );
533 item->DeleteStructure();
534 }
535
536 // if there are still grid table entries, create new fields for them
537 while( i < m_fields->size() )
538 view->Add( m_footprint->AddField( m_fields->at( i++ ) ) );
539
540 LSET privateLayers;
541
542 for( PCB_LAYER_ID layer : *m_privateLayers )
543 privateLayers.set( layer );
544
545 m_footprint->SetPrivateLayers( privateLayers );
546
547 int attributes = 0;
548
549 switch( m_componentType->GetSelection() )
550 {
551 case 0: attributes |= FP_THROUGH_HOLE; break;
552 case 1: attributes |= FP_SMD; break;
553 default: break;
554 }
555
556 if( m_boardOnly->GetValue() )
557 attributes |= FP_BOARD_ONLY;
558
559 if( m_excludeFromPosFiles->GetValue() )
560 attributes |= FP_EXCLUDE_FROM_POS_FILES;
561
562 if( m_excludeFromBOM->GetValue() )
563 attributes |= FP_EXCLUDE_FROM_BOM;
564
565 if( m_noCourtyards->GetValue() )
566 attributes |= FP_ALLOW_MISSING_COURTYARD;
567
568 if( m_cbDNP->GetValue() )
569 attributes |= FP_DNP;
570
571 if( m_allowBridges->GetValue() )
572 attributes |= FP_ALLOW_SOLDERMASK_BRIDGES;
573
574 m_footprint->SetAttributes( attributes );
575
576 // Initialize mask clearances
577 if( m_netClearance.IsNull() )
579 else
580 m_footprint->SetLocalClearance( m_netClearance.GetValue() );
581
582 if( m_solderMask.IsNull() )
583 m_footprint->SetLocalSolderMaskMargin( {} );
584 else
585 m_footprint->SetLocalSolderMaskMargin( m_solderMask.GetValue() );
586
587 if( m_solderPaste.IsNull() )
588 m_footprint->SetLocalSolderPasteMargin( {} );
589 else
590 m_footprint->SetLocalSolderPasteMargin( m_solderPaste.GetValue() );
591
592 if( m_solderPasteRatio.IsNull() )
593 m_footprint->SetLocalSolderPasteMarginRatio( {} );
594 else
595 m_footprint->SetLocalSolderPasteMarginRatio( m_solderPasteRatio.GetDoubleValue() / 100.0 );
596
597 switch( m_ZoneConnectionChoice->GetSelection() )
598 {
599 default:
600 case 0: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::INHERITED ); break;
601 case 1: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::FULL ); break;
602 case 2: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::THERMAL ); break;
603 case 3: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::NONE ); break;
604 }
605
606 m_footprint->ClearNetTiePadGroups();
607
608 for( int ii = 0; ii < m_padGroupsGrid->GetNumberRows(); ++ii )
609 {
610 wxString group = m_padGroupsGrid->GetCellValue( ii, 0 );
611
612 if( !group.IsEmpty() )
613 m_footprint->AddNetTiePadGroup( group );
614 }
615
616 // Copy the models from the panel to the footprint
617 std::vector<FP_3DMODEL>& panelList = m_3dPanel->GetModelList();
618 std::vector<FP_3DMODEL>* fpList = &m_footprint->Models();
619 fpList->clear();
620 fpList->insert( fpList->end(), panelList.begin(), panelList.end() );
621
622 commit.Push( _( "Edit Footprint Properties" ) );
623
624 return true;
625}
626
627
628static bool footprintIsFromBoard( FOOTPRINT* aFootprint )
629{
630 return aFootprint->GetLink() != niluuid;
631}
632
633
635{
637 {
638 // Currently: nothing to do
639 }
640}
641
642
644{
646 return;
647
648 const BOARD_DESIGN_SETTINGS& dsnSettings = m_frame->GetDesignSettings();
649
650 int fieldId = (int) m_fields->size();
651 PCB_FIELD newField( m_footprint, m_fields->size(),
653
654 // Set active layer if legal; otherwise copy layer from previous text item
656 newField.SetLayer( m_frame->GetActiveLayer() );
657 else
658 newField.SetLayer( m_fields->at( m_fields->size() - 1 ).GetLayer() );
659
660 newField.SetTextSize( dsnSettings.GetTextSize( newField.GetLayer() ) );
661 newField.SetTextThickness( dsnSettings.GetTextThickness( newField.GetLayer() ) );
662 newField.SetItalic( dsnSettings.GetTextItalic( newField.GetLayer() ) );
663
664 m_fields->push_back( newField );
665
666 // notify the grid
667 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
668 m_itemsGrid->ProcessTableMessage( msg );
669
670 m_itemsGrid->SetFocus();
671 m_itemsGrid->MakeCellVisible( m_fields->size() - 1, 0 );
672 m_itemsGrid->SetGridCursor( m_fields->size() - 1, 0 );
673
674 m_itemsGrid->EnableCellEditControl( true );
675 m_itemsGrid->ShowCellEditControl();
676}
677
678
680{
682 return;
683
684 wxArrayInt selectedRows = m_itemsGrid->GetSelectedRows();
685
686 if( selectedRows.empty() && m_itemsGrid->GetGridCursorRow() >= 0 )
687 selectedRows.push_back( m_itemsGrid->GetGridCursorRow() );
688
689 if( selectedRows.empty() )
690 return;
691
692 for( int row : selectedRows )
693 {
694 if( row < MANDATORY_FIELDS )
695 {
696 DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
698 return;
699 }
700 }
701
702 m_itemsGrid->CommitPendingChanges( true /* quiet mode */ );
703 m_itemsGrid->ClearSelection();
704
705 // Reverse sort so deleting a row doesn't change the indexes of the other rows.
706 selectedRows.Sort( []( int* first, int* second )
707 {
708 return *second - *first;
709 } );
710
711 for( int row : selectedRows )
712 {
713 m_fields->erase( m_fields->begin() + row );
714
715 // notify the grid
716 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 );
717 m_itemsGrid->ProcessTableMessage( msg );
718
719 if( m_itemsGrid->GetNumberRows() > 0 )
720 {
721 m_itemsGrid->MakeCellVisible( std::max( 0, row-1 ), m_itemsGrid->GetGridCursorCol() );
722 m_itemsGrid->SetGridCursor( std::max( 0, row-1 ), m_itemsGrid->GetGridCursorCol() );
723 }
724 }
725}
726
727
729{
731 return;
732
733 PCB_LAYER_ID nextLayer = User_1;
734
735 while( alg::contains( *m_privateLayers, nextLayer ) && nextLayer < User_9 )
736 nextLayer = ToLAYER_ID( nextLayer + 1 );
737
738 m_privateLayers->push_back( nextLayer );
739
740 // notify the grid
741 wxGridTableMessage msg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
742 m_privateLayersGrid->ProcessTableMessage( msg );
743
744 m_privateLayersGrid->SetFocus();
745 m_privateLayersGrid->MakeCellVisible( m_privateLayers->size() - 1, 0 );
746 m_privateLayersGrid->SetGridCursor( m_privateLayers->size() - 1, 0 );
747}
748
749
751{
753 return;
754
755 int curRow = m_privateLayersGrid->GetGridCursorRow();
756
757 if( curRow < 0 )
758 return;
759
760 m_privateLayers->erase( m_privateLayers->begin() + curRow );
761
762 // notify the grid
763 wxGridTableMessage msg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_DELETED, curRow, 1 );
764 m_privateLayersGrid->ProcessTableMessage( msg );
765
766 if( m_privateLayersGrid->GetNumberRows() > 0 )
767 {
768 m_privateLayersGrid->MakeCellVisible( std::max( 0, curRow-1 ),
769 m_privateLayersGrid->GetGridCursorCol() );
770 m_privateLayersGrid->SetGridCursor( std::max( 0, curRow-1 ),
771 m_privateLayersGrid->GetGridCursorCol() );
772 }
773}
774
775
777{
779 return;
780
781 m_padGroupsGrid->AppendRows( 1 );
782
783 m_padGroupsGrid->SetFocus();
784 m_padGroupsGrid->MakeCellVisible( m_padGroupsGrid->GetNumberRows() - 1, 0 );
785 m_padGroupsGrid->SetGridCursor( m_padGroupsGrid->GetNumberRows() - 1, 0 );
786
787 m_padGroupsGrid->EnableCellEditControl( true );
788 m_padGroupsGrid->ShowCellEditControl();
789}
790
791
793{
795 return;
796
797 wxArrayInt selectedRows = m_padGroupsGrid->GetSelectedRows();
798 int curRow = m_padGroupsGrid->GetGridCursorRow();
799
800 if( selectedRows.empty() && curRow >= 0 && curRow < m_padGroupsGrid->GetNumberRows() )
801 selectedRows.Add( curRow );
802
803 for( int ii = selectedRows.Count() - 1; ii >= 0; --ii )
804 {
805 int row = selectedRows.Item( ii );
806 m_padGroupsGrid->DeleteRows( row, 1 );
807 curRow = std::min( curRow, row );
808 }
809
810 curRow = std::max( 0, curRow - 1 );
811 m_padGroupsGrid->MakeCellVisible( curRow, m_padGroupsGrid->GetGridCursorCol() );
812 m_padGroupsGrid->SetGridCursor( curRow, m_padGroupsGrid->GetGridCursorCol() );
813}
814
815
817{
818 // Account for scroll bars
820
821 itemsWidth -= m_itemsGrid->GetRowLabelSize();
822
823 for( int i = 0; i < m_itemsGrid->GetNumberCols(); i++ )
824 {
825 if( i == 1 )
826 continue;
827
828 itemsWidth -= m_itemsGrid->GetColSize( i );
829 }
830
831 m_itemsGrid->SetColSize(
832 1, std::max( itemsWidth, m_itemsGrid->GetVisibleWidth( 0, true, false ) ) );
833
834 // Update the width private layers grid
835 m_privateLayersGrid->SetColSize( 0, std::max( m_privateLayersGrid->GetClientSize().x,
837
838 // Update the width net tie pad groups grid
839 m_padGroupsGrid->SetColSize( 0, std::max( m_padGroupsGrid->GetClientSize().x,
841
842 // Update the width of the 3D panel
844}
845
846
848{
849 // Handle a delayed focus. The delay allows us to:
850 // a) change focus when the error was triggered from within a killFocus handler
851 // b) show the correct notebook page in the background before the error dialog comes up
852 // when triggered from an OK or a notebook page change
853
854 if( static_cast<int>( m_delayedFocusPage ) >= 0 )
855 {
856 if( m_NoteBook->GetSelection() != static_cast<int>( m_delayedFocusPage ) )
857 m_NoteBook->ChangeSelection( static_cast<int>( m_delayedFocusPage ) );
858
859 m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_UNKNOWN;
860 }
861
862 if( !m_delayedErrorMessage.IsEmpty() )
863 {
864 // We will re-enter this routine when the error dialog is displayed, so make
865 // sure we don't keep putting up more dialogs.
866 wxString msg = m_delayedErrorMessage;
867 m_delayedErrorMessage = wxEmptyString;
868
869 // Do not use DisplayErrorMessage(); it screws up window order on Mac
870 DisplayError( nullptr, msg );
871 }
872
874 {
875 m_delayedFocusCtrl->SetFocus();
876
877 if( wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_delayedFocusCtrl ) )
878 textEntry->SelectAll();
879
880 m_delayedFocusCtrl = nullptr;
881 }
882 else if( m_delayedFocusGrid )
883 {
884 m_delayedFocusGrid->SetFocus();
887
889 m_delayedFocusGrid->EnableCellEditControl( true );
890
891 m_delayedFocusGrid->ShowCellEditControl();
892
893 m_delayedFocusGrid = nullptr;
896 }
897}
898
899
901{
902 wxSize new_size = aEvent.GetSize();
903
904 if( ( !m_itemsGrid->IsCellEditControlShown() || m_lastRequestedSize != new_size )
905 && m_gridSize != new_size )
906 {
907 m_gridSize = new_size;
908
909 // A trick to fix a cosmetic issue: when, in m_itemsGrid, a layer selector widget has
910 // the focus (is activated in column 6) when resizing the grid, the widget is not moved.
911 // So just change the widget having the focus in this case
912 if( m_NoteBook->GetSelection() == 0 && !m_itemsGrid->HasFocus() )
913 {
914 int col = m_itemsGrid->GetGridCursorCol();
915
916 if( col == 6 ) // a layer selector widget can be activated
917 m_itemsGrid->SetFocus();
918 }
919
921 }
922
923 // We store this value to check whether the dialog is changing size. This might indicate
924 // that the user is scaling the dialog with an editor shown. Some editors do not close
925 // (at least on GTK) when the user drags a dialog corner
926 m_lastRequestedSize = new_size;
927
928 // Always propagate for a grid repaint (needed if the height changes, as well as width)
929 aEvent.Skip();
930}
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:62
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:758
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:248
wxString GetLibDescription() const
Definition: footprint.h:256
ZONE_CONNECTION GetLocalZoneConnection() const
Definition: footprint.h:287
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:2214
PCB_FIELD * AddField(const PCB_FIELD &aField)
Add a field to the symbol.
Definition: footprint.cpp:595
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:141
std::optional< int > GetLocalClearance() const
Definition: footprint.h:274
int GetAttributes() const
Definition: footprint.h:289
LSET GetPrivateLayers() const
Definition: footprint.h:140
const std::vector< wxString > & GetNetTiePadGroups() const
Definition: footprint.h:338
const LIB_ID & GetFPID() const
Definition: footprint.h:247
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with PCB_TEXTs.
Definition: footprint.cpp:580
std::optional< double > GetLocalSolderPasteMarginRatio() const
Definition: footprint.h:283
KIID GetLink() const
Definition: footprint.h:851
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:2225
void SetLibDescription(const wxString &aDesc)
Definition: footprint.h:257
void SetLocalClearance(std::optional< int > aClearance)
Definition: footprint.h:275
std::optional< int > GetLocalSolderMaskMargin() const
Definition: footprint.h:277
wxString GetKeywords() const
Definition: footprint.h:259
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
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: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, bool aQuiet=false)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:100
Custom text control validator definitions.
@ THERMAL
Use thermal relief for pads.
@ NONE
Pads are not covered.
@ FULL
pads are covered by copper