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 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 EMBEDDED_FILES* files = nullptr;
95
96 // In the case of the footprint editor, we need to distinguish between the footprint
97 // in the library where the embedded files are stored with the footprint and the footprint
98 // from the board where the embedded files are stored with the board.
100 {
101 FOOTPRINT_EDIT_FRAME* fpFrame = static_cast<FOOTPRINT_EDIT_FRAME*>( m_frame );
102
103 if( fpFrame->IsCurrentFPFromBoard() )
104 {
106
107 if( pcbframe != nullptr ) // happens when the board editor is not active (or closed)
108 {
109 files = pcbframe->GetBoard();
110 }
111 }
112 else
113 {
114 files = fpFrame->GetBoard()->GetFirstFootprint();
115 }
116 }
117 else if( m_frame->GetFrameType() == FRAME_PCB_EDITOR )
118 {
119 files = static_cast<PCB_EDIT_FRAME*>( m_frame )->GetBoard();
120 }
121
122 m_urlAttr = new wxGridCellAttr;
123 GRID_CELL_URL_EDITOR* urlEditor = new GRID_CELL_URL_EDITOR( m_dialog, nullptr, files );
124 urlEditor->SetValidator( m_urlValidator );
125 m_urlAttr->SetEditor( urlEditor );
126
127 m_eval = std::make_unique<NUMERIC_EVALUATOR>( m_frame->GetUserUnits() );
128
129 m_frame->Bind( EDA_EVT_UNITS_CHANGED, &PCB_FIELDS_GRID_TABLE::onUnitsChanged, this );
130}
131
132
134{
135 m_readOnlyAttr->DecRef();
136 m_boolColAttr->DecRef();
137 m_orientationColAttr->DecRef();
138 m_layerColAttr->DecRef();
139 m_referenceAttr->DecRef();
140 m_valueAttr->DecRef();
141 m_urlAttr->DecRef();
142
143 m_frame->Unbind( EDA_EVT_UNITS_CHANGED, &PCB_FIELDS_GRID_TABLE::onUnitsChanged, this );
144}
145
146
147void PCB_FIELDS_GRID_TABLE::onUnitsChanged( wxCommandEvent& aEvent )
148{
149 if( GetView() )
150 GetView()->ForceRefresh();
151
152 aEvent.Skip();
153}
154
155
157{
158 switch( aCol )
159 {
160 case PFC_NAME: return _( "Name" );
161 case PFC_VALUE: return _( "Value" );
162 case PFC_SHOWN: return _( "Show" );
163 case PFC_WIDTH: return _( "Width" );
164 case PFC_HEIGHT: return _( "Height" );
165 case PFC_THICKNESS: return _( "Thickness" );
166 case PFC_ITALIC: return _( "Italic" );
167 case PFC_LAYER: return _( "Layer" );
168 case PFC_ORIENTATION: return _( "Orientation" );
169 case PFC_UPRIGHT: return _( "Keep Upright" );
170 case PFC_XOFFSET: return _( "X Offset" );
171 case PFC_YOFFSET: return _( "Y Offset" );
172 case PFC_KNOCKOUT: return _( "Knockout" );
173 case PFC_MIRRORED: return _( "Mirrored" );
174 default: wxFAIL; return wxEmptyString;
175 }
176}
177
178
179bool PCB_FIELDS_GRID_TABLE::CanGetValueAs( int aRow, int aCol, const wxString& aTypeName )
180{
181 switch( aCol )
182 {
183 case PFC_NAME:
184 case PFC_VALUE:
185 case PFC_WIDTH:
186 case PFC_HEIGHT:
187 case PFC_THICKNESS:
188 case PFC_ORIENTATION:
189 case PFC_XOFFSET:
190 case PFC_YOFFSET:
191 return aTypeName == wxGRID_VALUE_STRING;
192
193 case PFC_SHOWN:
194 case PFC_ITALIC:
195 case PFC_UPRIGHT:
196 case PFC_KNOCKOUT:
197 case PFC_MIRRORED:
198 return aTypeName == wxGRID_VALUE_BOOL;
199
200 case PFC_LAYER:
201 return aTypeName == wxGRID_VALUE_NUMBER;
202
203 default:
204 wxFAIL;
205 return false;
206 }
207}
208
209
210bool PCB_FIELDS_GRID_TABLE::CanSetValueAs( int aRow, int aCol, const wxString& aTypeName )
211{
212 return CanGetValueAs( aRow, aCol, aTypeName );
213}
214
215
216wxGridCellAttr* PCB_FIELDS_GRID_TABLE::GetAttr( int aRow, int aCol,
217 wxGridCellAttr::wxAttrKind aKind )
218{
219 switch( aCol )
220 {
221 case PFC_NAME:
222 if( aRow < MANDATORY_FIELDS )
223 {
224 m_readOnlyAttr->IncRef();
225 return enhanceAttr( m_readOnlyAttr, aRow, aCol, aKind );
226 }
227
228 return enhanceAttr( nullptr, aRow, aCol, aKind );
229
230 case PFC_VALUE:
231 if( aRow == REFERENCE_FIELD )
232 {
233 m_referenceAttr->IncRef();
234 return enhanceAttr( m_referenceAttr, aRow, aCol, aKind );
235 }
236 else if( aRow == VALUE_FIELD )
237 {
238 m_valueAttr->IncRef();
239 return enhanceAttr( m_valueAttr, aRow, aCol, aKind );
240 }
241 else if( aRow == DATASHEET_FIELD )
242 {
243 m_urlAttr->IncRef();
244 return enhanceAttr( m_urlAttr, aRow, aCol, aKind );
245 }
246
247 return enhanceAttr( nullptr, aRow, aCol, aKind );
248
249 case PFC_WIDTH:
250 case PFC_HEIGHT:
251 case PFC_THICKNESS:
252 case PFC_XOFFSET:
253 case PFC_YOFFSET:
254 return enhanceAttr( nullptr, aRow, aCol, aKind );
255
256 case PFC_SHOWN:
257 case PFC_ITALIC:
258 case PFC_UPRIGHT:
259 case PFC_KNOCKOUT:
260 case PFC_MIRRORED:
261 m_boolColAttr->IncRef();
262 return enhanceAttr( m_boolColAttr, aRow, aCol, aKind );
263
264 case PFC_LAYER:
265 m_layerColAttr->IncRef();
266 return enhanceAttr( m_layerColAttr, aRow, aCol, aKind );
267
268 case PFC_ORIENTATION:
269 m_orientationColAttr->IncRef();
270 return enhanceAttr( m_orientationColAttr, aRow, aCol, aKind );
271
272 default:
273 wxFAIL;
274 return enhanceAttr( nullptr, aRow, aCol, aKind );
275 }
276}
277
278
279wxString PCB_FIELDS_GRID_TABLE::GetValue( int aRow, int aCol )
280{
281 wxGrid* grid = GetView();
282 const PCB_FIELD& field = this->at( (size_t) aRow );
283
284 if( grid->GetGridCursorRow() == aRow && grid->GetGridCursorCol() == aCol
285 && grid->IsCellEditControlShown() )
286 {
287 auto it = m_evalOriginal.find( { aRow, aCol } );
288
289 if( it != m_evalOriginal.end() )
290 return it->second;
291 }
292
293 switch( aCol )
294 {
295 case PFC_NAME: return field.GetName();
296 case PFC_VALUE: return field.GetText();
297 case PFC_WIDTH: return m_frame->StringFromValue( field.GetTextWidth(), true );
298 case PFC_HEIGHT: return m_frame->StringFromValue( field.GetTextHeight(), true );
299 case PFC_THICKNESS: return m_frame->StringFromValue( field.GetTextThickness(), true );
300 case PFC_LAYER: return field.GetLayerName();
301
302 case PFC_ORIENTATION:
303 {
304 EDA_ANGLE angle = field.GetTextAngle() - field.GetParentFootprint()->GetOrientation();
305 return m_frame->StringFromValue( angle, true );
306 }
307
308 case PFC_XOFFSET: return m_frame->StringFromValue( field.GetFPRelativePosition().x, true );
309 case PFC_YOFFSET: return m_frame->StringFromValue( field.GetFPRelativePosition().y, true );
310
311 default:
312 // we can't assert here because wxWidgets sometimes calls this without checking
313 // the column type when trying to see if there's an overflow
314 return wxT( "bad wxWidgets!" );
315 }
316}
317
318
320{
321 PCB_FIELD& field = this->at( (size_t) aRow );
322
323 switch( aCol )
324 {
325 case PFC_SHOWN: return field.IsVisible();
326 case PFC_ITALIC: return field.IsItalic();
327 case PFC_UPRIGHT: return field.IsKeepUpright();
328 case PFC_KNOCKOUT: return field.IsKnockout();
329 case PFC_MIRRORED: return field.IsMirrored();
330
331 default:
332 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a bool value" ), aCol ) );
333 return false;
334 }
335}
336
337
339{
340 PCB_FIELD& field = this->at( (size_t) aRow );
341
342 switch( aCol )
343 {
344 case PFC_LAYER: return field.GetLayer();
345
346 default:
347 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a long value" ), aCol ) );
348 return 0;
349 }
350}
351
352
353void PCB_FIELDS_GRID_TABLE::SetValue( int aRow, int aCol, const wxString &aValue )
354{
355 PCB_FIELD& field = this->at( (size_t) aRow );
356 VECTOR2I pos;
357 wxString value = aValue;
358
359 switch( aCol )
360 {
361 case PFC_WIDTH:
362 case PFC_HEIGHT:
363 case PFC_THICKNESS:
364 case PFC_XOFFSET:
365 case PFC_YOFFSET:
366 m_eval->SetDefaultUnits( m_frame->GetUserUnits() );
367
368 if( m_eval->Process( value ) )
369 {
370 m_evalOriginal[ { aRow, aCol } ] = value;
371 value = m_eval->Result();
372 }
373
374 break;
375
376 default:
377 break;
378 }
379
380 switch( aCol )
381 {
382 case PFC_NAME: field.SetName( value ); break;
383 case PFC_VALUE: field.SetText( value ); break;
384 case PFC_WIDTH: field.SetTextWidth( m_frame->ValueFromString( value ) ); break;
385 case PFC_HEIGHT: field.SetTextHeight( m_frame->ValueFromString( value ) ); break;
386 case PFC_THICKNESS: field.SetTextThickness( m_frame->ValueFromString( value ) ); break;
387
388 case PFC_ORIENTATION:
390 + field.GetParentFootprint()->GetOrientation() );
391 break;
392
393 case PFC_XOFFSET:
394 case PFC_YOFFSET:
395 pos = field.GetFPRelativePosition();
396
397 if( aCol == PFC_XOFFSET )
398 pos.x = m_frame->ValueFromString( value );
399 else
400 pos.y = m_frame->ValueFromString( value );
401
402 field.SetFPRelativePosition( pos );
403 break;
404
405 default:
406 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a string value" ), aCol ) );
407 break;
408 }
409
410 GetView()->Refresh();
412}
413
414
415void PCB_FIELDS_GRID_TABLE::SetValueAsBool( int aRow, int aCol, bool aValue )
416{
417 PCB_FIELD& field = this->at( (size_t) aRow );
418
419 switch( aCol )
420 {
421 case PFC_SHOWN: field.SetVisible( aValue ); break;
422 case PFC_ITALIC: field.SetItalic( aValue ); break;
423 case PFC_UPRIGHT: field.SetKeepUpright( aValue ); break;
424 case PFC_KNOCKOUT: field.SetIsKnockout( aValue ); break;
425 case PFC_MIRRORED: field.SetMirrored( aValue ); break;
426
427 default:
428 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a bool value" ), aCol ) );
429 break;
430 }
431
433}
434
435
436void PCB_FIELDS_GRID_TABLE::SetValueAsLong( int aRow, int aCol, long aValue )
437{
438 PCB_FIELD& field = this->at( (size_t) aRow );
439
440 switch( aCol )
441 {
442 case PFC_LAYER:
443 field.SetLayer( ToLAYER_ID( (int) aValue ) );
444 field.SetMirrored( IsBackLayer( field.GetLayer() ) );
445 break;
446
447 default:
448 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a long value" ), aCol ) );
449 break;
450 }
451
453}
454
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
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:456
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition: dialog_shim.h:88
void OnModify()
FRAME_T GetFrameType() const
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:384
int GetTextWidth() const
Definition: eda_text.h:251
void SetTextWidth(int aWidth)
Definition: eda_text.cpp:547
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:377
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:282
void SetTextHeight(int aHeight)
Definition: eda_text.cpp:558
bool IsMirrored() const
Definition: eda_text.h:177
void SetKeepUpright(bool aKeepUpright)
Definition: eda_text.cpp:416
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:268
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:290
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:298
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
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
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
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:105
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)
@ 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:705
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:699
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
BOARD * GetBoard()
@ DATASHEET_FIELD
name of datasheet
@ 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