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, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <board.h>
21#include <footprint.h>
23#include <kiway.h>
24#include <kiway_player.h>
26#include <pcb_base_frame.h>
27#include <pcb_edit_frame.h>
28#include <project.h>
29#include <trigo.h>
31
35
36enum
37{
38 MYID_SELECT_FOOTPRINT = 991, // must be within GRID_TRICKS' enum range
40};
41
42
43wxArrayString g_menuOrientations;
44
45
47 std::vector<EMBEDDED_FILES*> aFilesStack ) :
48 m_frame( aFrame ),
49 m_dialog( aDialog ),
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, aFilesStack );
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() == FIELD_T::REFERENCE )
217 {
218 m_referenceAttr->IncRef();
219 return enhanceAttr( m_referenceAttr, aRow, aCol, aKind );
220 }
221 else if( field.GetId() == FIELD_T::VALUE )
222 {
223 m_valueAttr->IncRef();
224 return enhanceAttr( m_valueAttr, aRow, aCol, aKind );
225 }
226 else if( field.GetId() == FIELD_T::DATASHEET || field.HasHypertext() )
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 if( aCol != PFC_VALUE )
345 value.Trim( true ).Trim( false );
346
347 if( aCol == PFC_WIDTH
348 || aCol == PFC_HEIGHT
349 || aCol == PFC_THICKNESS
350 || aCol == PFC_XOFFSET
351 || aCol == PFC_YOFFSET )
352 {
353 m_eval->SetDefaultUnits( m_frame->GetUserUnits() );
354
355 if( m_eval->Process( value ) )
356 {
357 m_evalOriginal[ { aRow, aCol } ] = value;
358 value = m_eval->Result();
359 }
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:
371 field.SetTextAngle( m_frame->AngleValueFromString( value )
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 m_dialog->OnModify();
394}
395
396
397void PCB_FIELDS_GRID_TABLE::SetValueAsBool( int aRow, int aCol, bool aValue )
398{
399 PCB_FIELD& field = this->at( (size_t) aRow );
400
401 switch( aCol )
402 {
403 case PFC_SHOWN: field.SetVisible( aValue ); break;
404 case PFC_ITALIC: field.SetItalic( aValue ); break;
405 case PFC_UPRIGHT: field.SetKeepUpright( aValue ); break;
406 case PFC_KNOCKOUT: field.SetIsKnockout( aValue ); break;
407 case PFC_MIRRORED: field.SetMirrored( aValue ); break;
408
409 default:
410 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a bool value" ), aCol ) );
411 break;
412 }
413
414 m_dialog->OnModify();
415}
416
417
418void PCB_FIELDS_GRID_TABLE::SetValueAsLong( int aRow, int aCol, long aValue )
419{
420 PCB_FIELD& field = this->at( (size_t) aRow );
421
422 switch( aCol )
423 {
424 case PFC_LAYER:
425 field.SetLayer( ToLAYER_ID( (int) aValue ) );
426
427 if( BOARD* board = field.GetBoard() )
428 field.SetMirrored( board->IsBackLayer( field.GetLayer() ) );
429 else
430 field.SetMirrored( IsBackLayer( field.GetLayer() ) );
431
432 break;
433
434 default:
435 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a long value" ), aCol ) );
436 break;
437 }
438
439 m_dialog->OnModify();
440}
441
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:265
virtual bool IsKnockout() const
Definition board_item.h:352
virtual void SetIsKnockout(bool aKnockout)
Definition board_item.h:353
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition board_item.h:313
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
FOOTPRINT * GetParentFootprint() const
VECTOR2I GetFPRelativePosition() const
void SetFPRelativePosition(const VECTOR2I &aPos)
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:372
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition dialog_shim.h:65
bool IsItalic() const
Definition eda_text.h:190
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:110
bool IsKeepUpright() const
Definition eda_text.h:227
virtual bool IsVisible() const
Definition eda_text.h:208
virtual int GetTextHeight() const
Definition eda_text.h:288
void SetMirrored(bool isMirrored)
Definition eda_text.cpp:388
virtual int GetTextWidth() const
Definition eda_text.h:285
virtual void SetTextWidth(int aWidth)
Definition eda_text.cpp:554
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:381
virtual void SetTextHeight(int aHeight)
Definition eda_text.cpp:565
bool IsMirrored() const
Definition eda_text.h:211
void SetKeepUpright(bool aKeepUpright)
Definition eda_text.cpp:420
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:265
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
Definition eda_text.cpp:302
EDA_ANGLE GetOrientation() const
Definition footprint.h:406
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.
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
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
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
FIELD_VALIDATOR m_fieldNameValidator
wxGridCellAttr * m_orientationColAttr
void SetValueAsLong(int aRow, int aCol, long aValue) override
bool IsMandatory() const
FIELD_T GetId() const
Definition pcb_field.h:110
bool HasHypertext() const
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
void SetName(const wxString &aName)
Definition pcb_field.h:108
void SetTextThickness(int aWidth) override
The TextThickness is that set by the user.
Definition pcb_text.cpp:495
EDA_ANGLE GetTextAngle() const override
Definition pcb_text.cpp:543
int GetTextThickness() const override
Definition pcb_text.cpp:480
void SetTextAngle(const EDA_ANGLE &aAngle) override
Definition pcb_text.cpp:552
wxGridCellAttr * enhanceAttr(wxGridCellAttr *aInputAttr, int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind)
Definition wx_grid.cpp:43
@ MYID_SELECT_FOOTPRINT
#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:801
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition lset.cpp:750
wxArrayString g_menuOrientations
@ PFC_THICKNESS
@ PFC_ORIENTATION
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
@ DATASHEET
name of datasheet
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683