KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_footprint_properties_fp_editor.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2015 Dick Hollenbeck, [email protected]
6 * Copyright (C) 2008 Wayne Stambaugh <[email protected]>
7 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
28
29#include <wx/debug.h>
30
33#include <bitmaps.h>
34#include <board_commit.h>
36#include <confirm.h>
37
40#include <embedded_files.h>
41#include <filename_resolver.h>
42#include <footprint.h>
46#include <layer_utils.h>
47#include <kiplatform/ui.h>
50#include <pgm_base.h>
52#include <tool/tool_manager.h>
53#include <tools/pcb_actions.h>
55#include <validators.h>
59#include <widgets/wx_grid.h>
60
61#include <fp_lib_table.h>
62#include <project_pcb.h>
63#include <kidialog.h>
64
65
66class LAYERS_GRID_TABLE : public WX_GRID_TABLE_BASE, public std::vector<PCB_LAYER_ID>
67{
68public:
69 LAYERS_GRID_TABLE( PCB_BASE_FRAME* aFrame, const LSET& aForbiddenLayers );
71
72 int GetNumberRows() override { return (int) size(); }
73 int GetNumberCols() override { return 1; }
74
75 bool CanGetValueAs( int aRow, int aCol, const wxString& aTypeName ) override;
76 bool CanSetValueAs( int aRow, int aCol, const wxString& aTypeName ) override;
77 wxGridCellAttr* GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind ) override;
78
79 wxString GetValue( int aRow, int aCol ) override;
80 long GetValueAsLong( int aRow, int aCol ) override;
81
82 void SetValue( int aRow, int aCol, const wxString& aValue ) override;
83 void SetValueAsLong( int aRow, int aCol, long aValue ) override;
84
85private:
87 wxGridCellAttr* m_layerColAttr;
88};
89
90
91LAYERS_GRID_TABLE::LAYERS_GRID_TABLE( PCB_BASE_FRAME* aFrame, const LSET& aForbiddenLayers ) :
92 m_frame( aFrame )
93{
94 m_layerColAttr = new wxGridCellAttr;
95 m_layerColAttr->SetRenderer( new GRID_CELL_LAYER_RENDERER( m_frame ) );
96
97 m_layerColAttr->SetEditor( new GRID_CELL_LAYER_SELECTOR( m_frame, aForbiddenLayers, true ) );
98}
99
100
105
106
107bool LAYERS_GRID_TABLE::CanGetValueAs( int aRow, int aCol, const wxString& aTypeName )
108{
109 return aTypeName == wxGRID_VALUE_NUMBER;
110}
111
112
113bool LAYERS_GRID_TABLE::CanSetValueAs( int aRow, int aCol, const wxString& aTypeName )
114{
115 return aTypeName == wxGRID_VALUE_NUMBER;
116}
117
118
119wxGridCellAttr* LAYERS_GRID_TABLE::GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind )
120{
121 m_layerColAttr->IncRef();
122 return enhanceAttr( m_layerColAttr, aRow, aCol, aKind );
123}
124
125
126wxString LAYERS_GRID_TABLE::GetValue( int aRow, int aCol )
127{
128 return m_frame->GetBoard()->GetLayerName( this->at( (size_t) aRow ) );
129}
130
131
132long LAYERS_GRID_TABLE::GetValueAsLong( int aRow, int aCol )
133{
134 return this->at( (size_t) aRow );
135}
136
137
138void LAYERS_GRID_TABLE::SetValue( int aRow, int aCol, const wxString& aValue )
139{
140 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a string value" ), aCol ) );
141}
142
143
144void LAYERS_GRID_TABLE::SetValueAsLong( int aRow, int aCol, long aValue )
145{
146 this->at( (size_t) aRow ) = ToLAYER_ID( (int) aValue );
147}
148
149
150// Remember the last open page during session.
151
153
154
156 FOOTPRINT* aFootprint ) :
158 m_frame( aParent ),
159 m_footprint( aFootprint ),
160 m_initialized( false ),
165 m_gridSize( 0, 0 ),
166 m_lastRequestedSize( 0, 0 )
167{
168 SetEvtHandlerEnabled( false );
169
170 // Create the extra panels.
173
174 m_NoteBook->AddPage( m_3dPanel, _("3D Models"), false );
175 m_NoteBook->AddPage( m_embeddedFiles, _( "Embedded Files" ) );
176
177 m_fields = new PCB_FIELDS_GRID_TABLE( m_frame, this, { m_embeddedFiles->GetLocalFiles() } );
178
179 {
180 LSET forbiddenLayers = LSET::AllCuMask() | LSET::AllTechMask();
181 forbiddenLayers.set( Edge_Cuts );
182 forbiddenLayers.set( Margin );
183
184 m_privateLayers = new LAYERS_GRID_TABLE( m_frame, forbiddenLayers );
185 }
186
187 {
188 LSET forbiddenLayers = LSET::AllLayersMask() & ~LSET::UserDefinedLayersMask();
189 m_customUserLayers = new LAYERS_GRID_TABLE( m_frame, forbiddenLayers );
190 }
191
192 m_delayedErrorMessage = wxEmptyString;
193 m_delayedFocusCtrl = nullptr;
194 m_delayedFocusGrid = nullptr;
198
199 // Give an icon
200 wxIcon icon;
201 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_modedit ) );
202 SetIcon( icon );
203
204 m_itemsGrid->SetTable( m_fields );
207
208 m_itemsGrid->PushEventHandler( new GRID_TRICKS( m_itemsGrid ) );
210 [this]( wxCommandEvent& aEvent )
211 {
212 OnAddPrivateLayer( aEvent );
213 } ) );
214 m_nettieGroupsGrid->PushEventHandler( new GRID_TRICKS( m_nettieGroupsGrid,
215 [this]( wxCommandEvent& aEvent )
216 {
217 OnAddNettieGroup( aEvent );
218 } ) );
219 m_jumperGroupsGrid->PushEventHandler( new GRID_TRICKS( m_jumperGroupsGrid,
220 [this]( wxCommandEvent& aEvent )
221 {
222 OnAddJumperGroup( aEvent );
223 } ) );
225 [this]( wxCommandEvent& aEvent )
226 {
227 OnAddCustomLayer( aEvent );
228 } ) );
229
230 m_itemsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
231 m_privateLayersGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
232 m_nettieGroupsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
233 m_jumperGroupsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
234 m_customUserLayersGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
235
236 // Show/hide columns according to the user's preference
237 m_itemsGrid->ShowHideColumns( m_frame->GetSettings()->m_FootprintTextShownColumns );
238
240
241 // Set font sizes
242 wxFont infoFont = KIUI::GetInfoFont( this ).Italic();
243 m_staticTextInfoCopper->SetFont( infoFont );
244 m_staticTextInfoPaste->SetFont( infoFont );
245
246 if( static_cast<int>( m_page ) >= 0 )
247 m_NoteBook->SetSelection( (unsigned) m_page );
248
250 {
255 }
257 {
259 }
260
261 m_solderPaste.SetNegativeZero();
262
264 m_solderPasteRatio.SetNegativeZero();
265
266 // Configure button logos
277
279
281 SetEvtHandlerEnabled( true );
282}
283
284
286{
287 m_frame->GetSettings()->m_FootprintTextShownColumns = m_itemsGrid->GetShownColumnsAsString();
288
289 // Prevents crash bug in wxGrid's d'tor
290 m_itemsGrid->DestroyTable( m_fields );
291 m_privateLayersGrid->DestroyTable( m_privateLayers );
293
294 // Delete the GRID_TRICKS.
295 m_itemsGrid->PopEventHandler( true );
296 m_privateLayersGrid->PopEventHandler( true );
297 m_nettieGroupsGrid->PopEventHandler( true );
298 m_jumperGroupsGrid->PopEventHandler( true );
299 m_customUserLayersGrid->PopEventHandler( true );
300
301 m_page = static_cast<NOTEBOOK_PAGES>( m_NoteBook->GetSelection() );
302
303 // the GL canvas on the 3D models page has to be visible before it is destroyed
304 m_NoteBook->SetSelection( static_cast<int>( NOTEBOOK_PAGES::PAGE_3D_MODELS ) );
305}
306
307
309{
310 LIB_ID fpID = m_footprint->GetFPID();
311 wxString footprintName = fpID.GetLibItemName();
312
313 m_FootprintNameCtrl->ChangeValue( footprintName );
314
315 m_DocCtrl->SetValue( EscapeString( m_footprint->GetLibDescription(), CTX_LINE ) );
316 m_KeywordCtrl->SetValue( m_footprint->GetKeywords() );
317
318 if( !wxDialog::TransferDataToWindow() )
319 return false;
320
321 if( !m_PanelGeneral->TransferDataToWindow() )
322 return false;
323
324 // Add the models to the panel
325 if( !m_3dPanel->TransferDataToWindow() )
326 return false;
327
328 if( !m_embeddedFiles->TransferDataToWindow() )
329 return false;
330
331 // Footprint Fields
332 for( PCB_FIELD* field : m_footprint->GetFields() )
333 m_fields->push_back( *field );
334
335 // Notify the grid
336 wxGridTableMessage tmsg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->GetNumberRows() );
337 m_itemsGrid->ProcessTableMessage( tmsg );
338
339 if( m_footprint->GetAttributes() & FP_THROUGH_HOLE )
340 m_componentType->SetSelection( 0 );
341 else if( m_footprint->GetAttributes() & FP_SMD )
342 m_componentType->SetSelection( 1 );
343 else
344 m_componentType->SetSelection( 2 );
345
346 // Private layers
347 for( PCB_LAYER_ID privateLayer : m_footprint->GetPrivateLayers().UIOrder() )
348 m_privateLayers->push_back( privateLayer );
349
350 // Notify the grid
351 wxGridTableMessage gridTableMessagesg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
352 m_privateLayers->GetNumberRows() );
353 m_privateLayersGrid->ProcessTableMessage( gridTableMessagesg );
354
355 switch( m_footprint->GetStackupMode() )
356 {
358 {
359 m_cbCustomLayers->SetValue( false );
360
361 m_copperLayerCount->SetSelection( 0 );
362 break;
363 }
365 {
366 m_cbCustomLayers->SetValue( true );
367
368 const LSET& customFpLayers = m_footprint->GetStackupLayers();
369 const LSET customUserLayers = customFpLayers & LSET::UserDefinedLayersMask();
370
371 for( PCB_LAYER_ID customUserLayer : customUserLayers )
372 {
373 m_customUserLayers->push_back( customUserLayer );
374 }
375
376 // Set the number of copper layers
377 m_copperLayerCount->SetSelection( ( customFpLayers & LSET::AllCuMask() ).count() / 2 - 1 );
378 break;
379 }
380 }
382
383 // Notify the grid
384 {
385 wxGridTableMessage gridTableMessagesCustom( m_customUserLayers, wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
386 m_customUserLayers->GetNumberRows() );
387 m_customUserLayersGrid->ProcessTableMessage( gridTableMessagesCustom );
388 }
389
390 m_boardOnly->SetValue( m_footprint->GetAttributes() & FP_BOARD_ONLY );
391 m_excludeFromPosFiles->SetValue( m_footprint->GetAttributes() & FP_EXCLUDE_FROM_POS_FILES );
392 m_excludeFromBOM->SetValue( m_footprint->GetAttributes() & FP_EXCLUDE_FROM_BOM );
393 m_cbDNP->SetValue( m_footprint->GetAttributes() & FP_DNP );
394
395 // Local Clearances
396
397 if( m_footprint->GetLocalClearance().has_value() )
398 m_netClearance.SetValue( m_footprint->GetLocalClearance().value() );
399 else
400 m_netClearance.SetValue( wxEmptyString );
401
402 if( m_footprint->GetLocalSolderMaskMargin().has_value() )
403 m_solderMask.SetValue( m_footprint->GetLocalSolderMaskMargin().value() );
404 else
405 m_solderMask.SetValue( wxEmptyString );
406
407 if( m_footprint->GetLocalSolderPasteMargin().has_value() )
408 m_solderPaste.SetValue( m_footprint->GetLocalSolderPasteMargin().value() );
409 else
410 m_solderPaste.SetValue( wxEmptyString );
411
412 if( m_footprint->GetLocalSolderPasteMarginRatio().has_value() )
413 m_solderPasteRatio.SetDoubleValue( m_footprint->GetLocalSolderPasteMarginRatio().value() * 100.0 );
414 else
415 m_solderPasteRatio.SetValue( wxEmptyString );
416
417 m_noCourtyards->SetValue( m_footprint->AllowMissingCourtyard() );
418 m_allowBridges->SetValue( m_footprint->AllowSolderMaskBridges() );
419
420 switch( m_footprint->GetLocalZoneConnection() )
421 {
422 default:
423 case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
424 case ZONE_CONNECTION::FULL: m_ZoneConnectionChoice->SetSelection( 1 ); break;
425 case ZONE_CONNECTION::THERMAL: m_ZoneConnectionChoice->SetSelection( 2 ); break;
426 case ZONE_CONNECTION::NONE: m_ZoneConnectionChoice->SetSelection( 3 ); break;
427 }
428
429 for( const wxString& group : m_footprint->GetNetTiePadGroups() )
430 {
431 if( !group.IsEmpty() )
432 {
433 m_nettieGroupsGrid->AppendRows( 1 );
434 m_nettieGroupsGrid->SetCellValue( m_nettieGroupsGrid->GetNumberRows() - 1, 0, group );
435 }
436 }
437
438 m_cbDuplicatePadsAreJumpers->SetValue( m_footprint->GetDuplicatePadNumbersAreJumpers() );
439
440 for( const std::set<wxString>& group : m_footprint->JumperPadGroups() )
441 {
442 wxString groupTxt;
443
444 for( const wxString& pinNumber : group )
445 {
446 if( !groupTxt.IsEmpty() )
447 groupTxt << ", ";
448
449 groupTxt << pinNumber;
450 }
451
452 m_jumperGroupsGrid->AppendRows( 1 );
453 m_jumperGroupsGrid->SetCellValue( m_jumperGroupsGrid->GetNumberRows() - 1, 0, groupTxt );
454 }
455
456 // Items grid
457 for( int col = 0; col < m_itemsGrid->GetNumberCols(); col++ )
458 {
459 // Adjust min size to the column label size
460 m_itemsGrid->SetColMinimalWidth( col, m_itemsGrid->GetVisibleWidth( col, true, false ) );
461 // Adjust the column size.
462 int col_size = m_itemsGrid->GetVisibleWidth( col );
463
464 if( col == PFC_LAYER ) // This one's a drop-down. Check all possible values.
465 {
466 BOARD* board = m_footprint->GetBoard();
467
468 for( PCB_LAYER_ID layer : board->GetEnabledLayers() )
469 col_size = std::max( col_size, GetTextExtent( board->GetLayerName( layer ) ).x );
470
471 // Swatch and gaps:
472 col_size += KiROUND( 14 * GetDPIScaleFactor() ) + 12;
473 }
474
475 if( m_itemsGrid->IsColShown( col ) )
476 m_itemsGrid->SetColSize( col, col_size );
477 }
478
479 m_itemsGrid->SetRowLabelSize( 0 );
480
481 Layout();
483 m_initialized = true;
484
485 return true;
486}
487
488
490 LIB_ID* doOverwrite )
491{
492 if( aFootprintName.IsEmpty() )
493 {
494 m_delayedErrorMessage = _( "Footprint must have a name." );
495 return false;
496 }
497 else if( !FOOTPRINT::IsLibNameValid( aFootprintName ) )
498 {
499 m_delayedErrorMessage.Printf( _( "Footprint name may not contain '%s'." ),
501 return false;
502 }
503
504 LIB_ID fpID = m_footprint->GetFPID();
505 wxString libraryName = fpID.GetLibNickname();
506 wxString originalFPName = fpID.GetLibItemName();
508
509 if( aFootprintName != originalFPName && tbl->FootprintExists( libraryName, aFootprintName ) )
510 {
511 wxString msg = wxString::Format( _( "Footprint '%s' already exists in library '%s'." ),
512 aFootprintName, libraryName );
513
514 KIDIALOG errorDlg( m_frame, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
515 errorDlg.SetOKLabel( _( "Overwrite" ) );
516
517 if( errorDlg.ShowModal() == wxID_OK )
518 {
519 doOverwrite->SetLibNickname( libraryName );
520 doOverwrite->SetLibItemName( aFootprintName );
521 return true;
522 }
523 }
524
525 return true;
526}
527
528
530{
531 LSET userLayers;
532 if( m_cbCustomLayers->GetValue() )
533 {
534 userLayers |= LSET::AllCuMask( ( m_copperLayerCount->GetSelection() + 1 ) * 2 );
535
536 for( PCB_LAYER_ID layer : *m_customUserLayers )
537 {
538 userLayers.set( layer );
539 }
540 }
541 else
542 {
543 userLayers |= LSET{ F_Cu, In1_Cu, B_Cu };
544 userLayers |= LSET::UserDefinedLayersMask( 4 );
545 }
546
547 return userLayers;
548}
549
550
551static LSET GetAllUsedFootprintLayers( const FOOTPRINT& aFootprint )
552{
553 LSET usedLayers{};
554 aFootprint.RunOnChildren(
555 [&]( BOARD_ITEM* aSubItem )
556 {
557 wxCHECK2( aSubItem, /*void*/ );
558
559 switch( aSubItem->Type() )
560 {
561 case PCB_ZONE_T:
562 {
563 ZONE& zone = static_cast<ZONE&>( *aSubItem );
564 usedLayers |= zone.GetLayerSet();
565 break;
566 }
567 default:
568 {
569 usedLayers.set( aSubItem->GetLayer() );
570 break;
571 }
572 }
573 },
575 return usedLayers;
576}
577
578
580{
581 if( !m_itemsGrid->CommitPendingChanges() )
582 return false;
583
584 if( !DIALOG_SHIM::Validate() )
585 return false;
586
587 // First, test for invalid chars in footprint name
588 wxString footprintName = m_FootprintNameCtrl->GetValue();
589 LIB_ID overwrite;
590
591 if( !checkFootprintName( footprintName, &overwrite ) )
592 {
593 if( m_NoteBook->GetSelection() != 0 )
594 m_NoteBook->SetSelection( 0 );
595
598
599 return false;
600 }
601
602 // Check for valid field text properties
603 for( int i = 0; i < (int) m_fields->size(); ++i )
604 {
605 PCB_FIELD& field = m_fields->at( i );
606
607 // Check for missing field names.
608 if( field.GetName( false ).IsEmpty() )
609 {
611 m_delayedErrorMessage = wxString::Format( _( "Fields must have a name." ) );
614
615 return false;
616 }
617
618 int minSize = pcbIUScale.mmToIU( TEXT_MIN_SIZE_MM );
619 int maxSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
620
621 if( field.GetTextWidth() < minSize || field.GetTextWidth() > maxSize )
622 {
624 m_delayedErrorMessage = wxString::Format( _( "The text width must be between %s and %s." ),
625 m_frame->StringFromValue( minSize, true ),
626 m_frame->StringFromValue( maxSize, true ) );
629
630 return false;
631 }
632
633 if( field.GetTextHeight() < minSize || field.GetTextHeight() > maxSize )
634 {
636 m_delayedErrorMessage = wxString::Format( _( "The text height must be between %s and %s." ),
637 m_frame->StringFromValue( minSize, true ),
638 m_frame->StringFromValue( maxSize, true ) );
641
642 return false;
643 }
644
645 // Test for acceptable values for thickness and size and clamp if fails
646 int maxPenWidth = ClampTextPenSize( field.GetTextThickness(), field.GetTextSize() );
647
648 if( field.GetTextThickness() > maxPenWidth )
649 {
650 m_itemsGrid->SetCellValue( i, PFC_THICKNESS, m_frame->StringFromValue( maxPenWidth, true ) );
651
653 m_delayedErrorMessage = _( "The text thickness is too large for the text size.\n"
654 "It will be clamped." );
657
658 return false;
659 }
660 }
661
662 if( !m_netClearance.Validate( 0, INT_MAX ) )
663 return false;
664
665 if( overwrite.IsValid() )
666 {
667 if( m_frame->DeleteFootprintFromLibrary( overwrite, false /* already confirmed */ ) )
668 m_frame->SyncLibraryTree( true );
669 }
670
671 // See if there is an object in the footprint that uses a layer that is not in that list
673
674 // Check that the user isn't trying to remove a layer that is used by the footprint
675 usedLayers &= ~getCustomLayersFromControls();
676 usedLayers &= ~LSET::AllTechMask();
677 usedLayers &= ~LSET::UserMask();
678
679 if( usedLayers.any() )
680 {
682 wxString::Format( _( "You are trying to remove layers that are used by the footprint: %s.\n"
683 "Please remove the objects that use these layers first." ),
684 LAYER_UTILS::AccumulateNames( usedLayers, m_frame->GetBoard() ) );
689 return false;
690 }
691
692 return true;
693}
694
695
697{
698 if( !m_itemsGrid->CommitPendingChanges()
699 || !m_privateLayersGrid->CommitPendingChanges()
700 || !m_nettieGroupsGrid->CommitPendingChanges()
701 || !m_jumperGroupsGrid->CommitPendingChanges()
702 || !m_customUserLayersGrid->CommitPendingChanges() )
703 {
704 return false;
705 }
706
707 KIGFX::PCB_VIEW* view = m_frame->GetCanvas()->GetView();
708 PCB_SELECTION_TOOL* selectionTool = m_frame->GetToolManager()->GetTool<PCB_SELECTION_TOOL>();
709 BOARD_COMMIT commit( m_frame );
710 commit.Modify( m_footprint );
711
712 // Must be done inside the commit to capture the undo state
713 // This will call TransferDataToWindow() on the 3D panel and
714 // the embedded files panel.
715 if( !DIALOG_SHIM::TransferDataFromWindow() )
716 return false;
717
718 // Clear out embedded files that are no longer in use
719 std::set<wxString> files;
720 std::set<wxString> files_to_delete;
721
722 // Get the new files from the footprint fields
723 for( const PCB_FIELD& field : *m_fields )
724 {
725 if( field.GetText().StartsWith( FILEEXT::KiCadUriPrefix ) )
726 files.insert( field.GetText() );
727 }
728
729 // Find any files referenced in the old fields that are not in the new fields
730 for( PCB_FIELD* field : m_footprint->GetFields() )
731 {
732 if( field->GetText().StartsWith( FILEEXT::KiCadUriPrefix ) )
733 {
734 if( files.find( field->GetText() ) == files.end() )
735 files_to_delete.insert( field->GetText() );
736 }
737 }
738
739 for( const wxString& file : files_to_delete )
740 {
741 wxString name = file.Mid( FILEEXT::KiCadUriPrefix.size() + 3 ); // Skip "kicad-embed://"
742 m_footprint->RemoveFile( name );
743 }
744
745 LIB_ID fpID = m_footprint->GetFPID();
746 fpID.SetLibItemName( m_FootprintNameCtrl->GetValue() );
747 m_footprint->SetFPID( fpID );
748
749 m_footprint->SetLibDescription( UnescapeString( m_DocCtrl->GetValue() ) );
750 m_footprint->SetKeywords( m_KeywordCtrl->GetValue() );
751
752 // Update fields
753 m_frame->GetToolManager()->RunAction( ACTIONS::selectionClear );
754
755 while( !m_footprint->GetFields().empty() )
756 {
757 PCB_FIELD* existing = m_footprint->GetFields().front();
758 view->Remove( existing );
759 m_footprint->Remove( existing );
760 delete existing;
761 }
762
763 for( PCB_FIELD& field : *m_fields )
764 {
765 PCB_FIELD* newField = field.CloneField();
766 m_footprint->Add( newField );
767 view->Add( newField );
768
769 if( newField->IsSelected() )
770 {
771 // The old copy was in the selection list, but this one is not. Remove the
772 // out-of-sync selection flag so we can re-add the field to the selection.
773 newField->ClearSelected();
774 selectionTool->AddItemToSel( newField, true );
775 }
776 }
777
778 LSET privateLayers;
779
780 for( PCB_LAYER_ID layer : *m_privateLayers )
781 privateLayers.set( layer );
782
783 m_footprint->SetPrivateLayers( privateLayers );
784
785 if( m_cbCustomLayers->GetValue() )
786 {
787 const LSET customLayers = getCustomLayersFromControls();
788
790 m_footprint->SetStackupLayers( std::move( customLayers ) );
791 }
792 else
793 {
794 // Just use the default stackup mode
796 }
797
798 int attributes = 0;
799
800 switch( m_componentType->GetSelection() )
801 {
802 case 0: attributes |= FP_THROUGH_HOLE; break;
803 case 1: attributes |= FP_SMD; break;
804 default: break;
805 }
806
807 if( m_boardOnly->GetValue() )
808 attributes |= FP_BOARD_ONLY;
809
810 if( m_excludeFromPosFiles->GetValue() )
811 attributes |= FP_EXCLUDE_FROM_POS_FILES;
812
813 if( m_excludeFromBOM->GetValue() )
814 attributes |= FP_EXCLUDE_FROM_BOM;
815
816 if( m_cbDNP->GetValue() )
817 attributes |= FP_DNP;
818
819 m_footprint->SetAttributes( attributes );
820
821 m_footprint->SetAllowMissingCourtyard( m_noCourtyards->GetValue() );
822 m_footprint->SetAllowSolderMaskBridges( m_allowBridges->GetValue() );
823
824 // Initialize mask clearances
825 if( m_netClearance.IsNull() )
826 m_footprint->SetLocalClearance( {} );
827 else
828 m_footprint->SetLocalClearance( m_netClearance.GetValue() );
829
830 if( m_solderMask.IsNull() )
831 m_footprint->SetLocalSolderMaskMargin( {} );
832 else
833 m_footprint->SetLocalSolderMaskMargin( m_solderMask.GetValue() );
834
835 if( m_solderPaste.IsNull() )
836 m_footprint->SetLocalSolderPasteMargin( {} );
837 else
838 m_footprint->SetLocalSolderPasteMargin( m_solderPaste.GetValue() );
839
840 if( m_solderPasteRatio.IsNull() )
841 m_footprint->SetLocalSolderPasteMarginRatio( {} );
842 else
843 m_footprint->SetLocalSolderPasteMarginRatio( m_solderPasteRatio.GetDoubleValue() / 100.0 );
844
845 switch( m_ZoneConnectionChoice->GetSelection() )
846 {
847 default:
848 case 0: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::INHERITED ); break;
849 case 1: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::FULL ); break;
850 case 2: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::THERMAL ); break;
851 case 3: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::NONE ); break;
852 }
853
854 m_footprint->ClearNetTiePadGroups();
855
856 for( int ii = 0; ii < m_nettieGroupsGrid->GetNumberRows(); ++ii )
857 {
858 wxString group = m_nettieGroupsGrid->GetCellValue( ii, 0 );
859
860 if( !group.IsEmpty() )
861 m_footprint->AddNetTiePadGroup( group );
862 }
863
864 m_footprint->SetDuplicatePadNumbersAreJumpers( m_cbDuplicatePadsAreJumpers->GetValue() );
865
866 std::vector<std::set<wxString>>& jumpers = m_footprint->JumperPadGroups();
867 jumpers.clear();
868
869 for( int ii = 0; ii < m_jumperGroupsGrid->GetNumberRows(); ++ii )
870 {
871 wxStringTokenizer tokenizer( m_jumperGroupsGrid->GetCellValue( ii, 0 ), ", \t\r\n", wxTOKEN_STRTOK );
872 std::set<wxString>& group = jumpers.emplace_back();
873
874 while( tokenizer.HasMoreTokens() )
875 {
876 if( wxString token = tokenizer.GetNextToken(); !token.IsEmpty() )
877 group.insert( token );
878 }
879 }
880
881 // Copy the models from the panel to the footprint
882 std::vector<FP_3DMODEL>& panelList = m_3dPanel->GetModelList();
883 std::vector<FP_3DMODEL>* fpList = &m_footprint->Models();
884 fpList->clear();
885 fpList->insert( fpList->end(), panelList.begin(), panelList.end() );
886
887 commit.Push( _( "Edit Footprint Properties" ) );
888
889 return true;
890}
891
892
894{
895 m_itemsGrid->OnAddRow(
896 [&]() -> std::pair<int, int>
897 {
898 const BOARD_DESIGN_SETTINGS& dsnSettings = m_frame->GetDesignSettings();
899
901
902 // Set active layer if legal; otherwise copy layer from previous text item
903 if( LSET::AllTechMask().test( m_frame->GetActiveLayer() ) )
904 newField.SetLayer( m_frame->GetActiveLayer() );
905 else
906 newField.SetLayer( m_fields->at( m_fields->size() - 1 ).GetLayer() );
907
908 newField.SetTextSize( dsnSettings.GetTextSize( newField.GetLayer() ) );
909 newField.SetTextThickness( dsnSettings.GetTextThickness( newField.GetLayer() ) );
910 newField.SetItalic( dsnSettings.GetTextItalic( newField.GetLayer() ) );
911
912 m_fields->push_back( newField );
913
914 // notify the grid
915 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
916 m_itemsGrid->ProcessTableMessage( msg );
917 OnModify();
918
919 return { m_fields->size() - 1, PFC_NAME };
920 } );
921}
922
923
925{
926 m_itemsGrid->OnDeleteRows(
927 [&]( int row )
928 {
929 if( row < m_fields->GetMandatoryRowCount() )
930 {
931 DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
932 m_fields->GetMandatoryRowCount() ) );
933 return false;
934 }
935
936 return true;
937 },
938 [&]( int row )
939 {
940 m_fields->erase( m_fields->begin() + row );
941
942 // notify the grid
943 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 );
944 m_itemsGrid->ProcessTableMessage( msg );
945 } );
946
947 OnModify();
948}
949
950
952 int aRow )
953{
954 aLayerTable.erase( aLayerTable.begin() + aRow );
955
956 // notify the grid
957 wxGridTableMessage msg( &aLayerTable, wxGRIDTABLE_NOTIFY_ROWS_DELETED, aRow, 1 );
958 aGrid.ProcessTableMessage( msg );
959
960 OnModify();
961}
962
963
965 LAYERS_GRID_TABLE& aGridTable )
966{
967 PCB_LAYER_ID nextLayer = User_1;
968
969 while( alg::contains( aGridTable, nextLayer ) && nextLayer < User_45 )
970 nextLayer = ToLAYER_ID( nextLayer + 2 );
971
972 aGridTable.push_back( nextLayer );
973
974 // notify the grid
975 wxGridTableMessage msg( &aGridTable, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
976 aGrid.ProcessTableMessage( msg );
977 OnModify();
978
979 return { aGridTable.size() - 1, 0 };
980}
981
982
984{
985 m_privateLayersGrid->OnAddRow(
986 [&]()
987 {
989 } );
990}
991
992
994{
995 m_privateLayersGrid->OnDeleteRows(
996 [&]( int row )
997 {
999 } );
1000}
1001
1002
1007
1008
1010{
1011 m_customUserLayersGrid->OnAddRow(
1012 [&]()
1013 {
1015 } );
1016}
1017
1018
1020{
1021 m_customUserLayersGrid->OnDeleteRows(
1022 [&]( int row )
1023 {
1025 } );
1026}
1027
1028
1033
1034
1039
1040
1045
1046
1051
1052
1054{
1055 aGrid->OnAddRow(
1056 [&]() -> std::pair<int, int>
1057 {
1058 aGrid->AppendRows( 1 );
1059 OnModify();
1060
1061 return { aGrid->GetNumberRows() - 1, 0 };
1062 } );
1063}
1064
1065
1067{
1068 aGrid->OnDeleteRows(
1069 [&]( int row )
1070 {
1071 aGrid->DeleteRows( row, 1 );
1072 } );
1073
1074 OnModify();
1075}
1076
1077
1079{
1080 // Account for scroll bars
1081 int itemsWidth = KIPLATFORM::UI::GetUnobscuredSize( m_itemsGrid ).x;
1082
1083 itemsWidth -= m_itemsGrid->GetRowLabelSize();
1084
1085 for( int i = 0; i < m_itemsGrid->GetNumberCols(); i++ )
1086 {
1087 if( i == 1 )
1088 continue;
1089
1090 itemsWidth -= m_itemsGrid->GetColSize( i );
1091 }
1092
1093 m_itemsGrid->SetColSize( 1, std::max( itemsWidth, m_itemsGrid->GetVisibleWidth( 0, true, false ) ) );
1094
1095 auto updateSingleColumnGrid =
1096 []( WX_GRID* aGrid )
1097 {
1098 aGrid->SetColSize( 0, std::max( aGrid->GetClientSize().x, aGrid->GetVisibleWidth( 0 ) ) );
1099 };
1100
1101 updateSingleColumnGrid( m_privateLayersGrid );
1102 updateSingleColumnGrid( m_nettieGroupsGrid );
1103 updateSingleColumnGrid( m_jumperGroupsGrid );
1104 updateSingleColumnGrid( m_customUserLayersGrid );
1105
1106 // Update the width of the 3D panel
1107 m_3dPanel->AdjustGridColumnWidths();
1108}
1109
1110
1112{
1113 // Handle a delayed focus. The delay allows us to:
1114 // a) change focus when the error was triggered from within a killFocus handler
1115 // b) show the correct notebook page in the background before the error dialog comes up
1116 // when triggered from an OK or a notebook page change
1117
1118 if( static_cast<int>( m_delayedFocusPage ) >= 0 )
1119 {
1120 if( m_NoteBook->GetSelection() != static_cast<int>( m_delayedFocusPage ) )
1121 m_NoteBook->ChangeSelection( static_cast<int>( m_delayedFocusPage ) );
1122
1124 }
1125
1126 if( !m_delayedErrorMessage.IsEmpty() )
1127 {
1128 // We will re-enter this routine when the error dialog is displayed, so make
1129 // sure we don't keep putting up more dialogs.
1130 wxString msg = m_delayedErrorMessage;
1131 m_delayedErrorMessage = wxEmptyString;
1132
1133 // Do not use DisplayErrorMessage(); it screws up window order on Mac
1134 DisplayError( nullptr, msg );
1135 }
1136
1137 if( m_delayedFocusCtrl )
1138 {
1139 m_delayedFocusCtrl->SetFocus();
1140
1141 if( wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_delayedFocusCtrl ) )
1142 textEntry->SelectAll();
1143
1144 m_delayedFocusCtrl = nullptr;
1145 }
1146 else if( m_delayedFocusGrid )
1147 {
1148 m_delayedFocusGrid->SetFocus();
1151
1152 if( !( m_delayedFocusColumn == 0 && m_delayedFocusRow < m_fields->GetMandatoryRowCount() ) )
1153 m_delayedFocusGrid->EnableCellEditControl( true );
1154
1155 m_delayedFocusGrid->ShowCellEditControl();
1156
1157 m_delayedFocusGrid = nullptr;
1158 m_delayedFocusRow = -1;
1160 }
1161}
1162
1163
1165{
1166 wxSize new_size = aEvent.GetSize();
1167
1168 if( ( !m_itemsGrid->IsCellEditControlShown() || m_lastRequestedSize != new_size )
1169 && m_gridSize != new_size )
1170 {
1171 m_gridSize = new_size;
1172
1173 // A trick to fix a cosmetic issue: when, in m_itemsGrid, a layer selector widget has
1174 // the focus (is activated in column 6) when resizing the grid, the widget is not moved.
1175 // So just change the widget having the focus in this case
1176 if( m_NoteBook->GetSelection() == 0 && !m_itemsGrid->HasFocus() )
1177 {
1178 int col = m_itemsGrid->GetGridCursorCol();
1179
1180 if( col == 6 ) // a layer selector widget can be activated
1181 m_itemsGrid->SetFocus();
1182 }
1183
1185 }
1186
1187 // We store this value to check whether the dialog is changing size. This might indicate
1188 // that the user is scaling the dialog with an editor shown. Some editors do not close
1189 // (at least on GTK) when the user drags a dialog corner
1190 m_lastRequestedSize = new_size;
1191
1192 // Always propagate for a grid repaint (needed if the height changes, as well as width)
1193 aEvent.Skip();
1194}
1195
1196
1198{
1199 bool enableCustomCtrls = m_cbCustomLayers->GetValue();
1200
1201 m_copperLayerCount->Enable( enableCustomCtrls );
1202 m_customUserLayersGrid->Enable( enableCustomCtrls );
1203 m_bpAddCustomLayer->Enable( enableCustomCtrls );
1204 m_bpDeleteCustomLayer->Enable( enableCustomCtrls );
1205}
1206
1207
1209{
1210 if( !m_itemsGrid->CommitPendingChanges() )
1211 aEvent.Veto();
1212
1213 if( !m_privateLayersGrid->CommitPendingChanges() )
1214 aEvent.Veto();
1215
1216 if( !m_customUserLayersGrid->CommitPendingChanges() )
1217 aEvent.Veto();
1218}
1219
1220
1222{
1223 if( m_initialized )
1224 OnModify();
1225}
1226
1227
1229{
1230 if( m_initialized )
1231 OnModify();
1232}
1233
1234
1236{
1237 if( m_initialized )
1238 OnModify();
1239}
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
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:223
BASE_SET & set(size_t pos)
Definition base_set.h:116
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.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:79
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:232
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition board_item.h:280
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_FP_EDITOR_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)
DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR(FOOTPRINT_EDIT_FRAME *aParent, FOOTPRINT *aFootprint)
LSET getCustomLayersFromControls() const
Get the layers for the footprint from the controls that can be affected by the stackup.
bool checkFootprintName(const wxString &aFootprintName, LIB_ID *doOverwrite)
void onLayerGridRowDelete(WX_GRID &aGrid, LAYERS_GRID_TABLE &aLayerTable, int aRow)
std::pair< int, int > onLayerGridRowAddUserLayer(WX_GRID &aGrid, LAYERS_GRID_TABLE &aLayerTable)
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...
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
void ClearSelected()
Definition eda_item.h:137
bool IsSelected() const
Definition eda_item.h:127
int GetTextHeight() const
Definition eda_text.h:266
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition eda_text.cpp:534
int GetTextWidth() const
Definition eda_text.h:263
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition eda_text.cpp:285
int GetTextThickness() const
Definition eda_text.h:127
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
Definition eda_text.cpp:308
VECTOR2I GetTextSize() const
Definition eda_text.h:260
Provide a custom wxValidator object for limiting the allowable characters when defining footprint nam...
Definition validators.h:53
static bool IsLibNameValid(const wxString &aName)
Test for validity of a name of a footprint to be used in a footprint library ( no spaces,...
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const override
Invoke a function on all children.
static const wxChar * StringLibNameInvalidChars(bool aUserReadable)
Test for validity of the name in a library of the footprint ( no spaces, dir separators ....
bool FootprintExists(const wxString &aNickname, const wxString &aFootprintName)
Indicates whether or not the given footprint already exists in the given library.
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition grid_tricks.h:61
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition kidialog.h:42
int ShowModal() override
Definition kidialog.cpp:93
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1) override
Add a VIEW_ITEM to the view.
Definition pcb_view.cpp:57
virtual void Remove(VIEW_ITEM *aItem) override
Remove a VIEW_ITEM from the view.
Definition pcb_view.cpp:74
LAYERS_GRID_TABLE(PCB_BASE_FRAME *aFrame, const LSET &aForbiddenLayers)
wxString GetValue(int aRow, int aCol) override
bool CanGetValueAs(int aRow, int aCol, const wxString &aTypeName) override
void SetValueAsLong(int aRow, int aCol, long aValue) override
long GetValueAsLong(int aRow, int aCol) override
bool CanSetValueAs(int aRow, int aCol, const wxString &aTypeName) override
void SetValue(int aRow, int aCol, const wxString &aValue) override
wxGridCellAttr * GetAttr(int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind) override
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:111
bool IsValid() const
Check if this LID_ID is valid.
Definition lib_id.h:172
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition lib_id.cpp:100
const UTF8 & GetLibItemName() const
Definition lib_id.h:102
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition lib_id.h:87
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static const LSET & AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
Definition lset.cpp:659
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition lset.cpp:582
static const LSET & AllLayersMask()
Definition lset.cpp:624
static LSET UserDefinedLayersMask(int aUserDefinedLayerCount=MAX_USER_DEFINED_LAYERS)
Return a mask with the requested number of user defined layers.
Definition lset.cpp:687
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:591
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
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:
static FP_LIB_TABLE * PcbFootprintLibs(PROJECT *aProject)
Return the table of footprint libraries without Kiway.
int AddItemToSel(const TOOL_EVENT &aEvent)
wxGridCellAttr * enhanceAttr(wxGridCellAttr *aInputAttr, int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind)
Definition wx_grid.cpp:45
void OnDeleteRows(const std::function< void(int row)> &aDeleter)
Handles a row deletion event.
Definition wx_grid.cpp:694
void OnAddRow(const std::function< std::pair< int, int >()> &aAdder)
Definition wx_grid.cpp:674
Handle a list of polygons defining a copper zone.
Definition zone.h:74
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition zone.h:136
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.
static LSET GetAllUsedFootprintLayers(const FOOTPRINT &aFootprint)
const int minSize
Push and Shove router track width and via size dialog.
#define _(s)
Declaration of the eda_3d_viewer class.
@ RECURSE
Definition eda_item.h:51
#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: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
@ EXPAND_INNER_LAYERS
The 'normal' stackup handling, where there is a single inner layer (In1) and rule areas using it expa...
Definition footprint.h:96
@ CUSTOM_LAYERS
Stackup handling where the footprint can have any number of copper layers, and objects on those layer...
Definition footprint.h:101
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
@ User_45
Definition layer_ids.h:168
@ Edge_Cuts
Definition layer_ids.h:112
@ B_Cu
Definition layer_ids.h:65
@ Margin
Definition layer_ids.h:113
@ In1_Cu
Definition layer_ids.h:66
@ User_1
Definition layer_ids.h:124
@ F_Cu
Definition layer_ids.h:64
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition lset.cpp:737
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)
wxString AccumulateNames(const LSEQ &aLayers, const BOARD *aBoard)
Accumulate layer names from a layer set into a comma separated string.
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:100
@ 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
wxString GetUserFieldName(int aFieldNdx, bool aTranslateForHI)
#define DO_TRANSLATE
@ USER
The field ID hasn't been set yet; field is invalid.
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition typeinfo.h:107
Custom text control validator definitions.
@ 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