KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_fields_grid_table.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-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 <board.h>
25#include <footprint.h>
27#include <kiway.h>
28#include <kiway_player.h>
30#include <pcb_base_frame.h>
31#include <pcb_edit_frame.h>
32#include <project.h>
33#include <trigo.h>
35
39
40enum
41{
42 MYID_SELECT_FOOTPRINT = 991, // must be within GRID_TRICKS' enum range
44};
45
46
47wxArrayString g_menuOrientations;
48
49
51 m_frame( aFrame ),
52 m_dialog( aDialog ),
53 m_fieldNameValidator( FIELD_NAME ),
54 m_referenceValidator( REFERENCE_FIELD ),
55 m_valueValidator( VALUE_FIELD ),
56 m_urlValidator( FIELD_VALUE ),
57 m_nonUrlValidator( FIELD_VALUE )
58{
59 // Build the column attributes.
60
61 m_readOnlyAttr = new wxGridCellAttr;
62 m_readOnlyAttr->SetReadOnly( true );
63
64 m_boolColAttr = new wxGridCellAttr;
65 m_boolColAttr->SetRenderer( new wxGridCellBoolRenderer() );
66 m_boolColAttr->SetEditor( new wxGridCellBoolEditor() );
67 m_boolColAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
68
69 if( g_menuOrientations.IsEmpty() )
70 {
71 g_menuOrientations.push_back( "0" + EDA_UNIT_UTILS::GetText( EDA_UNITS::DEGREES ) );
72 g_menuOrientations.push_back( "90" + EDA_UNIT_UTILS::GetText( EDA_UNITS::DEGREES ) );
73 g_menuOrientations.push_back( "-90" + EDA_UNIT_UTILS::GetText( EDA_UNITS::DEGREES ) );
74 g_menuOrientations.push_back( "180" + EDA_UNIT_UTILS::GetText( EDA_UNITS::DEGREES ) );
75 }
76
77 m_orientationColAttr = new wxGridCellAttr;
79
80 m_layerColAttr = new wxGridCellAttr;
81 m_layerColAttr->SetRenderer( new GRID_CELL_LAYER_RENDERER( m_frame ) );
82 m_layerColAttr->SetEditor( new GRID_CELL_LAYER_SELECTOR( m_frame, {} ) );
83
84 m_referenceAttr = new wxGridCellAttr;
85 GRID_CELL_TEXT_EDITOR* referenceEditor = new GRID_CELL_TEXT_EDITOR();
86 referenceEditor->SetValidator( m_referenceValidator );
87 m_referenceAttr->SetEditor( referenceEditor );
88
89 m_valueAttr = new wxGridCellAttr;
91 valueEditor->SetValidator( m_valueValidator );
92 m_valueAttr->SetEditor( valueEditor );
93
94 m_footprintAttr = new wxGridCellAttr;
95
97 m_footprintAttr->SetReadOnly( true );
98
100 fpIdEditor->SetValidator( m_nonUrlValidator );
101 m_footprintAttr->SetEditor( fpIdEditor );
102
103 EMBEDDED_FILES* files = nullptr;
104
105 // In the case of the footprint editor, we need to distinguish between the footprint
106 // in the library where the embedded files are stored with the footprint and the footprint
107 // from the board where the embedded files are stored with the board.
109 {
110 FOOTPRINT_EDIT_FRAME* fpFrame = static_cast<FOOTPRINT_EDIT_FRAME*>( m_frame );
111
112 if( fpFrame->IsCurrentFPFromBoard() )
113 {
115
116 if( pcbframe != nullptr ) // happens when the board editor is not active (or closed)
117 {
118 files = pcbframe->GetBoard();
119 }
120 }
121 else
122 {
123 files = fpFrame->GetBoard()->GetFirstFootprint();
124 }
125 }
126 else if( m_frame->GetFrameType() == FRAME_PCB_EDITOR )
127 {
128 files = static_cast<PCB_EDIT_FRAME*>( m_frame )->GetBoard();
129 }
130
131 m_urlAttr = new wxGridCellAttr;
132 GRID_CELL_URL_EDITOR* urlEditor = new GRID_CELL_URL_EDITOR( m_dialog, nullptr, files );
133 urlEditor->SetValidator( m_urlValidator );
134 m_urlAttr->SetEditor( urlEditor );
135
136 m_eval = std::make_unique<NUMERIC_EVALUATOR>( m_frame->GetUserUnits() );
137
138 m_frame->Bind( EDA_EVT_UNITS_CHANGED, &PCB_FIELDS_GRID_TABLE::onUnitsChanged, this );
139}
140
141
143{
144 m_readOnlyAttr->DecRef();
145 m_boolColAttr->DecRef();
146 m_orientationColAttr->DecRef();
147 m_layerColAttr->DecRef();
148 m_referenceAttr->DecRef();
149 m_valueAttr->DecRef();
150 m_footprintAttr->DecRef();
151 m_urlAttr->DecRef();
152
153 m_frame->Unbind( EDA_EVT_UNITS_CHANGED, &PCB_FIELDS_GRID_TABLE::onUnitsChanged, this );
154}
155
156
157void PCB_FIELDS_GRID_TABLE::onUnitsChanged( wxCommandEvent& aEvent )
158{
159 if( GetView() )
160 GetView()->ForceRefresh();
161
162 aEvent.Skip();
163}
164
165
167{
168 switch( aCol )
169 {
170 case PFC_NAME: return _( "Name" );
171 case PFC_VALUE: return _( "Value" );
172 case PFC_SHOWN: return _( "Show" );
173 case PFC_WIDTH: return _( "Width" );
174 case PFC_HEIGHT: return _( "Height" );
175 case PFC_THICKNESS: return _( "Thickness" );
176 case PFC_ITALIC: return _( "Italic" );
177 case PFC_LAYER: return _( "Layer" );
178 case PFC_ORIENTATION: return _( "Orientation" );
179 case PFC_UPRIGHT: return _( "Keep Upright" );
180 case PFC_XOFFSET: return _( "X Offset" );
181 case PFC_YOFFSET: return _( "Y Offset" );
182 case PFC_KNOCKOUT: return _( "Knockout" );
183 case PFC_MIRRORED: return _( "Mirrored" );
184 default: wxFAIL; return wxEmptyString;
185 }
186}
187
188
189bool PCB_FIELDS_GRID_TABLE::CanGetValueAs( int aRow, int aCol, const wxString& aTypeName )
190{
191 switch( aCol )
192 {
193 case PFC_NAME:
194 case PFC_VALUE:
195 case PFC_WIDTH:
196 case PFC_HEIGHT:
197 case PFC_THICKNESS:
198 case PFC_ORIENTATION:
199 case PFC_XOFFSET:
200 case PFC_YOFFSET:
201 return aTypeName == wxGRID_VALUE_STRING;
202
203 case PFC_SHOWN:
204 case PFC_ITALIC:
205 case PFC_UPRIGHT:
206 case PFC_KNOCKOUT:
207 case PFC_MIRRORED:
208 return aTypeName == wxGRID_VALUE_BOOL;
209
210 case PFC_LAYER:
211 return aTypeName == wxGRID_VALUE_NUMBER;
212
213 default:
214 wxFAIL;
215 return false;
216 }
217}
218
219
220bool PCB_FIELDS_GRID_TABLE::CanSetValueAs( int aRow, int aCol, const wxString& aTypeName )
221{
222 return CanGetValueAs( aRow, aCol, aTypeName );
223}
224
225
226wxGridCellAttr* PCB_FIELDS_GRID_TABLE::GetAttr( int aRow, int aCol,
227 wxGridCellAttr::wxAttrKind aKind )
228{
229 switch( aCol )
230 {
231 case PFC_NAME:
232 if( aRow < MANDATORY_FIELDS )
233 {
234 m_readOnlyAttr->IncRef();
235 return enhanceAttr( m_readOnlyAttr, aRow, aCol, aKind );
236 }
237
238 return enhanceAttr( nullptr, aRow, aCol, aKind );
239
240 case PFC_VALUE:
241 if( aRow == REFERENCE_FIELD )
242 {
243 m_referenceAttr->IncRef();
244 return enhanceAttr( m_referenceAttr, aRow, aCol, aKind );
245 }
246 else if( aRow == VALUE_FIELD )
247 {
248 m_valueAttr->IncRef();
249 return enhanceAttr( m_valueAttr, aRow, aCol, aKind );
250 }
251 else if( aRow == FOOTPRINT_FIELD )
252 {
253 m_footprintAttr->IncRef();
254 return enhanceAttr( m_footprintAttr, aRow, aCol, aKind );
255 }
256 else if( aRow == DATASHEET_FIELD )
257 {
258 m_urlAttr->IncRef();
259 return enhanceAttr( m_urlAttr, aRow, aCol, aKind );
260 }
261
262 return enhanceAttr( nullptr, aRow, aCol, aKind );
263
264 case PFC_WIDTH:
265 case PFC_HEIGHT:
266 case PFC_THICKNESS:
267 case PFC_XOFFSET:
268 case PFC_YOFFSET:
269 return enhanceAttr( nullptr, aRow, aCol, aKind );
270
271 case PFC_SHOWN:
272 case PFC_ITALIC:
273 case PFC_UPRIGHT:
274 case PFC_KNOCKOUT:
275 case PFC_MIRRORED:
276 m_boolColAttr->IncRef();
277 return enhanceAttr( m_boolColAttr, aRow, aCol, aKind );
278
279 case PFC_LAYER:
280 m_layerColAttr->IncRef();
281 return enhanceAttr( m_layerColAttr, aRow, aCol, aKind );
282
283 case PFC_ORIENTATION:
284 m_orientationColAttr->IncRef();
285 return enhanceAttr( m_orientationColAttr, aRow, aCol, aKind );
286
287 default:
288 wxFAIL;
289 return enhanceAttr( nullptr, aRow, aCol, aKind );
290 }
291}
292
293
294wxString PCB_FIELDS_GRID_TABLE::GetValue( int aRow, int aCol )
295{
296 wxGrid* grid = GetView();
297 const PCB_FIELD& field = this->at( (size_t) aRow );
298
299 if( grid->GetGridCursorRow() == aRow && grid->GetGridCursorCol() == aCol
300 && grid->IsCellEditControlShown() )
301 {
302 auto it = m_evalOriginal.find( { aRow, aCol } );
303
304 if( it != m_evalOriginal.end() )
305 return it->second;
306 }
307
308 switch( aCol )
309 {
310 case PFC_NAME: return field.GetName();
311 case PFC_VALUE: return field.GetText();
312 case PFC_WIDTH: return m_frame->StringFromValue( field.GetTextWidth(), true );
313 case PFC_HEIGHT: return m_frame->StringFromValue( field.GetTextHeight(), true );
314 case PFC_THICKNESS: return m_frame->StringFromValue( field.GetTextThickness(), true );
315 case PFC_LAYER: return field.GetLayerName();
316
317 case PFC_ORIENTATION:
318 {
319 EDA_ANGLE angle = field.GetTextAngle() - field.GetParentFootprint()->GetOrientation();
320 return m_frame->StringFromValue( angle, true );
321 }
322
323 case PFC_XOFFSET: return m_frame->StringFromValue( field.GetFPRelativePosition().x, true );
324 case PFC_YOFFSET: return m_frame->StringFromValue( field.GetFPRelativePosition().y, true );
325
326 default:
327 // we can't assert here because wxWidgets sometimes calls this without checking
328 // the column type when trying to see if there's an overflow
329 return wxT( "bad wxWidgets!" );
330 }
331}
332
333
335{
336 PCB_FIELD& field = this->at( (size_t) aRow );
337
338 switch( aCol )
339 {
340 case PFC_SHOWN: return field.IsVisible();
341 case PFC_ITALIC: return field.IsItalic();
342 case PFC_UPRIGHT: return field.IsKeepUpright();
343 case PFC_KNOCKOUT: return field.IsKnockout();
344 case PFC_MIRRORED: return field.IsMirrored();
345
346 default:
347 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a bool value" ), aCol ) );
348 return false;
349 }
350}
351
352
354{
355 PCB_FIELD& field = this->at( (size_t) aRow );
356
357 switch( aCol )
358 {
359 case PFC_LAYER: return field.GetLayer();
360
361 default:
362 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a long value" ), aCol ) );
363 return 0;
364 }
365}
366
367
368void PCB_FIELDS_GRID_TABLE::SetValue( int aRow, int aCol, const wxString &aValue )
369{
370 PCB_FIELD& field = this->at( (size_t) aRow );
371 VECTOR2I pos;
372 wxString value = aValue;
373
374 switch( aCol )
375 {
376 case PFC_WIDTH:
377 case PFC_HEIGHT:
378 case PFC_THICKNESS:
379 case PFC_XOFFSET:
380 case PFC_YOFFSET:
381 m_eval->SetDefaultUnits( m_frame->GetUserUnits() );
382
383 if( m_eval->Process( value ) )
384 {
385 m_evalOriginal[ { aRow, aCol } ] = value;
386 value = m_eval->Result();
387 }
388
389 break;
390
391 default:
392 break;
393 }
394
395 switch( aCol )
396 {
397 case PFC_NAME: field.SetName( value ); break;
398 case PFC_VALUE: field.SetText( value ); break;
399 case PFC_WIDTH: field.SetTextWidth( m_frame->ValueFromString( value ) ); break;
400 case PFC_HEIGHT: field.SetTextHeight( m_frame->ValueFromString( value ) ); break;
401 case PFC_THICKNESS: field.SetTextThickness( m_frame->ValueFromString( value ) ); break;
402
403 case PFC_ORIENTATION:
405 + field.GetParentFootprint()->GetOrientation() );
406 break;
407
408 case PFC_XOFFSET:
409 case PFC_YOFFSET:
410 pos = field.GetFPRelativePosition();
411
412 if( aCol == PFC_XOFFSET )
413 pos.x = m_frame->ValueFromString( value );
414 else
415 pos.y = m_frame->ValueFromString( value );
416
417 field.SetFPRelativePosition( pos );
418 break;
419
420 default:
421 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a string value" ), aCol ) );
422 break;
423 }
424
425 GetView()->Refresh();
426}
427
428
429void PCB_FIELDS_GRID_TABLE::SetValueAsBool( int aRow, int aCol, bool aValue )
430{
431 PCB_FIELD& field = this->at( (size_t) aRow );
432
433 switch( aCol )
434 {
435 case PFC_SHOWN: field.SetVisible( aValue ); break;
436 case PFC_ITALIC: field.SetItalic( aValue ); break;
437 case PFC_UPRIGHT: field.SetKeepUpright( aValue ); break;
438 case PFC_KNOCKOUT: field.SetIsKnockout( aValue ); break;
439 case PFC_MIRRORED: field.SetMirrored( aValue ); break;
440
441 default:
442 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a bool value" ), aCol ) );
443 break;
444 }
445}
446
447
448void PCB_FIELDS_GRID_TABLE::SetValueAsLong( int aRow, int aCol, long aValue )
449{
450 PCB_FIELD& field = this->at( (size_t) aRow );
451
452 switch( aCol )
453 {
454 case PFC_LAYER:
455 field.SetLayer( ToLAYER_ID( (int) aValue ) );
456 field.SetMirrored( IsBackLayer( field.GetLayer() ) );
457 break;
458
459 default:
460 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a long value" ), aCol ) );
461 break;
462 }
463}
464
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:240
virtual bool IsKnockout() const
Definition: board_item.h:312
virtual void SetIsKnockout(bool aKnockout)
Definition: board_item.h:313
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:276
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:264
VECTOR2I GetFPRelativePosition() const
Definition: board_item.cpp:293
void SetFPRelativePosition(const VECTOR2I &aPos)
Definition: board_item.cpp:307
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Definition: board_item.cpp:104
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:447
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition: dialog_shim.h:88
FRAME_T GetFrameType() const
bool IsType(FRAME_T aType) const
int GetTextHeight() const
Definition: eda_text.h:224
bool IsItalic() const
Definition: eda_text.h:140
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:130
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:94
bool IsKeepUpright() const
Definition: eda_text.h:166
virtual bool IsVisible() const
Definition: eda_text.h:147
void SetMirrored(bool isMirrored)
Definition: eda_text.cpp:251
int GetTextWidth() const
Definition: eda_text.h:221
void SetTextWidth(int aWidth)
Definition: eda_text.cpp:396
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:244
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:196
void SetTextHeight(int aHeight)
Definition: eda_text.cpp:407
bool IsMirrored() const
Definition: eda_text.h:150
void SetKeepUpright(bool aKeepUpright)
Definition: eda_text.cpp:283
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:182
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:204
int GetTextThickness() const
Definition: eda_text.h:122
void SetItalic(bool aItalic)
Definition: eda_text.cpp:212
EDA_ANGLE GetOrientation() const
Definition: footprint.h:216
This class works around a bug in wxGrid where the first keystroke doesn't get sent through the valida...
virtual void SetValidator(const wxValidator &validator) override
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:55
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:406
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
BOARD * GetBoard() const
The main frame for Pcbnew.
wxGridCellAttr * m_referenceAttr
PCB_FIELDS_GRID_TABLE(PCB_BASE_FRAME *aFrame, DIALOG_SHIM *aDialog)
void onUnitsChanged(wxCommandEvent &aEvent)
void SetValue(int aRow, int aCol, const wxString &aValue) override
bool GetValueAsBool(int aRow, int aCol) override
wxString GetColLabelValue(int aCol) override
bool CanGetValueAs(int aRow, int aCol, const wxString &aTypeName) override
std::map< std::pair< int, int >, wxString > m_evalOriginal
FIELD_VALIDATOR m_nonUrlValidator
long GetValueAsLong(int aRow, int aCol) override
wxGridCellAttr * m_readOnlyAttr
FIELD_VALIDATOR m_urlValidator
FIELD_VALIDATOR m_valueValidator
wxGridCellAttr * m_footprintAttr
wxString GetValue(int aRow, int aCol) override
wxGridCellAttr * GetAttr(int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind) override
std::unique_ptr< NUMERIC_EVALUATOR > m_eval
void SetValueAsBool(int aRow, int aCol, bool aValue) override
FIELD_VALIDATOR m_referenceValidator
bool CanSetValueAs(int aRow, int aCol, const wxString &aTypeName) override
wxGridCellAttr * m_boolColAttr
wxGridCellAttr * m_layerColAttr
wxGridCellAttr * m_orientationColAttr
void SetValueAsLong(int aRow, int aCol, long aValue) override
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: pcb_field.cpp:92
void SetName(const wxString &aName)
Definition: pcb_field.h:107
EDA_ANGLE AngleValueFromString(const wxString &aTextValue) const
EDA_UNITS GetUserUnits() const
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 ValueFromString(const wxString &aTextValue, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
Converts aTextValue in aUnits to internal units used by the frame.
wxGridCellAttr * enhanceAttr(wxGridCellAttr *aInputAttr, int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind)
Definition: wx_grid.cpp:42
#define _(s)
@ FRAME_PCB_EDITOR
Definition: frame_type.h:42
@ FRAME_FOOTPRINT_EDITOR
Definition: frame_type.h:43
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
Definition: layer_ids.h:628
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:875
KICOMMON_API wxString GetText(EDA_UNITS aUnits, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Get the units string for a given units type.
Definition: eda_units.cpp:126
wxArrayString g_menuOrientations
@ MYID_SHOW_DATASHEET
@ MYID_SELECT_FOOTPRINT
@ PFC_XOFFSET
@ PFC_KNOCKOUT
@ PFC_ITALIC
@ PFC_HEIGHT
@ PFC_THICKNESS
@ PFC_MIRRORED
@ PFC_ORIENTATION
@ PFC_UPRIGHT
@ PFC_YOFFSET
BOARD * GetBoard()
@ DATASHEET_FIELD
name of datasheet
@ FOOTPRINT_FIELD
Field Name Module PCB, i.e. "16DIP300".
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ MANDATORY_FIELDS
The first 5 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
#define FIELD_NAME
Definition: validators.h:43
#define FIELD_VALUE
Definition: validators.h:44