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