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