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 <kiway_player.h>
25#include <project.h>
28#include <trigo.h>
29#include <pcb_base_frame.h>
30#include <footprint.h>
34
35enum
36{
37 MYID_SELECT_FOOTPRINT = 991, // must be within GRID_TRICKS' enum range
39};
40
41
42wxArrayString g_menuOrientations;
43
44
46 m_frame( aFrame ),
47 m_dialog( aDialog ),
48 m_fieldNameValidator( FIELD_NAME ),
49 m_referenceValidator( REFERENCE_FIELD ),
50 m_valueValidator( VALUE_FIELD ),
51 m_urlValidator( FIELD_VALUE ),
52 m_nonUrlValidator( FIELD_VALUE )
53{
54 // Build the column attributes.
55
56 m_readOnlyAttr = new wxGridCellAttr;
57 m_readOnlyAttr->SetReadOnly( true );
58
59 m_boolColAttr = new wxGridCellAttr;
60 m_boolColAttr->SetRenderer( new wxGridCellBoolRenderer() );
61 m_boolColAttr->SetEditor( new wxGridCellBoolEditor() );
62 m_boolColAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
63
64 if( g_menuOrientations.IsEmpty() )
65 {
66 g_menuOrientations.push_back( "0" + EDA_UNIT_UTILS::GetText( EDA_UNITS::DEGREES ) );
67 g_menuOrientations.push_back( "90" + EDA_UNIT_UTILS::GetText( EDA_UNITS::DEGREES ) );
68 g_menuOrientations.push_back( "-90" + EDA_UNIT_UTILS::GetText( EDA_UNITS::DEGREES ) );
69 g_menuOrientations.push_back( "180" + EDA_UNIT_UTILS::GetText( EDA_UNITS::DEGREES ) );
70 }
71
72 m_orientationColAttr = new wxGridCellAttr;
74
75 m_layerColAttr = new wxGridCellAttr;
76 m_layerColAttr->SetRenderer( new GRID_CELL_LAYER_RENDERER( m_frame ) );
77 m_layerColAttr->SetEditor( new GRID_CELL_LAYER_SELECTOR( m_frame, {} ) );
78
79 m_referenceAttr = new wxGridCellAttr;
80 GRID_CELL_TEXT_EDITOR* referenceEditor = new GRID_CELL_TEXT_EDITOR();
81 referenceEditor->SetValidator( m_referenceValidator );
82 m_referenceAttr->SetEditor( referenceEditor );
83
84 m_valueAttr = new wxGridCellAttr;
86 valueEditor->SetValidator( m_valueValidator );
87 m_valueAttr->SetEditor( valueEditor );
88
89 m_footprintAttr = new wxGridCellAttr;
90
92 m_footprintAttr->SetReadOnly( true );
93
95 fpIdEditor->SetValidator( m_nonUrlValidator );
96 m_footprintAttr->SetEditor( fpIdEditor );
97
98 m_urlAttr = new wxGridCellAttr;
100 urlEditor->SetValidator( m_urlValidator );
101 m_urlAttr->SetEditor( urlEditor );
102
103 m_eval = std::make_unique<NUMERIC_EVALUATOR>( m_frame->GetUserUnits() );
104
105 m_frame->Bind( EDA_EVT_UNITS_CHANGED, &PCB_FIELDS_GRID_TABLE::onUnitsChanged, this );
106}
107
108
110{
111 m_readOnlyAttr->DecRef();
112 m_boolColAttr->DecRef();
113 m_orientationColAttr->DecRef();
114 m_layerColAttr->DecRef();
115 m_referenceAttr->DecRef();
116 m_valueAttr->DecRef();
117 m_footprintAttr->DecRef();
118 m_urlAttr->DecRef();
119
120 m_frame->Unbind( EDA_EVT_UNITS_CHANGED, &PCB_FIELDS_GRID_TABLE::onUnitsChanged, this );
121}
122
123
124void PCB_FIELDS_GRID_TABLE::onUnitsChanged( wxCommandEvent& aEvent )
125{
126 if( GetView() )
127 GetView()->ForceRefresh();
128
129 aEvent.Skip();
130}
131
132
134{
135 switch( aCol )
136 {
137 case PFC_NAME: return _( "Name" );
138 case PFC_VALUE: return _( "Value" );
139 case PFC_SHOWN: return _( "Show" );
140 case PFC_WIDTH: return _( "Width" );
141 case PFC_HEIGHT: return _( "Height" );
142 case PFC_THICKNESS: return _( "Thickness" );
143 case PFC_ITALIC: return _( "Italic" );
144 case PFC_LAYER: return _( "Layer" );
145 case PFC_ORIENTATION: return _( "Orientation" );
146 case PFC_UPRIGHT: return _( "Keep Upright" );
147 case PFC_XOFFSET: return _( "X Offset" );
148 case PFC_YOFFSET: return _( "Y Offset" );
149 case PFC_KNOCKOUT: return _( "Knockout" );
150 case PFC_MIRRORED: return _( "Mirrored" );
151 default: wxFAIL; return wxEmptyString;
152 }
153}
154
155
156bool PCB_FIELDS_GRID_TABLE::CanGetValueAs( int aRow, int aCol, const wxString& aTypeName )
157{
158 switch( aCol )
159 {
160 case PFC_NAME:
161 case PFC_VALUE:
162 case PFC_WIDTH:
163 case PFC_HEIGHT:
164 case PFC_THICKNESS:
165 case PFC_ORIENTATION:
166 case PFC_XOFFSET:
167 case PFC_YOFFSET:
168 return aTypeName == wxGRID_VALUE_STRING;
169
170 case PFC_SHOWN:
171 case PFC_ITALIC:
172 case PFC_UPRIGHT:
173 case PFC_KNOCKOUT:
174 case PFC_MIRRORED:
175 return aTypeName == wxGRID_VALUE_BOOL;
176
177 case PFC_LAYER:
178 return aTypeName == wxGRID_VALUE_NUMBER;
179
180 default:
181 wxFAIL;
182 return false;
183 }
184}
185
186
187bool PCB_FIELDS_GRID_TABLE::CanSetValueAs( int aRow, int aCol, const wxString& aTypeName )
188{
189 return CanGetValueAs( aRow, aCol, aTypeName );
190}
191
192
193wxGridCellAttr* PCB_FIELDS_GRID_TABLE::GetAttr( int aRow, int aCol,
194 wxGridCellAttr::wxAttrKind aKind )
195{
196 switch( aCol )
197 {
198 case PFC_NAME:
199 if( aRow < MANDATORY_FIELDS )
200 {
201 m_readOnlyAttr->IncRef();
202 return enhanceAttr( m_readOnlyAttr, aRow, aCol, aKind );
203 }
204
205 return enhanceAttr( nullptr, aRow, aCol, aKind );
206
207 case PFC_VALUE:
208 if( aRow == REFERENCE_FIELD )
209 {
210 m_referenceAttr->IncRef();
211 return enhanceAttr( m_referenceAttr, aRow, aCol, aKind );
212 }
213 else if( aRow == VALUE_FIELD )
214 {
215 m_valueAttr->IncRef();
216 return enhanceAttr( m_valueAttr, aRow, aCol, aKind );
217 }
218 else if( aRow == FOOTPRINT_FIELD )
219 {
220 m_footprintAttr->IncRef();
221 return enhanceAttr( m_footprintAttr, aRow, aCol, aKind );
222 }
223 else if( aRow == DATASHEET_FIELD )
224 {
225 m_urlAttr->IncRef();
226 return enhanceAttr( m_urlAttr, aRow, aCol, aKind );
227 }
228
229 return enhanceAttr( nullptr, aRow, aCol, aKind );
230
231 case PFC_WIDTH:
232 case PFC_HEIGHT:
233 case PFC_THICKNESS:
234 case PFC_XOFFSET:
235 case PFC_YOFFSET:
236 return enhanceAttr( nullptr, aRow, aCol, aKind );
237
238 case PFC_SHOWN:
239 case PFC_ITALIC:
240 case PFC_UPRIGHT:
241 case PFC_KNOCKOUT:
242 case PFC_MIRRORED:
243 m_boolColAttr->IncRef();
244 return enhanceAttr( m_boolColAttr, aRow, aCol, aKind );
245
246 case PFC_LAYER:
247 m_layerColAttr->IncRef();
248 return enhanceAttr( m_layerColAttr, aRow, aCol, aKind );
249
250 case PFC_ORIENTATION:
251 m_orientationColAttr->IncRef();
252 return enhanceAttr( m_orientationColAttr, aRow, aCol, aKind );
253
254 default:
255 wxFAIL;
256 return enhanceAttr( nullptr, aRow, aCol, aKind );
257 }
258}
259
260
261wxString PCB_FIELDS_GRID_TABLE::GetValue( int aRow, int aCol )
262{
263 wxGrid* grid = GetView();
264 const PCB_FIELD& field = this->at( (size_t) aRow );
265
266 if( grid->GetGridCursorRow() == aRow && grid->GetGridCursorCol() == aCol
267 && grid->IsCellEditControlShown() )
268 {
269 auto it = m_evalOriginal.find( { aRow, aCol } );
270
271 if( it != m_evalOriginal.end() )
272 return it->second;
273 }
274
275 switch( aCol )
276 {
277 case PFC_NAME: return field.GetName();
278 case PFC_VALUE: return field.GetText();
279 case PFC_WIDTH: return m_frame->StringFromValue( field.GetTextWidth(), true );
280 case PFC_HEIGHT: return m_frame->StringFromValue( field.GetTextHeight(), true );
281 case PFC_THICKNESS: return m_frame->StringFromValue( field.GetTextThickness(), true );
282 case PFC_LAYER: return field.GetLayerName();
283
284 case PFC_ORIENTATION:
285 {
286 EDA_ANGLE angle = field.GetTextAngle() - field.GetParentFootprint()->GetOrientation();
287 return m_frame->StringFromValue( angle, true );
288 }
289
290 case PFC_XOFFSET: return m_frame->StringFromValue( field.GetFPRelativePosition().x, true );
291 case PFC_YOFFSET: return m_frame->StringFromValue( field.GetFPRelativePosition().y, true );
292
293 default:
294 // we can't assert here because wxWidgets sometimes calls this without checking
295 // the column type when trying to see if there's an overflow
296 return wxT( "bad wxWidgets!" );
297 }
298}
299
300
302{
303 PCB_FIELD& field = this->at( (size_t) aRow );
304
305 switch( aCol )
306 {
307 case PFC_SHOWN: return field.IsVisible();
308 case PFC_ITALIC: return field.IsItalic();
309 case PFC_UPRIGHT: return field.IsKeepUpright();
310 case PFC_KNOCKOUT: return field.IsKnockout();
311 case PFC_MIRRORED: return field.IsMirrored();
312
313 default:
314 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a bool value" ), aCol ) );
315 return false;
316 }
317}
318
319
321{
322 PCB_FIELD& field = this->at( (size_t) aRow );
323
324 switch( aCol )
325 {
326 case PFC_LAYER: return field.GetLayer();
327
328 default:
329 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a long value" ), aCol ) );
330 return 0;
331 }
332}
333
334
335void PCB_FIELDS_GRID_TABLE::SetValue( int aRow, int aCol, const wxString &aValue )
336{
337 PCB_FIELD& field = this->at( (size_t) aRow );
338 VECTOR2I pos;
339 wxString value = aValue;
340
341 switch( aCol )
342 {
343 case PFC_WIDTH:
344 case PFC_HEIGHT:
345 case PFC_THICKNESS:
346 case PFC_XOFFSET:
347 case PFC_YOFFSET:
348 m_eval->SetDefaultUnits( m_frame->GetUserUnits() );
349
350 if( m_eval->Process( value ) )
351 {
352 m_evalOriginal[ { aRow, aCol } ] = value;
353 value = m_eval->Result();
354 }
355
356 break;
357
358 default:
359 break;
360 }
361
362 switch( aCol )
363 {
364 case PFC_NAME: field.SetName( value ); break;
365 case PFC_VALUE: field.SetText( value ); break;
366 case PFC_WIDTH: field.SetTextWidth( m_frame->ValueFromString( value ) ); break;
367 case PFC_HEIGHT: field.SetTextHeight( m_frame->ValueFromString( value ) ); break;
368 case PFC_THICKNESS: field.SetTextThickness( m_frame->ValueFromString( value ) ); break;
369
370 case PFC_ORIENTATION:
372 + field.GetParentFootprint()->GetOrientation() );
373 break;
374
375 case PFC_XOFFSET:
376 case PFC_YOFFSET:
377 pos = field.GetFPRelativePosition();
378
379 if( aCol == PFC_XOFFSET )
380 pos.x = m_frame->ValueFromString( value );
381 else
382 pos.y = m_frame->ValueFromString( value );
383
384 field.SetFPRelativePosition( pos );
385 break;
386
387 default:
388 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a string value" ), aCol ) );
389 break;
390 }
391
392 GetView()->Refresh();
393}
394
395
396void PCB_FIELDS_GRID_TABLE::SetValueAsBool( int aRow, int aCol, bool aValue )
397{
398 PCB_FIELD& field = this->at( (size_t) aRow );
399
400 switch( aCol )
401 {
402 case PFC_SHOWN: field.SetVisible( aValue ); break;
403 case PFC_ITALIC: field.SetItalic( aValue ); break;
404 case PFC_UPRIGHT: field.SetKeepUpright( aValue ); break;
405 case PFC_KNOCKOUT: field.SetIsKnockout( aValue ); break;
406 case PFC_MIRRORED: field.SetMirrored( aValue ); break;
407
408 default:
409 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a bool value" ), aCol ) );
410 break;
411 }
412}
413
414
415void PCB_FIELDS_GRID_TABLE::SetValueAsLong( int aRow, int aCol, long aValue )
416{
417 PCB_FIELD& field = this->at( (size_t) aRow );
418
419 switch( aCol )
420 {
421 case PFC_LAYER:
422 field.SetLayer( ToLAYER_ID( (int) aValue ) );
423 field.SetMirrored( IsBackLayer( field.GetLayer() ) );
424 break;
425
426 default:
427 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a long value" ), aCol ) );
428 break;
429 }
430}
431
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:231
virtual bool IsKnockout() const
Definition: board_item.h:301
virtual void SetIsKnockout(bool aKnockout)
Definition: board_item.h:302
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:265
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:248
VECTOR2I GetFPRelativePosition() const
Definition: board_item.cpp:262
void SetFPRelativePosition(const VECTOR2I &aPos)
Definition: board_item.cpp:276
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Definition: board_item.cpp:103
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition: dialog_shim.h:88
bool IsType(FRAME_T aType) const
int GetTextHeight() const
Definition: eda_text.h:228
bool IsItalic() const
Definition: eda_text.h:144
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:134
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:98
bool IsKeepUpright() const
Definition: eda_text.h:170
virtual bool IsVisible() const
Definition: eda_text.h:151
void SetMirrored(bool isMirrored)
Definition: eda_text.cpp:250
int GetTextWidth() const
Definition: eda_text.h:225
void SetTextWidth(int aWidth)
Definition: eda_text.cpp:395
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:243
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:195
void SetTextHeight(int aHeight)
Definition: eda_text.cpp:406
bool IsMirrored() const
Definition: eda_text.h:154
void SetKeepUpright(bool aKeepUpright)
Definition: eda_text.cpp:282
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:181
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:203
int GetTextThickness() const
Definition: eda_text.h:126
void SetItalic(bool aItalic)
Definition: eda_text.cpp:211
EDA_ANGLE GetOrientation() const
Definition: footprint.h:214
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
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
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_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:979
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:1022
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
@ 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