KiCad PCB EDA Suite
Loading...
Searching...
No Matches
panel_fp_editor_defaults.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) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <pgm_base.h>
27#include <template_fieldnames.h>
29#include <grid_tricks.h>
30#include <eda_text.h>
33#include <bitmaps.h>
34#include <confirm.h>
35#include <kidialog.h>
36
37class TEXT_ITEMS_GRID_TABLE : public wxGridTableBase
38{
40 std::vector<TEXT_ITEM_INFO> m_items;
41
42public:
43 TEXT_ITEMS_GRID_TABLE( bool aForFieldProps ) :
44 m_forFieldProps( aForFieldProps )
45 { }
46
47 int GetNumberRows() override { return m_items.size(); }
48 int GetNumberCols() override { return 3; }
49
50 wxString GetColLabelValue( int aCol ) override
51 {
52 switch( aCol )
53 {
54 case 0: return m_forFieldProps ? _( "Value" ) : _( "Text Items" );
55 case 1: return _( "Show" );
56 case 2: return _( "Layer" );
57 default: return wxEmptyString;
58 }
59 }
60
61 wxString GetRowLabelValue( int aRow ) override
62 {
63 switch( aRow )
64 {
65 case 0: return _( "Reference designator" );
66 case 1: return _( "Value" );
67 default: return wxEmptyString;
68 }
69 }
70
71 bool CanGetValueAs( int aRow, int aCol, const wxString& aTypeName ) override
72 {
73 switch( aCol )
74 {
75 case 0: return aTypeName == wxGRID_VALUE_STRING;
76 case 1: return aTypeName == wxGRID_VALUE_BOOL;
77 case 2: return aTypeName == wxGRID_VALUE_NUMBER;
78 default: wxFAIL; return false;
79 }
80 }
81
82 bool CanSetValueAs( int aRow, int aCol, const wxString& aTypeName ) override
83 {
84 return CanGetValueAs( aRow, aCol, aTypeName );
85 }
86
87 wxString GetValue( int row, int col ) override
88 {
89 return m_items[row].m_Text;
90 }
91 void SetValue( int row, int col, const wxString& value ) override
92 {
93 if( col == 0 )
94 m_items[row].m_Text = value;
95 }
96
97 bool GetValueAsBool( int row, int col ) override
98 {
99 return m_items[row].m_Visible;
100 }
101 void SetValueAsBool( int row, int col, bool value ) override
102 {
103 if( col == 1 )
104 m_items[row].m_Visible = value;
105 }
106
107 long GetValueAsLong( int row, int col ) override
108 {
109 return m_items[row].m_Layer;
110 }
111 void SetValueAsLong( int row, int col, long value ) override
112 {
113 if( col == 2 )
114 m_items[row].m_Layer = (int) value;
115 }
116
117 bool AppendRows( size_t aNumRows = 1 ) override
118 {
119 for( size_t i = 0; i < aNumRows; ++i )
120 m_items.emplace_back( wxT( "" ), true, F_SilkS );
121
122 if( GetView() )
123 {
124 wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, aNumRows );
125 GetView()->ProcessTableMessage( msg );
126 }
127
128 return true;
129 }
130
131 bool DeleteRows( size_t aPos, size_t aNumRows ) override
132 {
133 // aPos may be a large positive, e.g. size_t(-1), and the sum of
134 // aPos+aNumRows may wrap here, so both ends of the range are tested.
135 if( aPos < m_items.size() && aPos + aNumRows <= m_items.size() )
136 {
137 m_items.erase( m_items.begin() + aPos, m_items.begin() + aPos + aNumRows );
138
139 if( GetView() )
140 {
141 wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, aPos, aNumRows );
142 GetView()->ProcessTableMessage( msg );
143 }
144 return true;
145 }
146
147 return false;
148 }
149};
150
151
152// Columns of graphics grid
153enum
154{
161
162enum
163{
170
173
174
176 UNITS_PROVIDER* aUnitsProvider ) :
178{
179 m_unitProvider = aUnitsProvider;
180 m_fieldPropsGrid->SetDefaultRowSize( m_fieldPropsGrid->GetDefaultRowSize() + 4 );
181
182 m_fieldPropsGrid->SetTable( new TEXT_ITEMS_GRID_TABLE( true ), true );
183 m_fieldPropsGrid->PushEventHandler( new GRID_TRICKS( m_fieldPropsGrid ) );
184 m_fieldPropsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
185
186 wxGridCellAttr* attr = new wxGridCellAttr;
187 attr->SetRenderer( new wxGridCellBoolRenderer() );
188 attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
189 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
190 m_fieldPropsGrid->SetColAttr( 1, attr );
191
192 attr = new wxGridCellAttr;
193 attr->SetRenderer( new GRID_CELL_LAYER_RENDERER( nullptr ) );
194 attr->SetEditor( new GRID_CELL_LAYER_SELECTOR( nullptr, {} ) );
195 m_fieldPropsGrid->SetColAttr( 2, attr );
196
197 m_textItemsGrid->SetDefaultRowSize( m_textItemsGrid->GetDefaultRowSize() + 4 );
198
199 m_textItemsGrid->SetTable( new TEXT_ITEMS_GRID_TABLE( false ), true );
200 m_textItemsGrid->PushEventHandler( new GRID_TRICKS( m_textItemsGrid ) );
201 m_textItemsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
202
203 attr = new wxGridCellAttr;
204 attr->SetRenderer( new wxGridCellBoolRenderer() );
205 attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
206 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
207 m_textItemsGrid->SetColAttr( 1, attr );
208
209 attr = new wxGridCellAttr;
210 attr->SetRenderer( new GRID_CELL_LAYER_RENDERER( nullptr ) );
211 attr->SetEditor( new GRID_CELL_LAYER_SELECTOR( nullptr, {} ) );
212 m_textItemsGrid->SetColAttr( 2, attr );
213
214 m_graphicsGrid->SetUnitsProvider( aUnitsProvider );
219
220 m_graphicsGrid->SetDefaultRowSize( m_graphicsGrid->GetDefaultRowSize() + 4 );
221
222 // Work around a bug in wxWidgets where it fails to recalculate the grid height
223 // after changing the default row size
224 m_graphicsGrid->AppendRows( 1 );
225 m_graphicsGrid->DeleteRows( m_graphicsGrid->GetNumberRows() - 1, 1 );
226
227 m_graphicsGrid->PushEventHandler( new GRID_TRICKS( m_graphicsGrid ) );
228}
229
230
232{
233 // destroy GRID_TRICKS before grids.
234 m_fieldPropsGrid->PopEventHandler( true );
235 m_textItemsGrid->PopEventHandler( true );
236 m_graphicsGrid->PopEventHandler( true );
237}
238
239
241{
242 wxColour disabledColour = wxSystemSettings::GetColour( wxSYS_COLOUR_FRAMEBK );
243
244 auto disableCell =
245 [&]( int row, int col )
246 {
247 m_graphicsGrid->SetReadOnly( row, col );
248 m_graphicsGrid->SetCellBackgroundColour( row, col, disabledColour );
249 };
250
251 for( int i = 0; i < ROW_COUNT; ++i )
252 {
254
255 if( i == ROW_EDGES || i == ROW_COURTYARD )
256 {
257 disableCell( i, COL_TEXT_WIDTH );
258 disableCell( i, COL_TEXT_HEIGHT );
259 disableCell( i, COL_TEXT_THICKNESS );
260 disableCell( i, COL_TEXT_ITALIC );
261 }
262 else
263 {
267 m_graphicsGrid->SetCellValue( i, COL_TEXT_ITALIC, aCfg->m_DesignSettings.m_TextItalic[ i ] ? wxT( "1" ) : wxT( "" ) );
268
269 auto attr = new wxGridCellAttr;
270 attr->SetRenderer( new wxGridCellBoolRenderer() );
271 attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
272 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
273 m_graphicsGrid->SetAttr( i, COL_TEXT_ITALIC, attr );
274 }
275 }
276
277 // Footprint defaults
278 m_fieldPropsGrid->GetTable()->DeleteRows( 0, m_textItemsGrid->GetNumberRows() );
279 m_fieldPropsGrid->GetTable()->AppendRows( 2 );
280
281 for( int i : { REFERENCE_FIELD, VALUE_FIELD } )
282 {
284
285 m_fieldPropsGrid->GetTable()->SetValue( i, 0, item.m_Text );
286 m_fieldPropsGrid->GetTable()->SetValueAsBool( i, 1, item.m_Visible );
287 m_fieldPropsGrid->GetTable()->SetValueAsLong( i, 2, item.m_Layer );
288 }
289
290 m_textItemsGrid->GetTable()->DeleteRows( 0, m_textItemsGrid->GetNumberRows() );
291 m_textItemsGrid->GetTable()->AppendRows( aCfg->m_DesignSettings.m_DefaultFPTextItems.size() - 2 );
292
293 for( int i = 2; i < (int) aCfg->m_DesignSettings.m_DefaultFPTextItems.size(); ++i )
294 {
296
297 m_textItemsGrid->GetTable()->SetValue( i - 2, 0, item.m_Text );
298 m_textItemsGrid->GetTable()->SetValueAsBool( i - 2, 1, item.m_Visible );
299 m_textItemsGrid->GetTable()->SetValueAsLong( i - 2, 2, item.m_Layer );
300 }
301
302 for( int col = 0; col < m_graphicsGrid->GetNumberCols(); col++ )
303 {
304 // Set the minimal width to the column label size.
305 m_graphicsGrid->SetColMinimalWidth( col, m_graphicsGrid->GetVisibleWidth( col, true, false ) );
306
307 // Set the width to see the full contents
308 if( m_graphicsGrid->IsColShown( col ) )
309 m_graphicsGrid->SetColSize( col, m_graphicsGrid->GetVisibleWidth( col, true, true, true ) );
310 }
311
312 m_graphicsGrid->SetRowLabelSize( m_graphicsGrid->GetVisibleWidth( -1, true, true, true ) );
313
314 Layout();
315}
316
317
319{
322
323 loadFPSettings( cfg );
324
325 return true;
326}
327
328
330{
331 bool retVal = wxPanel::Show( aShow );
332
333 if( aShow )
334 {
335 // These *should* work in the constructor, and indeed they do if this panel is the
336 // first displayed. However, on OSX 3.0.5 (at least), if another panel is displayed
337 // first then the icons will be blank unless they're set here.
338 m_bpAdd->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
339 m_bpDelete->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
340 }
341
342 if( aShow && m_firstShow )
343 {
344 m_graphicsGrid->SetColSize( 0, m_graphicsGrid->GetColSize( 0 ) + 1 );
345 m_firstShow = false;
346 }
347
348 return retVal;
349}
350
351
353{
355 return false;
356
358 BOARD_DESIGN_SETTINGS& cfg = mgr.GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>( "fpedit" )->m_DesignSettings;
359
360 // A minimal value for sizes and thickness:
361 const int minWidth = pcbIUScale.mmToIU( MINIMUM_LINE_WIDTH_MM );
362 const int maxWidth = pcbIUScale.mmToIU( MAXIMUM_LINE_WIDTH_MM );
364 const int maxSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
365 wxString errorsMsg;
366
367 for( int i = 0; i < ROW_COUNT; ++i )
368 {
369 bool badParam = false;
370
371 int lineWidth = m_graphicsGrid->GetUnitValue( i, COL_LINE_THICKNESS );
372
373 if( lineWidth < minWidth || lineWidth > maxWidth )
374 {
375 if( !errorsMsg.IsEmpty() )
376 errorsMsg += wxT( "\n\n" );
377
378 errorsMsg += wxString::Format( _( "%s: Incorrect line width.\n"
379 "It must be between %s and %s" ),
380 m_graphicsGrid->GetRowLabelValue( i ),
381 m_unitProvider->StringFromValue( minWidth , true),
382 m_unitProvider->StringFromValue( maxWidth , true) );
383 badParam = true;
384 }
385
386 if( !badParam )
387 cfg.m_LineThickness[ i ] = lineWidth;
388
389 if( i == ROW_EDGES || i == ROW_COURTYARD )
390 continue;
391
392 badParam = false;
393 int textWidth = m_graphicsGrid->GetUnitValue( i, COL_TEXT_WIDTH );
394 int textHeight = m_graphicsGrid->GetUnitValue( i, COL_TEXT_HEIGHT );
395 int textThickness = m_graphicsGrid->GetUnitValue( i, COL_TEXT_THICKNESS );
396
397 if( textWidth < minSize || textHeight < minSize
398 || textWidth > maxSize || textHeight > maxSize )
399 {
400 if( !errorsMsg.IsEmpty() )
401 errorsMsg += wxT( "\n\n" );
402
403 errorsMsg += wxString::Format( _( "%s: Text size is incorrect.\n"
404 "Size must be between %s and %s" ),
405 m_graphicsGrid->GetRowLabelValue( i ),
407 m_unitProvider->StringFromValue( maxSize , true) );
408 badParam = true;
409 }
410
411 // Text thickness cannot be > text size /4 to be readable
412 int textMinDim = std::min( textWidth, textHeight );
413 int textMaxThickness = std::min( maxWidth, textMinDim /4);
414
415 if( !badParam && ( textThickness < minWidth || textThickness > textMaxThickness ) )
416 {
417 if( !errorsMsg.IsEmpty() )
418 errorsMsg += wxT( "\n\n" );
419
420 if( textThickness > textMaxThickness )
421 errorsMsg += wxString::Format( _( "%s: Text thickness is too large.\n"
422 "It will be truncated to %s" ),
423 m_graphicsGrid->GetRowLabelValue( i ),
424 m_unitProvider->StringFromValue( textMaxThickness , true) );
425
426 else if( textThickness < minWidth )
427 errorsMsg += wxString::Format( _( "%s: Text thickness is too small.\n"
428 "It will be truncated to %s" ),
429 m_graphicsGrid->GetRowLabelValue( i ),
430 m_unitProvider->StringFromValue( minWidth , true ) );
431
432 textThickness = std::min( textThickness, textMaxThickness );
433 textThickness = std::max( textThickness, minWidth );
434 m_graphicsGrid->SetUnitValue( i, COL_TEXT_THICKNESS, textThickness );
435 }
436
437 if( !badParam )
438 {
439 cfg.m_TextSize[i] = VECTOR2I( textWidth, textHeight );
440 cfg.m_TextThickness[ i ] = textThickness;
441 }
442
443 wxString msg = m_graphicsGrid->GetCellValue( i, COL_TEXT_ITALIC );
444 cfg.m_TextItalic[ i ] = wxGridCellBoolEditor::IsTrueValue( msg );
445 }
446
447 // Footprint defaults
448 cfg.m_DefaultFPTextItems.clear();
449
450 wxGridTableBase* table = m_fieldPropsGrid->GetTable();
451
452 for( int i : { REFERENCE_FIELD, VALUE_FIELD } )
453 {
454 wxString text = table->GetValue( i, 0 );
455 bool visible = table->GetValueAsBool( i, 1 );
456 int layer = (int) table->GetValueAsLong( i, 2 );
457
458 cfg.m_DefaultFPTextItems.emplace_back( text, visible, layer );
459 }
460
461 table = m_textItemsGrid->GetTable();
462
463 for( int i = 0; i < m_textItemsGrid->GetNumberRows(); ++i )
464 {
465 wxString text = table->GetValue( i, 0 );
466 bool visible = table->GetValueAsBool( i, 1 );
467 int layer = (int) table->GetValueAsLong( i, 2 );
468
469 cfg.m_DefaultFPTextItems.emplace_back( text, visible, layer );
470 }
471
472 if( errorsMsg.IsEmpty() )
473 return true;
474
475 KIDIALOG dlg( wxGetTopLevelParent( this ), errorsMsg, KIDIALOG::KD_ERROR,
476 _( "Parameter error" ) );
477 dlg.ShowModal();
478
479 return false;
480}
481
482
483void PANEL_FP_EDITOR_DEFAULTS::OnAddTextItem( wxCommandEvent& event )
484{
486 return;
487
488 wxGridTableBase* table = m_textItemsGrid->GetTable();
489
490 int newRow = m_textItemsGrid->GetNumberRows();
491 table->AppendRows( 1 );
492 table->SetValueAsBool( newRow, 1, table->GetValueAsBool( newRow - 1, 1 ) );
493 table->SetValueAsLong( newRow, 2, table->GetValueAsLong( newRow - 1, 2 ) );
494
495 m_textItemsGrid->MakeCellVisible( newRow, 0 );
496 m_textItemsGrid->SetGridCursor( newRow, 0 );
497
498 m_textItemsGrid->EnableCellEditControl( true );
499 m_textItemsGrid->ShowCellEditControl();
500}
501
502
504{
505 wxArrayInt selectedRows = m_textItemsGrid->GetSelectedRows();
506
507 if( selectedRows.empty() && m_textItemsGrid->GetGridCursorRow() >= 0 )
508 selectedRows.push_back( m_textItemsGrid->GetGridCursorRow() );
509
510 if( selectedRows.empty() )
511 return;
512
514 return;
515
516 // Reverse sort so deleting a row doesn't change the indexes of the other rows.
517 selectedRows.Sort( []( int* first, int* second ) { return *second - *first; } );
518
519 for( int row : selectedRows )
520 {
521 m_textItemsGrid->GetTable()->DeleteRows( row, 1 );
522
523 if( m_textItemsGrid->GetNumberRows() > 0 )
524 {
525 m_textItemsGrid->MakeCellVisible( std::max( 0, row-1 ),
526 m_textItemsGrid->GetGridCursorCol() );
527 m_textItemsGrid->SetGridCursor( std::max( 0, row-1 ),
528 m_textItemsGrid->GetGridCursorCol() );
529 }
530 }
531}
532
533
535{
537 cfg.Load(); // Loading without a file will init to defaults
538
539 loadFPSettings( &cfg );
540}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
Definition: bitmap.cpp:110
#define MINIMUM_LINE_WIDTH_MM
#define MAXIMUM_LINE_WIDTH_MM
Container for design settings for a BOARD object.
std::vector< TEXT_ITEM_INFO > m_DefaultFPTextItems
int m_TextThickness[LAYER_CLASS_COUNT]
int m_LineThickness[LAYER_CLASS_COUNT]
VECTOR2I m_TextSize[LAYER_CLASS_COUNT]
bool m_TextItalic[LAYER_CLASS_COUNT]
BOARD_DESIGN_SETTINGS m_DesignSettings
Only some of these settings are actually used for footprint editing.
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition: grid_tricks.h:61
virtual void Load()
Updates the parameters of this object based on the current JSON document contents.
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: kidialog.h:43
@ KD_ERROR
Definition: kidialog.h:46
int ShowModal() override
Definition: kidialog.cpp:95
Class PANEL_FP_EDITOR_DEFAULTS_BASE.
virtual void OnAddTextItem(wxCommandEvent &event) override
void ResetPanel() override
Reset the contents of this panel.
bool Show(bool aShow) override
PANEL_FP_EDITOR_DEFAULTS(wxWindow *aParent, UNITS_PROVIDER *aUnitsProvider)
virtual void OnDeleteTextItem(wxCommandEvent &event) override
void loadFPSettings(FOOTPRINT_EDITOR_SETTINGS *aCfg)
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:142
T * GetAppSettings(const wxString &aFilename)
Returns a handle to the a given settings by type If the settings have already been loaded,...
void SetBitmap(const wxBitmapBundle &aBmp)
std::vector< TEXT_ITEM_INFO > m_items
bool DeleteRows(size_t aPos, size_t aNumRows) override
wxString GetRowLabelValue(int aRow) override
TEXT_ITEMS_GRID_TABLE(bool aForFieldProps)
void SetValueAsLong(int row, int col, long value) override
void SetValue(int row, int col, const wxString &value) override
wxString GetValue(int row, int col) override
void SetValueAsBool(int row, int col, bool value) override
wxString GetColLabelValue(int aCol) override
bool CanSetValueAs(int aRow, int aCol, const wxString &aTypeName) override
bool GetValueAsBool(int row, int col) override
bool AppendRows(size_t aNumRows=1) override
bool CanGetValueAs(int aRow, int aCol, const wxString &aTypeName) override
long GetValueAsLong(int row, int col) override
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.
int GetVisibleWidth(int aCol, bool aHeader=true, bool aContents=true, bool aKeep=false)
Calculates the specified column based on the actual size of the text on screen.
Definition: wx_grid.cpp:769
void SetTable(wxGridTableBase *table, bool aTakeOwnership=false)
Hide wxGrid's SetTable() method with one which doesn't mess up the grid column widths when setting th...
Definition: wx_grid.cpp:270
void SetUnitValue(int aRow, int aCol, int aValue)
Set a unitized cell's value.
Definition: wx_grid.cpp:740
int GetUnitValue(int aRow, int aCol)
Apply standard KiCad unit and eval services to a numeric cell.
Definition: wx_grid.cpp:698
void SetAutoEvalCols(const std::vector< int > &aCols)
Definition: wx_grid.h:124
void SetUnitsProvider(UNITS_PROVIDER *aProvider, int aCol=0)
Set a UNITS_PROVIDER to enable use of unit- and eval-based Getters.
Definition: wx_grid.cpp:689
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:637
This file is part of the common library.
const int minSize
Push and Shove router track width and via size dialog.
#define _(s)
#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
This file is part of the common library.
@ F_SilkS
Definition: layer_ids.h:100
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1060
see class PGM_BASE
constexpr int mmToIU(double mm) const
Definition: base_units.h:88
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:691