KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_footprint_properties.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) 2016 Mario Luzeiro <[email protected]>
5 * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
6 * Copyright (C) 2015 Dick Hollenbeck, [email protected]
7 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
28#include <bitmaps.h>
29#include <board_commit.h>
31#include <board.h>
32#include <footprint.h>
33#include <confirm.h>
35#include <filename_resolver.h>
36#include <pcb_edit_frame.h>
37#include <pcbnew_settings.h>
38#include <pgm_base.h>
39#include <project_pcb.h>
40#include <kiplatform/ui.h>
49#include <tool/tool_manager.h>
51
52
53int DIALOG_FOOTPRINT_PROPERTIES::m_page = 0; // remember the last open page during session
54
55
58 m_frame( aParent ),
59 m_footprint( aFootprint ),
68 m_initialized( false ),
69 m_gridSize( 0, 0 ),
71{
72 // Create the extra panels. Embedded files is referenced by the 3D model panel.
75
76 m_NoteBook->AddPage( m_3dPanel, _("3D Models"), false );
77 m_NoteBook->AddPage( m_embeddedFiles, _( "Embedded Files" ) );
78
79 // Configure display origin transforms
82
83 std::vector<EMBEDDED_FILES*> embeddedFilesStack;
84 embeddedFilesStack.push_back( m_embeddedFiles->GetLocalFiles() );
85 embeddedFilesStack.push_back( m_frame->GetBoard()->GetEmbeddedFiles() );
86
87 m_fields = new PCB_FIELDS_GRID_TABLE( m_frame, this, embeddedFilesStack );
88
89 m_delayedErrorMessage = wxEmptyString;
90 m_delayedFocusGrid = nullptr;
93 m_initialFocus = false;
94
95 // Give an icon
96 wxIcon icon;
97 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_modedit ) );
98 SetIcon( icon );
99
100 m_itemsGrid->SetTable( m_fields );
101 m_itemsGrid->PushEventHandler( new GRID_TRICKS( m_itemsGrid ) );
102
103 // Show/hide text item columns according to the user's preference
104 if( PCBNEW_SETTINGS* cfg = m_frame->GetPcbNewSettings() )
105 m_itemsGrid->ShowHideColumns( cfg->m_FootprintTextShownColumns );
106
108 m_orientation.SetPrecision( 3 );
109
110 // Set predefined rotations in combo dropdown, according to the locale floating point
111 // separator notation
112 double rot_list[] = { 0.0, 90.0, -90.0, 180.0 };
113
114 for( size_t ii = 0; ii < m_orientationCtrl->GetCount() && ii < 4; ++ii )
115 m_orientationCtrl->SetString( ii, wxString::Format( "%.1f", rot_list[ii] ) );
116
117 // Set font size for items showing long strings:
118 wxFont infoFont = KIUI::GetSmallInfoFont( this );
119 m_libraryIDLabel->SetFont( infoFont );
120 m_tcLibraryID->SetFont( infoFont );
121
122 infoFont = KIUI::GetInfoFont( this ).Italic();
123 m_staticTextInfoCopper->SetFont( infoFont );
124 m_staticTextInfoPaste->SetFont( infoFont );
125
126 m_NoteBook->SetSelection( m_page );
127
128 if( m_page == 0 )
129 {
133 }
134 else if( m_page == 1 )
135 {
137 }
138
139 m_solderPaste.SetNegativeZero();
140
142 m_solderPasteRatio.SetNegativeZero();
143
144 // Configure button logos
147
148 m_tcLibraryID->SetBackgroundColour( KIPLATFORM::UI::GetDialogBGColour() );
149
150 // We can't set the tab order through wxWidgets due to shortcomings in their mnemonics
151 // implementation on MSW
152 m_tabOrder = {
163 m_cbDNP,
170 };
171
173
174 // The 3D model tab was added after the base dtor. The final dialog size needs to be set
175 // accordingly.
176 SetSizer( m_GeneralBoxSizer );
177 Layout();
178 m_GeneralBoxSizer->Fit( this );
179
181}
182
183
185{
186 if( PCBNEW_SETTINGS* cfg = m_frame->GetPcbNewSettings() )
187 cfg->m_FootprintTextShownColumns = m_itemsGrid->GetShownColumnsAsString();
188
189 // Prevents crash bug in wxGrid's d'tor
190 m_itemsGrid->DestroyTable( m_fields );
191
192 // Delete the GRID_TRICKS.
193 m_itemsGrid->PopEventHandler( true );
194
195 // free the memory used by all models, otherwise models which were
196 // browsed but not used would consume memory
198
199 // the GL canvas has to be visible before it is destroyed
200 m_page = m_NoteBook->GetSelection();
201 m_NoteBook->SetSelection( 1 );
202}
203
204
206{
208 {
210 Close();
211 }
212}
213
214
216{
218 {
220 Close();
221 }
222}
223
224
226{
228 {
230 Close();
231 }
232}
233
234
236{
238 {
240 Close();
241 }
242}
243
244
246{
247 if( !wxDialog::TransferDataToWindow() )
248 return false;
249
250 if( !m_PanelGeneral->TransferDataToWindow() )
251 return false;
252
253 // Add the models to the panel
254 if( !m_3dPanel->TransferDataToWindow() )
255 return false;
256
257 if( !m_embeddedFiles->TransferDataToWindow() )
258 return false;
259
260 // Footprint Fields
261 for( PCB_FIELD* srcField : m_footprint->GetFields() )
262 {
263 PCB_FIELD field( *srcField );
264 field.SetText( m_footprint->GetBoard()->ConvertKIIDsToCrossReferences( field.GetText() ) );
265
266 m_fields->push_back( field );
267 }
268
269 // notify the grid
270 wxGridTableMessage tmsg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->GetNumberRows() );
271 m_itemsGrid->ProcessTableMessage( tmsg );
272
273 // Footprint Properties
274
275 m_posX.SetValue( m_footprint->GetPosition().x );
276 m_posY.SetValue( m_footprint->GetPosition().y );
277
278 m_BoardSideCtrl->SetSelection( (m_footprint->GetLayer() == B_Cu) ? 1 : 0 );
279
280 EDA_ANGLE orientation = m_footprint->GetOrientation();
281 m_orientation.SetAngleValue( orientation.Normalize180() );
282
283 m_cbLocked->SetValue( m_footprint->IsLocked() );
284 m_cbLocked->SetToolTip( _( "Locked footprints cannot be freely moved or oriented on the canvas and can only be "
285 "selected when the 'Locked items' checkbox is checked in the selection filter." ) );
286
287 if( m_footprint->GetAttributes() & FP_THROUGH_HOLE )
288 m_componentType->SetSelection( 0 );
289 else if( m_footprint->GetAttributes() & FP_SMD )
290 m_componentType->SetSelection( 1 );
291 else
292 m_componentType->SetSelection( 2 );
293
294 m_boardOnly->SetValue( m_footprint->GetAttributes() & FP_BOARD_ONLY );
295 m_excludeFromPosFiles->SetValue( m_footprint->GetAttributes() & FP_EXCLUDE_FROM_POS_FILES );
296 m_excludeFromBOM->SetValue( m_footprint->GetAttributes() & FP_EXCLUDE_FROM_BOM );
297 m_cbDNP->SetValue( m_footprint->GetAttributes() & FP_DNP );
298
299 // Local Clearances
300
301 if( m_footprint->GetLocalClearance().has_value() )
302 m_netClearance.SetValue( m_footprint->GetLocalClearance().value() );
303 else
304 m_netClearance.SetValue( wxEmptyString );
305
306 if( m_footprint->GetLocalSolderMaskMargin().has_value() )
307 m_solderMask.SetValue( m_footprint->GetLocalSolderMaskMargin().value() );
308 else
309 m_solderMask.SetValue( wxEmptyString );
310
311 if( m_footprint->GetLocalSolderPasteMargin().has_value() )
312 m_solderPaste.SetValue( m_footprint->GetLocalSolderPasteMargin().value() );
313 else
314 m_solderPaste.SetValue( wxEmptyString );
315
316 if( m_footprint->GetLocalSolderPasteMarginRatio().has_value() )
317 m_solderPasteRatio.SetDoubleValue( m_footprint->GetLocalSolderPasteMarginRatio().value() * 100.0 );
318 else
319 m_solderPasteRatio.SetValue( wxEmptyString );
320
321 m_allowSolderMaskBridges->SetValue( m_footprint->AllowSolderMaskBridges() );
322
323 switch( m_footprint->GetLocalZoneConnection() )
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 wxString jumperGroups;
333
334 if( m_footprint->GetDuplicatePadNumbersAreJumpers() )
335 jumperGroups = _( "all pads with duplicate numbers" );
336
337 for( const std::set<wxString>& group : m_footprint->JumperPadGroups() )
338 {
339 wxString groupTxt;
340
341 for( const wxString& pinNumber : group )
342 {
343 if( !groupTxt.IsEmpty() )
344 groupTxt << ", ";
345
346 groupTxt << pinNumber;
347 }
348
349 if( !jumperGroups.IsEmpty() )
350 jumperGroups << "; ";
351
352 jumperGroups << "(" << groupTxt << ")";
353 }
354
355 if( jumperGroups.IsEmpty() )
356 {
357 m_jumperGroupsText->SetLabel( _( "none" ) );
359 }
360 else
361 {
362 m_jumperGroupsText->SetLabel( jumperGroups );
363 }
364
365 // Show the footprint's FPID.
366 m_tcLibraryID->SetValue( m_footprint->GetFPID().Format() );
367
368 for( int col = 0; col < m_itemsGrid->GetNumberCols(); col++ )
369 {
370 m_itemsGrid->SetColMinimalWidth( col, m_itemsGrid->GetVisibleWidth( col, true, false ) );
371
372 // Adjust the column size.
373 int col_size = m_itemsGrid->GetVisibleWidth( col );
374
375 if( col == PFC_LAYER ) // This one's a drop-down. Check all possible values.
376 {
377 BOARD* board = m_footprint->GetBoard();
378
379 for( PCB_LAYER_ID layer : board->GetEnabledLayers() )
380 col_size = std::max( col_size, GetTextExtent( board->GetLayerName( layer ) ).x );
381
382 // Swatch and gaps:
383 col_size += KiROUND( 14 * GetDPIScaleFactor() ) + 12;
384 }
385
386 if( m_itemsGrid->IsColShown( col ) )
387 m_itemsGrid->SetColSize( col, col_size );
388 }
389
390 m_itemsGrid->SetRowLabelSize( 0 );
391
392 Layout();
394 m_initialized = true;
395
396 return true;
397}
398
399
401{
402 if( !m_itemsGrid->CommitPendingChanges() )
403 return false;
404
405 if( !DIALOG_SHIM::Validate() )
406 return false;
407
408 // Validate texts.
409 for( size_t i = 0; i < m_fields->size(); ++i )
410 {
411 PCB_FIELD& field = m_fields->at( i );
412
413 // Check for missing field names.
414 if( field.GetName( false ).IsEmpty() )
415 {
417 m_delayedErrorMessage = wxString::Format( _( "Fields must have a name." ) );
420
421 return false;
422 }
423
424 int minSize = pcbIUScale.mmToIU( TEXT_MIN_SIZE_MM );
425 int maxSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
426 int width = m_frame->ValueFromString( m_itemsGrid->GetCellValue( i, PFC_WIDTH ) );
427 int height = m_frame->ValueFromString( m_itemsGrid->GetCellValue( i, PFC_HEIGHT ) );
428
429 if( width < minSize )
430 {
431 wxString min = m_frame->StringFromValue( minSize, true );
432
433 m_itemsGrid->SetCellValue( i, PFC_WIDTH, min );
434
436 m_delayedErrorMessage = wxString::Format( _( "Text width must be at least %s." ), min );
439
440 return false;
441 }
442 else if( width > maxSize )
443 {
444 wxString max = m_frame->StringFromValue( maxSize, true );
445
446 m_itemsGrid->SetCellValue( i, PFC_WIDTH, max );
447
449 m_delayedErrorMessage = wxString::Format( _( "Text width must be at most %s." ), max );
452
453 return false;
454 }
455
456 if( height < minSize )
457 {
458 wxString min = m_frame->StringFromValue( minSize, true );
459
460 m_itemsGrid->SetCellValue( i, PFC_HEIGHT, min );
461
463 m_delayedErrorMessage = wxString::Format( _( "Text height must be at least %s." ), min );
466
467 return false;
468 }
469 else if( height > maxSize )
470 {
471 wxString max = m_frame->StringFromValue( maxSize, true );
472
473 m_itemsGrid->SetCellValue( i, PFC_HEIGHT, max );
474
476 m_delayedErrorMessage = wxString::Format( _( "Text height must be at most %s." ), max );
479
480 return false;
481 }
482
483 // Test for acceptable values for thickness and size and clamp if fails
484 int maxPenWidth = ClampTextPenSize( field.GetTextThickness(), field.GetTextSize() );
485
486 if( field.GetTextThickness() > maxPenWidth )
487 {
488 wxString clamped = m_frame->StringFromValue( maxPenWidth, true );
489
490 m_itemsGrid->SetCellValue( i, PFC_THICKNESS, clamped );
491
493 m_delayedErrorMessage = wxString::Format( _( "Text thickness is too large for the text size.\n"
494 "It will be clamped at %s." ),
495 clamped );
498
499 return false;
500 }
501 }
502
503 if( !m_netClearance.Validate( 0, INT_MAX ) )
504 return false;
505
506 return true;
507}
508
509
511{
512 if( !Validate() )
513 return false;
514
515 if( !m_itemsGrid->CommitPendingChanges() )
516 return false;
517
518 KIGFX::PCB_VIEW* view = m_frame->GetCanvas()->GetView();
519 PCB_SELECTION_TOOL* selectionTool = m_frame->GetToolManager()->GetTool<PCB_SELECTION_TOOL>();
520 BOARD_COMMIT commit( m_frame );
521 commit.Modify( m_footprint );
522
523 // Make sure this happens inside a commit to capture any changed files
524 if( !m_3dPanel->TransferDataFromWindow() )
525 return false;
526
527 if( !m_embeddedFiles->TransferDataFromWindow() )
528 return false;
529
530 // Clear out embedded files that are no longer in use
531 std::set<wxString> files;
532 std::set<wxString> files_to_delete;
533
534 // Get the new files from the footprint fields
535 for( PCB_FIELD& field : *m_fields )
536 {
537 if( field.GetText().StartsWith( FILEEXT::KiCadUriPrefix ) )
538 files.insert( field.GetText() );
539 }
540
541 // Find any files referenced in the old fields that are not in the new fields
542 for( PCB_FIELD* field : m_footprint->GetFields() )
543 {
544 if( field->GetText().StartsWith( FILEEXT::KiCadUriPrefix ) )
545 {
546 if( files.find( field->GetText() ) == files.end() )
547 files_to_delete.insert( field->GetText() );
548 }
549 }
550
551 for( const wxString& file : files_to_delete )
552 {
553 wxString name = file.Mid( FILEEXT::KiCadUriPrefix.size() + 3 ); // Skip "kicad-embed://"
554 m_footprint->RemoveFile( name );
555 }
556
557 // Update fields
558 for( PCB_FIELD* existing : m_footprint->GetFields() )
559 delete existing;
560
561 m_footprint->GetFields().clear();
562
563 int ordinal = 42; // Arbitrarily larger than any mandatory FIELD_T ids.
564
565 for( PCB_FIELD& field : *m_fields )
566 {
567 PCB_FIELD* newField = field.CloneField();
568 newField->SetText( commit.GetBoard()->ConvertCrossReferencesToKIIDs( field.GetText() ) );
569
570 if( !field.IsMandatory() )
571 newField->SetOrdinal( ordinal++ );
572
573 m_footprint->Add( newField );
574 view->Add( newField );
575
576 if( newField->IsSelected() )
577 {
578 // The old copy was in the selection list, but this one is not. Remove the
579 // out-of-sync selection flag so we can re-add the field to the selection.
580 newField->ClearSelected();
581 selectionTool->AddItemToSel( newField, true );
582 }
583 }
584
585 // Initialize masks clearances
586 if( m_netClearance.IsNull() )
587 m_footprint->SetLocalClearance( {} );
588 else
589 m_footprint->SetLocalClearance( m_netClearance.GetValue() );
590
591 if( m_solderMask.IsNull() )
592 m_footprint->SetLocalSolderMaskMargin( {} );
593 else
594 m_footprint->SetLocalSolderMaskMargin( m_solderMask.GetValue() );
595
596 if( m_solderPaste.IsNull() )
597 m_footprint->SetLocalSolderPasteMargin( {} );
598 else
599 m_footprint->SetLocalSolderPasteMargin( m_solderPaste.GetValue() );
600
601 if( m_solderPasteRatio.IsNull() )
602 m_footprint->SetLocalSolderPasteMarginRatio( {} );
603 else
604 m_footprint->SetLocalSolderPasteMarginRatio( m_solderPasteRatio.GetDoubleValue() / 100.0 );
605
606 switch( m_ZoneConnectionChoice->GetSelection() )
607 {
608 default:
609 case 0: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::INHERITED ); break;
610 case 1: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::FULL ); break;
611 case 2: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::THERMAL ); break;
612 case 3: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::NONE ); break;
613 }
614
615 // Set Footprint Position
616 VECTOR2I pos( m_posX.GetValue(), m_posY.GetValue() );
617 m_footprint->SetPosition( pos );
618 m_footprint->SetLocked( m_cbLocked->GetValue() );
619
620 int attributes = 0;
621
622 switch( m_componentType->GetSelection() )
623 {
624 case 0: attributes |= FP_THROUGH_HOLE; break;
625 case 1: attributes |= FP_SMD; break;
626 default: break;
627 }
628
629 if( m_boardOnly->GetValue() )
630 attributes |= FP_BOARD_ONLY;
631
632 if( m_excludeFromPosFiles->GetValue() )
633 attributes |= FP_EXCLUDE_FROM_POS_FILES;
634
635 if( m_excludeFromBOM->GetValue() )
636 attributes |= FP_EXCLUDE_FROM_BOM;
637
638 if( m_cbDNP->GetValue() )
639 attributes |= FP_DNP;
640
641 m_footprint->SetAttributes( attributes );
642
643 m_footprint->SetAllowSolderMaskBridges( m_allowSolderMaskBridges->GetValue() );
644
645 EDA_ANGLE orient = m_orientation.GetAngleValue().Normalize();
646
647 if( m_footprint->GetOrientation() != orient )
648 m_footprint->Rotate( m_footprint->GetPosition(), orient - m_footprint->GetOrientation() );
649
650 // Set component side, that also have effect on the fields positions on board
651 bool change_layer = false;
652
653 if( m_BoardSideCtrl->GetSelection() == 0 ) // layer req = COMPONENT
654 {
655 if( m_footprint->GetLayer() == B_Cu )
656 change_layer = true;
657 }
658 else if( m_footprint->GetLayer() == F_Cu )
659 {
660 change_layer = true;
661 }
662
663 if( change_layer )
664 m_footprint->Flip( m_footprint->GetPosition(), m_frame->GetPcbNewSettings()->m_FlipDirection );
665
666 // Copy the models from the panel to the footprint
667 std::vector<FP_3DMODEL>& panelList = m_3dPanel->GetModelList();
668 std::vector<FP_3DMODEL>* fpList = &m_footprint->Models();
669 fpList->clear();
670 fpList->insert( fpList->end(), panelList.begin(), panelList.end() );
671
672 // This is a simple edit, we must create an undo entry
673 if( m_footprint->GetEditFlags() == 0 ) // i.e. not edited, or moved
674 commit.Push( _( "Edit Footprint Properties" ) );
675
677 return true;
678}
679
680
682{
683 m_itemsGrid->OnAddRow(
684 [&]() -> std::pair<int, int>
685 {
687
688 newField.SetVisible( false );
689 newField.SetLayer( m_footprint->GetLayer() == F_Cu ? F_Fab : B_Fab );
690 newField.SetFPRelativePosition( { 0, 0 } );
691 newField.StyleFromSettings( m_frame->GetDesignSettings() );
692
693 m_fields->push_back( newField );
694
695 // notify the grid
696 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
697 m_itemsGrid->ProcessTableMessage( msg );
698 OnModify();
699
700 return { m_fields->size() - 1, PFC_NAME };
701 } );
702}
703
704
706{
707 m_itemsGrid->OnDeleteRows(
708 [&]( int row )
709 {
710 if( row < m_fields->GetMandatoryRowCount() )
711 {
712 DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
713 m_fields->GetMandatoryRowCount() ) );
714 return false;
715 }
716
717 return true;
718 },
719 [&]( int row )
720 {
721 m_fields->erase( m_fields->begin() + row );
722
723 // notify the grid
724 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 );
725 m_itemsGrid->ProcessTableMessage( msg );
726 } );
727
728 OnModify();
729}
730
731
733{
734 // Account for scroll bars
736
737 itemsWidth -= m_itemsGrid->GetRowLabelSize();
738
739 for( int i = 0; i < m_itemsGrid->GetNumberCols(); i++ )
740 {
741 if( i == 1 )
742 continue;
743
744 itemsWidth -= m_itemsGrid->GetColSize( i );
745 }
746
747 m_itemsGrid->SetColSize( 1, std::max( itemsWidth, m_itemsGrid->GetVisibleWidth( 0, true, false ) ) );
748
749 // Update the width of the 3D panel
750 m_3dPanel->AdjustGridColumnWidths();
751}
752
753
755{
756 if( !m_initialized )
757 return;
758
759 // Handle a grid error. This is delayed to OnUpdateUI so that we can change focus
760 // even when the original validation was triggered from a killFocus event, and so
761 // that the corresponding notebook page can be shown in the background when triggered
762 // from an OK.
763 if( m_delayedFocusRow >= 0 )
764 {
765 // We will re-enter this routine if an error dialog is displayed, so make sure we
766 // zero out our member variables first.
767 wxGrid* grid = m_delayedFocusGrid;
768 int row = m_delayedFocusRow;
769 int col = m_delayedFocusColumn;
770 wxString msg = m_delayedErrorMessage;
771
772 m_delayedFocusGrid = nullptr;
775 m_delayedErrorMessage = wxEmptyString;
776
777 if( !msg.IsEmpty() )
778 {
779 // Do not use DisplayErrorMessage(); it screws up window order on Mac
780 DisplayError( nullptr, msg );
781 }
782
783 grid->SetFocus();
784 grid->MakeCellVisible( row, col );
785
786 // Selecting the first grid item only makes sense for the
787 // items grid
788 if( !m_initialFocus || grid == m_itemsGrid )
789 {
790 grid->SetGridCursor( row, col );
791
792 if( !( col == 0 && row < m_fields->GetMandatoryRowCount() ) )
793 grid->EnableCellEditControl( true );
794
795 grid->ShowCellEditControl();
796
797 if( grid == m_itemsGrid && row == 0 && col == 0 )
798 {
799 wxGridCellEditor* referenceEditor = grid->GetCellEditor( 0, 0 );
800
801 if( wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( referenceEditor->GetControl() ) )
802 KIUI::SelectReferenceNumber( textEntry );
803
804 referenceEditor->DecRef();
805 }
806 }
807
808 m_initialFocus = false;
809 }
810}
811
812
814{
815 wxSize new_size = aEvent.GetSize();
816
817 if( ( !m_itemsGrid->IsCellEditControlShown() || m_lastRequestedSize != new_size )
818 && m_gridSize != new_size )
819 {
820 m_gridSize = new_size;
821
822 // A trick to fix a cosmetic issue: when, in m_itemsGrid, a layer selector widget has
823 // the focus (is activated in column 6) when resizing the grid, the widget is not moved.
824 // So just change the widget having the focus in this case
825 if( m_NoteBook->GetSelection() == 0 && !m_itemsGrid->HasFocus() )
826 {
827 int col = m_itemsGrid->GetGridCursorCol();
828
829 if( col == 6 ) // a layer selector widget can be activated
830 m_itemsGrid->SetFocus();
831 }
832
834 }
835
836 // We store this value to check whether the dialog is changing size. This might indicate
837 // that the user is scaling the dialog with an editor shown. Some editors do not close
838 // (at least on GTK) when the user drags a dialog corner
839 m_lastRequestedSize = new_size;
840
841 // Always propagate for a grid repaint (needed if the height changes, as well as width)
842 aEvent.Skip();
843
844}
845
846
847void DIALOG_FOOTPRINT_PROPERTIES::OnPageChanging( wxNotebookEvent& aEvent )
848{
849 if( !m_itemsGrid->CommitPendingChanges() )
850 aEvent.Veto();
851}
852
853
854void DIALOG_FOOTPRINT_PROPERTIES::OnCheckBox( wxCommandEvent& event )
855{
856 if( m_initialized )
857 OnModify();
858}
859
860
861void DIALOG_FOOTPRINT_PROPERTIES::OnCombobox( wxCommandEvent& event )
862{
863 if( m_initialized )
864 OnModify();
865}
866
867
868void DIALOG_FOOTPRINT_PROPERTIES::OnText( wxCommandEvent& event )
869{
870 if( m_initialized )
871 OnModify();
872}
873
874
875void DIALOG_FOOTPRINT_PROPERTIES::OnChoice( wxCommandEvent& event )
876{
877 if( m_initialized )
878 OnModify();
879}
const char * name
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:112
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition bitmap.cpp:104
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:110
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition board_item.h:280
void SetFPRelativePosition(const VECTOR2I &aPos)
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:317
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition board.cpp:691
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition board.cpp:923
DIALOG_FOOTPRINT_PROPERTIES_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Footprint Properties"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
void OnDeleteField(wxCommandEvent &) override
void OnUpdateUI(wxUpdateUIEvent &) override
void OnAddField(wxCommandEvent &) override
void OnText(wxCommandEvent &event) override
void OnCombobox(wxCommandEvent &event) override
PANEL_FP_PROPERTIES_3D_MODEL * m_3dPanel
void OnGridSize(wxSizeEvent &aEvent) override
void OnPageChanging(wxNotebookEvent &event) override
void EditLibraryFootprint(wxCommandEvent &) override
DIALOG_FOOTPRINT_PROPERTIES(PCB_EDIT_FRAME *aParent, FOOTPRINT *aFootprint)
void OnChoice(wxCommandEvent &event) override
void EditFootprint(wxCommandEvent &) override
void OnCheckBox(wxCommandEvent &event) override
void UpdateFootprint(wxCommandEvent &) override
void ChangeFootprint(wxCommandEvent &) override
std::vector< wxWindow * > m_tabOrder
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition dialog_shim.h:82
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...
EDA_ANGLE Normalize180()
Definition eda_angle.h:268
void ClearSelected()
Definition eda_item.h:137
bool IsSelected() const
Definition eda_item.h:127
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:98
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:397
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:281
int GetTextThickness() const
Definition eda_text.h:128
VECTOR2I GetTextSize() const
Definition eda_text.h:261
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
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
The main frame for Pcbnew.
void SetOrdinal(int aOrdinal)
Definition pcb_field.h:116
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
PCB_FIELD * CloneField() const
Same as Clone, but returns a PCB_FIELD item.
Definition pcb_field.h:92
The selection tool: currently supports:
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings) override
Definition pcb_text.cpp:314
static S3D_CACHE * Get3DCacheManager(PROJECT *aProject, bool updateProjDir=false)
Return a pointer to an instance of the 3D cache manager.
void FlushCache(bool closePlugins=true)
Free all data in the cache and by default closes all plugins.
Definition 3d_cache.cpp:525
int AddItemToSel(const TOOL_EVENT &aEvent)
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:169
This file is part of the common library.
const int minSize
Push and Shove router track width and via size dialog.
#define _(s)
Declaration of the eda_3d_viewer class.
#define TEXT_MIN_SIZE_MM
Minimum text size (1 micron).
Definition eda_text.h:47
#define TEXT_MAX_SIZE_MM
Maximum text size in mm (~10 inches)
Definition eda_text.h:48
@ FP_SMD
Definition footprint.h:82
@ FP_DNP
Definition footprint.h:87
@ FP_EXCLUDE_FROM_POS_FILES
Definition footprint.h:83
@ FP_BOARD_ONLY
Definition footprint.h:85
@ FP_EXCLUDE_FROM_BOM
Definition footprint.h:84
@ FP_THROUGH_HOLE
Definition footprint.h:81
int ClampTextPenSize(int aPenSize, int aSize, bool aStrict)
Pen width should not allow characters to become cluttered up in their own fatness.
Definition gr_text.cpp:73
static const std::string KiCadUriPrefix
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
@ B_Cu
Definition layer_ids.h:65
@ F_Fab
Definition layer_ids.h:119
@ F_Cu
Definition layer_ids.h:64
@ B_Fab
Definition layer_ids.h:118
wxColour GetDialogBGColour()
Definition wxgtk/ui.cpp:61
wxSize GetUnobscuredSize(const wxWindow *aWindow)
Tries to determine the size of the viewport of a scrollable widget (wxDataViewCtrl,...
Definition wxgtk/ui.cpp:264
KICOMMON_API wxFont GetInfoFont(wxWindow *aWindow)
KICOMMON_API wxFont GetSmallInfoFont(wxWindow *aWindow)
KICOMMON_API wxFont GetControlFont(wxWindow *aWindow)
KICOMMON_API void SelectReferenceNumber(wxTextEntry *aTextEntry)
Select the number (or "?") in a reference for ease of editing.
@ PFC_THICKNESS
see class PGM_BASE
wxString GetUserFieldName(int aFieldNdx, bool aTranslateForHI)
#define DO_TRANSLATE
@ USER
The field ID hasn't been set yet; field is invalid.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
@ THERMAL
Use thermal relief for pads.
Definition zones.h:50
@ NONE
Pads are not covered.
Definition zones.h:49
@ FULL
pads are covered by copper
Definition zones.h:51