KiCad PCB EDA Suite
Loading...
Searching...
No Matches
fp_text_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-2022 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>
26#include <fp_text_grid_table.h>
29#include <trigo.h>
30#include <pcb_base_frame.h>
31#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 m_footprintAttr->SetReadOnly( true );
92 fpIdEditor->SetValidator( m_nonUrlValidator );
93 m_footprintAttr->SetEditor( fpIdEditor );
94
95 m_urlAttr = new wxGridCellAttr;
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, &FP_TEXT_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_footprintAttr->DecRef();
115 m_urlAttr->DecRef();
116
117 m_frame->Unbind( EDA_EVT_UNITS_CHANGED, &FP_TEXT_GRID_TABLE::onUnitsChanged, this );
118}
119
120
121void FP_TEXT_GRID_TABLE::onUnitsChanged( wxCommandEvent& aEvent )
122{
123 if( GetView() )
124 GetView()->ForceRefresh();
125
126 aEvent.Skip();
127}
128
129
131{
132 switch( aCol )
133 {
134 case FPT_NAME: return _( "Name" );
135 case FPT_VALUE: return _( "Value" );
136 case FPT_SHOWN: return _( "Show" );
137 case FPT_WIDTH: return _( "Width" );
138 case FPT_HEIGHT: return _( "Height" );
139 case FPT_THICKNESS: return _( "Thickness" );
140 case FPT_ITALIC: return _( "Italic" );
141 case FPT_LAYER: return _( "Layer" );
142 case FPT_ORIENTATION: return _( "Orientation" );
143 case FPT_UPRIGHT: return _( "Keep Upright" );
144 case FPT_XOFFSET: return _( "X Offset" );
145 case FPT_YOFFSET: return _( "Y Offset" );
146 case FPT_KNOCKOUT: return _( "Knockout" );
147 default: wxFAIL; return wxEmptyString;
148 }
149}
150
151
152bool FP_TEXT_GRID_TABLE::CanGetValueAs( int aRow, int aCol, const wxString& aTypeName )
153{
154 switch( aCol )
155 {
156 case FPT_NAME:
157 case FPT_VALUE:
158 case FPT_WIDTH:
159 case FPT_HEIGHT:
160 case FPT_THICKNESS:
161 case FPT_ORIENTATION:
162 case FPT_XOFFSET:
163 case FPT_YOFFSET:
164 return aTypeName == wxGRID_VALUE_STRING;
165
166 case FPT_SHOWN:
167 case FPT_ITALIC:
168 case FPT_UPRIGHT:
169 case FPT_KNOCKOUT:
170 return aTypeName == wxGRID_VALUE_BOOL;
171
172 case FPT_LAYER:
173 return aTypeName == wxGRID_VALUE_NUMBER;
174
175 default:
176 wxFAIL;
177 return false;
178 }
179}
180
181
182bool FP_TEXT_GRID_TABLE::CanSetValueAs( int aRow, int aCol, const wxString& aTypeName )
183{
184 return CanGetValueAs( aRow, aCol, aTypeName );
185}
186
187
188wxGridCellAttr* FP_TEXT_GRID_TABLE::GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind )
189{
190 switch( aCol )
191 {
192 case FPT_NAME:
193 if( aRow < MANDATORY_FIELDS )
194 {
195 m_readOnlyAttr->IncRef();
196 return m_readOnlyAttr;
197 }
198
199 return nullptr;
200
201 case FPT_VALUE:
202 if( aRow == REFERENCE_FIELD )
203 {
204 m_referenceAttr->IncRef();
205 return m_referenceAttr;
206 }
207 else if( aRow == VALUE_FIELD )
208 {
209 m_valueAttr->IncRef();
210 return m_valueAttr;
211 }
212 else if( aRow == FOOTPRINT_FIELD )
213 {
214 m_footprintAttr->IncRef();
215 return m_footprintAttr;
216 }
217 else if( aRow == DATASHEET_FIELD )
218 {
219 m_urlAttr->IncRef();
220 return m_urlAttr;
221 }
222
223 return nullptr;
224
225 case FPT_WIDTH:
226 case FPT_HEIGHT:
227 case FPT_THICKNESS:
228 case FPT_XOFFSET:
229 case FPT_YOFFSET:
230 return nullptr;
231
232 case FPT_SHOWN:
233 case FPT_ITALIC:
234 case FPT_UPRIGHT:
235 case FPT_KNOCKOUT:
236 m_boolColAttr->IncRef();
237 return m_boolColAttr;
238
239 case FPT_LAYER:
240 m_layerColAttr->IncRef();
241 return m_layerColAttr;
242
243 case FPT_ORIENTATION:
244 m_orientationColAttr->IncRef();
246
247 default:
248 wxFAIL;
249 return nullptr;
250 }
251}
252
253
254wxString FP_TEXT_GRID_TABLE::GetValue( int aRow, int aCol )
255{
256 wxGrid* grid = GetView();
257 const PCB_FIELD* field = this->at( (size_t) aRow );
258
259 if( grid->GetGridCursorRow() == aRow && grid->GetGridCursorCol() == aCol
260 && grid->IsCellEditControlShown() )
261 {
262 auto it = m_evalOriginal.find( { aRow, aCol } );
263
264 if( it != m_evalOriginal.end() )
265 return it->second;
266 }
267
268 switch( aCol )
269 {
270 case FPT_NAME:
271 return field->GetName();
272
273 case FPT_VALUE:
274 return field->GetText();
275
276 case FPT_WIDTH:
277 return m_frame->StringFromValue( field->GetTextWidth(), true );
278
279 case FPT_HEIGHT:
280 return m_frame->StringFromValue( field->GetTextHeight(), true );
281
282 case FPT_THICKNESS:
283 return m_frame->StringFromValue( field->GetTextThickness(), true );
284
285 case FPT_LAYER:
286 return field->GetLayerName();
287
288 case FPT_ORIENTATION:
289 {
290 EDA_ANGLE angle = field->GetTextAngle() - field->GetParentFootprint()->GetOrientation();
291 return m_frame->StringFromValue( angle, true );
292 }
293
294 case FPT_XOFFSET:
295 return m_frame->StringFromValue( field->GetFPRelativePosition().x, true );
296
297 case FPT_YOFFSET:
298 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
308bool FP_TEXT_GRID_TABLE::GetValueAsBool( int aRow, int aCol )
309{
310 PCB_FIELD* field = this->at( (size_t) aRow );
311
312 switch( aCol )
313 {
314 case FPT_SHOWN: return field->IsVisible();
315 case FPT_ITALIC: return field->IsItalic();
316 case FPT_UPRIGHT: return field->IsKeepUpright();
317 case FPT_KNOCKOUT: return field->IsKnockout();
318
319 default:
320 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a bool value" ), aCol ) );
321 return false;
322 }
323}
324
325
326long FP_TEXT_GRID_TABLE::GetValueAsLong( int aRow, int aCol )
327{
328 PCB_FIELD* field = this->at( (size_t) aRow );
329
330 switch( aCol )
331 {
332 case FPT_LAYER: return field->GetLayer();
333
334 default:
335 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a long value" ), aCol ) );
336 return 0;
337 }
338}
339
340
341void FP_TEXT_GRID_TABLE::SetValue( int aRow, int aCol, const wxString &aValue )
342{
343 PCB_FIELD* field = this->at( (size_t) aRow );
344 VECTOR2I pos;
345 wxString value = aValue;
346
347 switch( aCol )
348 {
349 case FPT_WIDTH:
350 case FPT_HEIGHT:
351 case FPT_THICKNESS:
352 case FPT_XOFFSET:
353 case FPT_YOFFSET:
354 m_eval->SetDefaultUnits( m_frame->GetUserUnits() );
355
356 if( m_eval->Process( value ) )
357 {
358 m_evalOriginal[ { aRow, aCol } ] = value;
359 value = m_eval->Result();
360 }
361
362 break;
363
364 default:
365 break;
366 }
367
368 switch( aCol )
369 {
370 case FPT_NAME:
371 field->SetName( value );
372 break;
373
374 case FPT_VALUE:
375 field->SetText( value );
376 break;
377
378 case FPT_WIDTH:
379 field->SetTextWidth( m_frame->ValueFromString( value ) );
380 break;
381
382 case FPT_HEIGHT:
383 field->SetTextHeight( m_frame->ValueFromString( value ) );
384 break;
385
386 case FPT_THICKNESS:
387 field->SetTextThickness( m_frame->ValueFromString( value ) );
388 break;
389
390 case FPT_ORIENTATION:
392 + field->GetParentFootprint()->GetOrientation() );
393 break;
394
395 case FPT_XOFFSET:
396 case FPT_YOFFSET:
397 pos = field->GetFPRelativePosition();
398
399 if( aCol == FPT_XOFFSET )
400 pos.x = m_frame->ValueFromString( value );
401 else
402 pos.y = m_frame->ValueFromString( value );
403
404 field->SetFPRelativePosition( pos );
405 break;
406
407 default:
408 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a string value" ), aCol ) );
409 break;
410 }
411
412 GetView()->Refresh();
413}
414
415
416void FP_TEXT_GRID_TABLE::SetValueAsBool( int aRow, int aCol, bool aValue )
417{
418 PCB_FIELD* field = this->at( (size_t) aRow );
419
420 switch( aCol )
421 {
422 case FPT_SHOWN:
423 field->SetVisible( aValue );
424 break;
425
426 case FPT_ITALIC:
427 field->SetItalic( aValue );
428 break;
429
430 case FPT_UPRIGHT:
431 field->SetKeepUpright( aValue );
432 break;
433
434 case FPT_KNOCKOUT:
435 field->SetIsKnockout( aValue );
436 break;
437
438 default:
439 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a bool value" ), aCol ) );
440 break;
441 }
442}
443
444
445void FP_TEXT_GRID_TABLE::SetValueAsLong( int aRow, int aCol, long aValue )
446{
447 PCB_FIELD* field = this->at( (size_t) aRow );
448
449 switch( aCol )
450 {
451 case FPT_LAYER:
452 field->SetLayer( ToLAYER_ID( (int) aValue ) );
453 field->SetMirrored( IsBackLayer( field->GetLayer() ) );
454 break;
455
456 default:
457 wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a long value" ), aCol ) );
458 break;
459 }
460}
461
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:204
virtual bool IsKnockout() const
Definition: board_item.h:274
virtual void SetIsKnockout(bool aKnockout)
Definition: board_item.h:275
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:238
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:247
VECTOR2I GetFPRelativePosition() const
Definition: board_item.cpp:261
void SetFPRelativePosition(const VECTOR2I &aPos)
Definition: board_item.cpp:275
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Definition: board_item.cpp:102
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition: dialog_shim.h:83
int GetTextHeight() const
Definition: eda_text.h:213
bool IsItalic() const
Definition: eda_text.h:141
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:131
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:95
bool IsKeepUpright() const
Definition: eda_text.h:166
virtual bool IsVisible() const
Definition: eda_text.h:147
void SetMirrored(bool isMirrored)
Definition: eda_text.cpp:233
int GetTextWidth() const
Definition: eda_text.h:210
void SetTextWidth(int aWidth)
Definition: eda_text.cpp:376
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:226
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:194
void SetTextHeight(int aHeight)
Definition: eda_text.cpp:387
void SetKeepUpright(bool aKeepUpright)
Definition: eda_text.cpp:265
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:180
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:202
int GetTextThickness() const
Definition: eda_text.h:123
void SetItalic(bool aItalic)
Definition: eda_text.cpp:210
EDA_ANGLE GetOrientation() const
Definition: footprint.h:209
wxGridCellAttr * GetAttr(int row, int col, wxGridCellAttr::wxAttrKind kind) override
void SetValueAsLong(int aRow, int aCol, long aValue) override
wxGridCellAttr * m_boolColAttr
FIELD_VALIDATOR m_urlValidator
void SetValue(int aRow, int aCol, const wxString &aValue) override
wxString GetValue(int aRow, int aCol) override
wxString GetColLabelValue(int aCol) override
PCB_BASE_FRAME * m_frame
wxGridCellAttr * m_footprintAttr
void onUnitsChanged(wxCommandEvent &aEvent)
wxGridCellAttr * m_readOnlyAttr
bool GetValueAsBool(int aRow, int aCol) override
long GetValueAsLong(int aRow, int aCol) override
void SetValueAsBool(int aRow, int aCol, bool aValue) override
wxGridCellAttr * m_orientationColAttr
DIALOG_SHIM * m_dialog
FP_TEXT_GRID_TABLE(PCB_BASE_FRAME *aFrame, DIALOG_SHIM *aDialog)
wxGridCellAttr * m_layerColAttr
bool CanSetValueAs(int aRow, int aCol, const wxString &aTypeName) override
wxGridCellAttr * m_urlAttr
wxGridCellAttr * m_valueAttr
FIELD_VALIDATOR m_valueValidator
wxGridCellAttr * m_referenceAttr
FIELD_VALIDATOR m_nonUrlValidator
bool CanGetValueAs(int aRow, int aCol, const wxString &aTypeName) override
std::map< std::pair< int, int >, wxString > m_evalOriginal
FIELD_VALIDATOR m_referenceValidator
std::unique_ptr< NUMERIC_EVALUATOR > m_eval
This class works around a bug in wxGrid where the first keystroke doesn't get sent through the valida...
Definition: validators.h:58
virtual void SetValidator(const wxValidator &validator) override
Definition: validators.cpp:47
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: pcb_field.cpp:47
void SetName(const wxString &aName)
Definition: pcb_field.h:104
EDA_ANGLE AngleValueFromString(const wxString &aTextValue)
wxString StringFromValue(double aValue, bool aAddUnitLabel=false, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Converts aValue in internal units into a united string.
int ValueFromString(const wxString &aTextValue, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Converts aTextValue in aUnits to internal units used by the frame.
EDA_UNITS GetUserUnits() const
#define _(s)
wxArrayString g_menuOrientations
@ MYID_SHOW_DATASHEET
@ MYID_SELECT_FOOTPRINT
@ FPT_ORIENTATION
@ FPT_YOFFSET
@ FPT_KNOCKOUT
@ FPT_UPRIGHT
@ FPT_ITALIC
@ FPT_LAYER
@ FPT_WIDTH
@ FPT_SHOWN
@ FPT_HEIGHT
@ FPT_VALUE
@ FPT_XOFFSET
@ FPT_THICKNESS
@ FPT_NAME
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
Definition: layer_ids.h:944
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:932
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:101
@ 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