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