KiCad PCB EDA Suite
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 (C) 2018 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.h>
25 #include <kiway_player.h>
26 #include <dialog_shim.h>
27 #include <fields_grid_table.h>
28 #include <sch_base_frame.h>
29 #include <sch_field.h>
30 #include <sch_validators.h>
31 #include <validators.h>
32 #include <class_library.h>
33 #include <template_fieldnames.h>
36 
37 #include "eda_doc.h"
38 
39 
40 enum
41 {
42  MYID_SELECT_FOOTPRINT = 991, // must be within GRID_TRICKS' enum range
44 };
45 
46 
47 template <class T>
49  LIB_PART* aPart ) :
50  m_frame( aFrame ),
51  m_userUnits( aDialog->GetUserUnits() ),
52  m_part( aPart ),
53  m_fieldNameValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_NAME ),
54  m_referenceValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), REFERENCE ),
55  m_valueValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), VALUE )
56 {
57  // Build the various grid cell attributes.
58 
59  m_readOnlyAttr = new wxGridCellAttr;
60  m_readOnlyAttr->SetReadOnly( true );
61 
62  m_fieldNameAttr = new wxGridCellAttr;
63  GRID_CELL_TEXT_EDITOR* nameEditor = new GRID_CELL_TEXT_EDITOR();
64  nameEditor->SetValidator( m_fieldNameValidator );
65  m_fieldNameAttr->SetEditor( nameEditor );
66 
67  m_referenceAttr = new wxGridCellAttr;
68  GRID_CELL_TEXT_EDITOR* referenceEditor = new GRID_CELL_TEXT_EDITOR();
69  referenceEditor->SetValidator( m_referenceValidator );
70  m_referenceAttr->SetEditor( referenceEditor );
71 
72  m_valueAttr = new wxGridCellAttr;
73  GRID_CELL_TEXT_EDITOR* valueEditor = new GRID_CELL_TEXT_EDITOR();
74  valueEditor->SetValidator( m_valueValidator );
75  m_valueAttr->SetEditor( valueEditor );
76 
77  m_footprintAttr = new wxGridCellAttr;
78  m_footprintAttr->SetEditor( new GRID_CELL_FOOTPRINT_ID_EDITOR( aDialog ) );
79 
80  m_urlAttr = new wxGridCellAttr;
81  m_urlAttr->SetEditor( new GRID_CELL_URL_EDITOR( aDialog ) );
82 
83  m_boolAttr = new wxGridCellAttr;
84  m_boolAttr->SetRenderer( new wxGridCellBoolRenderer() );
85  m_boolAttr->SetEditor( new wxGridCellBoolEditor() );
86  m_boolAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_BOTTOM );
87 
88  wxArrayString vAlignNames;
89  vAlignNames.Add( _( "Top" ) );
90  vAlignNames.Add( _( "Center" ) );
91  vAlignNames.Add( _( "Bottom" ) );
92  m_vAlignAttr = new wxGridCellAttr;
93  m_vAlignAttr->SetEditor( new wxGridCellChoiceEditor( vAlignNames ) );
94  m_vAlignAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_BOTTOM );
95 
96  wxArrayString hAlignNames;
97  hAlignNames.Add( _( "Left" ) );
98  hAlignNames.Add(_( "Center" ) );
99  hAlignNames.Add(_( "Right" ) );
100  m_hAlignAttr = new wxGridCellAttr;
101  m_hAlignAttr->SetEditor( new wxGridCellChoiceEditor( hAlignNames ) );
102  m_hAlignAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_BOTTOM );
103 
104  wxArrayString orientationNames;
105  orientationNames.Add( _( "Horizontal" ) );
106  orientationNames.Add(_( "Vertical" ) );
107  m_orientationAttr = new wxGridCellAttr;
108  m_orientationAttr->SetEditor( new wxGridCellChoiceEditor( orientationNames ) );
109  m_orientationAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_BOTTOM );
110 }
111 
112 
113 template <class T>
115 {
116  m_readOnlyAttr->DecRef();
117  m_fieldNameAttr->DecRef();
118  m_boolAttr->DecRef();
119  m_referenceAttr->DecRef();
120  m_valueAttr->DecRef();
121  m_footprintAttr->DecRef();
122  m_urlAttr->DecRef();
123  m_vAlignAttr->DecRef();
124  m_hAlignAttr->DecRef();
125  m_orientationAttr->DecRef();
126 }
127 
128 
129 template <class T>
131 {
132  switch( aCol )
133  {
134  case FDC_NAME: return _( "Name" );
135  case FDC_VALUE: return _( "Value" );
136  case FDC_SHOWN: return _( "Show" );
137  case FDC_H_ALIGN: return _( "H Align" );
138  case FDC_V_ALIGN: return _( "V Align" );
139  case FDC_ITALIC: return _( "Italic" );
140  case FDC_BOLD: return _( "Bold" );
141  case FDC_TEXT_SIZE: return _( "Text Size" );
142  case FDC_ORIENTATION: return _( "Orientation" );
143  case FDC_POSX: return _( "X Position" );
144  case FDC_POSY: return _( "Y Position" );
145  default: wxFAIL; return wxEmptyString;
146  }
147 }
148 
149 
150 template <class T>
151 bool FIELDS_GRID_TABLE<T>::CanGetValueAs( int aRow, int aCol, const wxString& aTypeName )
152 {
153  switch( aCol )
154  {
155  case FDC_NAME:
156  case FDC_VALUE:
157  case FDC_H_ALIGN:
158  case FDC_V_ALIGN:
159  case FDC_TEXT_SIZE:
160  case FDC_ORIENTATION:
161  case FDC_POSX:
162  case FDC_POSY:
163  return aTypeName == wxGRID_VALUE_STRING;
164 
165  case FDC_SHOWN:
166  case FDC_ITALIC:
167  case FDC_BOLD:
168  return aTypeName == wxGRID_VALUE_BOOL;
169 
170  default:
171  wxFAIL;
172  return false;
173  }
174 }
175 
176 
177 template <class T>
178 bool FIELDS_GRID_TABLE<T>::CanSetValueAs( int aRow, int aCol, const wxString& aTypeName )
179 {
180  return CanGetValueAs( aRow, aCol, aTypeName );
181 }
182 
183 
184 template <class T>
185 wxGridCellAttr* FIELDS_GRID_TABLE<T>::GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind )
186 {
187  switch( aCol )
188  {
189  case FDC_NAME:
190  if( aRow < MANDATORY_FIELDS )
191  {
192  m_readOnlyAttr->IncRef();
193  return m_readOnlyAttr;
194  }
195  else
196  {
197  m_fieldNameAttr->IncRef();
198  return m_fieldNameAttr;
199  }
200 
201  case FDC_VALUE:
202  if( aRow == REFERENCE )
203  {
204  m_referenceAttr->IncRef();
205  return m_referenceAttr;
206  }
207  else if( aRow == VALUE )
208  {
209  // For power symbols, the value is not editable, because value and pin name must
210  // be the same and can be edited only in library editor.
212  {
213  m_readOnlyAttr->IncRef();
214  return m_readOnlyAttr;
215  }
216  else
217  {
218  m_valueAttr->IncRef();
219  return m_valueAttr;
220  }
221  }
222  else if( aRow == FOOTPRINT )
223  {
224  m_footprintAttr->IncRef();
225  return m_footprintAttr;
226  }
227  else if( aRow == DATASHEET )
228  {
229  m_urlAttr->IncRef();
230  return m_urlAttr;
231  }
232  else
233  {
234  wxString fieldname = GetValue( aRow, FDC_NAME );
235  const TEMPLATE_FIELDNAME* templateFn = m_frame->GetTemplateFieldName( fieldname );
236 
237  if( templateFn && templateFn->m_URL )
238  {
239  m_urlAttr->IncRef();
240  return m_urlAttr;
241  }
242  }
243  return nullptr;
244 
245  case FDC_TEXT_SIZE:
246  case FDC_POSX:
247  case FDC_POSY:
248  return nullptr;
249 
250  case FDC_H_ALIGN:
251  m_hAlignAttr->IncRef();
252  return m_hAlignAttr;
253 
254  case FDC_V_ALIGN:
255  m_vAlignAttr->IncRef();
256  return m_vAlignAttr;
257 
258  case FDC_ORIENTATION:
259  m_orientationAttr->IncRef();
260  return m_orientationAttr;
261 
262  case FDC_SHOWN:
263  case FDC_ITALIC:
264  case FDC_BOLD:
265  m_boolAttr->IncRef();
266  return m_boolAttr;
267 
268  default:
269  wxFAIL;
270  return nullptr;
271  }
272 }
273 
274 
275 template <class T>
276 wxString FIELDS_GRID_TABLE<T>::GetValue( int aRow, int aCol )
277 {
278  wxCHECK( aRow < GetNumberRows(), wxEmptyString );
279  const T& field = this->at( (size_t) aRow );
280 
281  switch( aCol )
282  {
283  case FDC_NAME:
284  // Use default field name for mandatory fields, because they are transalted
285  // according to the current locale
286  if( aRow < MANDATORY_FIELDS )
288  else
289  return field.GetName( false );
290 
291  case FDC_VALUE:
292  return field.GetText();
293 
294  case FDC_H_ALIGN:
295  switch ( field.GetHorizJustify() )
296  {
298  return _( "Left" );
300  return _( "Center" );
302  return _( "Right" );
303  }
304 
305  break;
306 
307  case FDC_V_ALIGN:
308  switch ( field.GetVertJustify() )
309  {
311  return _( "Top" );
313  return _( "Center" );
315  return _( "Bottom" );
316  }
317 
318  break;
319 
320  case FDC_TEXT_SIZE:
321  return StringFromValue( m_userUnits, field.GetTextSize().GetHeight(), true, true );
322 
323  case FDC_ORIENTATION:
324  switch ( (int) field.GetTextAngle() )
325  {
326  case TEXT_ANGLE_HORIZ:
327  return _( "Horizontal" );
328  case TEXT_ANGLE_VERT:
329  return _( "Vertical" );
330  }
331 
332  break;
333 
334  case FDC_POSX:
335  return StringFromValue( m_userUnits, field.GetTextPos().x, true );
336 
337  case FDC_POSY:
338  return StringFromValue( m_userUnits, field.GetTextPos().y, true );
339 
340  default:
341  // we can't assert here because wxWidgets sometimes calls this without checking
342  // the column type when trying to see if there's an overflow
343  break;
344  }
345 
346  return wxT( "bad wxWidgets!" );
347 }
348 
349 
350 template <class T>
351 bool FIELDS_GRID_TABLE<T>::GetValueAsBool( int aRow, int aCol )
352 {
353  wxCHECK( aRow < GetNumberRows(), false );
354  const T& field = this->at( (size_t) aRow );
355 
356  switch( aCol )
357  {
358  case FDC_SHOWN: return field.IsVisible();
359  case FDC_ITALIC: return field.IsItalic();
360  case FDC_BOLD: return field.IsBold();
361  default:
362  wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a bool value" ), aCol ) );
363  return false;
364  }
365 }
366 
367 
368 template <class T>
369 void FIELDS_GRID_TABLE<T>::SetValue( int aRow, int aCol, const wxString &aValue )
370 {
371  wxCHECK( aRow < GetNumberRows(), /*void*/ );
372  T& field = this->at( (size_t) aRow );
373  wxPoint pos;
374 
375  switch( aCol )
376  {
377  case FDC_NAME:
378  field.SetName( aValue );
379  break;
380 
381  case FDC_VALUE:
382  field.SetText( aValue );
383  break;
384 
385  case FDC_H_ALIGN:
386  if( aValue == _( "Left" ) )
387  field.SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
388  else if( aValue == _( "Center" ) )
389  field.SetHorizJustify( GR_TEXT_HJUSTIFY_CENTER );
390  else if( aValue == _( "Right" ) )
391  field.SetHorizJustify( GR_TEXT_HJUSTIFY_RIGHT );
392  else
393  wxFAIL_MSG( wxT( "unknown horizontal alignment: " ) + aValue );
394  break;
395 
396  case FDC_V_ALIGN:
397  if( aValue == _( "Top" ) )
398  field.SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
399  else if( aValue == _( "Center" ) )
400  field.SetVertJustify( GR_TEXT_VJUSTIFY_CENTER );
401  else if( aValue == _( "Bottom" ) )
402  field.SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM );
403  else
404  wxFAIL_MSG( wxT( "unknown vertical alignment: " ) + aValue);
405  break;
406 
407  case FDC_TEXT_SIZE:
408  field.SetTextSize( wxSize( ValueFromString( m_userUnits, aValue ),
409  ValueFromString( m_userUnits, aValue ) ) );
410  break;
411 
412  case FDC_ORIENTATION:
413  if( aValue == _( "Horizontal" ) )
414  field.SetTextAngle( TEXT_ANGLE_HORIZ );
415  else if( aValue == _( "Vertical" ) )
416  field.SetTextAngle( TEXT_ANGLE_VERT );
417  else
418  wxFAIL_MSG( wxT( "unknown orientation: " ) + aValue );
419 
420  case FDC_POSX:
421  case FDC_POSY:
422  pos = field.GetTextPos();
423  if( aCol == FDC_POSX )
424  pos.x = ValueFromString( m_userUnits, aValue );
425  else
426  pos.y = ValueFromString( m_userUnits, aValue );
427  field.SetTextPos( pos );
428  break;
429 
430  default:
431  wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a string value" ), aCol ) );
432  break;
433  }
434 
435  GetView()->Refresh();
436 }
437 
438 
439 template <class T>
440 void FIELDS_GRID_TABLE<T>::SetValueAsBool( int aRow, int aCol, bool aValue )
441 {
442  wxCHECK( aRow < GetNumberRows(), /*void*/ );
443  T& field = this->at( (size_t) aRow );
444 
445  switch( aCol )
446  {
447  case FDC_SHOWN:
448  field.SetVisible( aValue );
449  break;
450  case FDC_ITALIC:
451  field.SetItalic( aValue );
452  break;
453  case FDC_BOLD:
454  field.SetBold( aValue );
455  break;
456  default:
457  wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a bool value" ), aCol ) );
458  break;
459  }
460 }
461 
462 
463 // Explicit Instantiations
464 
465 template class FIELDS_GRID_TABLE<SCH_FIELD>;
466 template class FIELDS_GRID_TABLE<LIB_FIELD>;
467 
468 
469 
471 {
472  if( m_grid->GetGridCursorRow() == FOOTPRINT && m_grid->GetGridCursorCol() == FDC_VALUE )
473  {
474  menu.Append( MYID_SELECT_FOOTPRINT, _( "Select Footprint..." ), _( "Browse for footprint" ) );
475  menu.AppendSeparator();
476  }
477  else if( m_grid->GetGridCursorRow() == DATASHEET && m_grid->GetGridCursorCol() == FDC_VALUE )
478  {
479  menu.Append( MYID_SHOW_DATASHEET, _( "Show Datasheet" ), _( "Show datasheet in browser" ) );
480  menu.AppendSeparator();
481  }
482 
484 }
485 
486 
487 void FIELDS_GRID_TRICKS::doPopupSelection( wxCommandEvent& event )
488 {
489  if( event.GetId() == MYID_SELECT_FOOTPRINT )
490  {
491  // pick a footprint using the footprint picker.
492  wxString fpid = m_grid->GetCellValue( FOOTPRINT, FDC_VALUE );
493  KIWAY_PLAYER* frame = m_dlg->Kiway().Player( FRAME_PCB_MODULE_VIEWER_MODAL, true, m_dlg );
494 
495  if( frame->ShowModal( &fpid, m_dlg ) )
496  m_grid->SetCellValue( FOOTPRINT, FDC_VALUE, fpid );
497 
498  frame->Destroy();
499  }
500  else if (event.GetId() == MYID_SHOW_DATASHEET )
501  {
502  wxString datasheet_uri = m_grid->GetCellValue( DATASHEET, FDC_VALUE );
503  datasheet_uri = ResolveUriByEnvVars( datasheet_uri );
504  GetAssociatedDocument( m_dlg, datasheet_uri );
505  }
506  else
507  {
509  }
510 }
#define TEXT_ANGLE_HORIZ
virtual void showPopupMenu(wxMenu &menu) override
Class KIWAY_PLAYER is a wxFrame capable of the OpenProjectFiles function, meaning it can load a porti...
Definition: kiway_player.h:120
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_player.h:60
name of datasheet
const wxString ResolveUriByEnvVars(const wxString &aUri)
Replace any environment variables in file-path uris (leaving network-path URIs alone).
Definition: common.cpp:456
bool IsPower() const
int GetNumberRows() override
#define TEXT_ANGLE_VERT
bool CanSetValueAs(int aRow, int aCol, const wxString &aTypeName) override
This file is part of the common library.
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors...
wxGridCellAttr * m_referenceAttr
bool m_URL
If field should have a browse button.
bool GetAssociatedDocument(wxWindow *aParent, const wxString &aDocName, const wxPathList *aPaths)
Function GetAssociatedDocument open a document (file) with the suitable browser.
Definition: eda_doc.cpp:87
SCH_BASE_FRAME * m_frame
static const wxString GetDefaultFieldName(int aFieldNdx)
Function GetDefaultFieldName returns a default symbol field name for field aFieldNdx for all componen...
Class DIALOG_SHIM may sit in the inheritance tree between wxDialog and any class written by wxFormBui...
Definition: dialog_shim.h:53
int ValueFromString(EDA_UNITS_T aUnits, const wxString &aTextValue, bool aUseMils)
Function ValueFromString converts aTextValue in aUnits to internal units used by the application...
Definition: base_units.cpp:409
wxString GetColLabelValue(int aCol) override
Field Name Module PCB, i.e. "16DIP300".
Field Reference of part, i.e. "IC21".
Class GRID_CELL_TEXT_EDITOR.
Definition: validators.h:42
wxGridCellAttr * m_readOnlyAttr
wxGridCellAttr * m_hAlignAttr
VTBL_ENTRY KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=NULL)
Function Player returns the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:300
SCH_FIELD_VALIDATOR m_referenceValidator
Defintions of control validators for schematic dialogs.
wxString GetValue(int aRow, int aCol) override
SCH_FIELD_VALIDATOR m_fieldNameValidator
bool CanGetValueAs(int aRow, int aCol, const wxString &aTypeName) override
wxGridCellAttr * m_boolAttr
Define a library symbol object.
#define FIELD_NAME
wxGridCellAttr * GetAttr(int row, int col, wxGridCellAttr::wxAttrKind kind) override
const TEMPLATE_FIELDNAME * GetTemplateFieldName(const wxString &aName) const
Search for aName in the the template field name list.
virtual void SetValidator(const wxValidator &validator) override
Definition: validators.cpp:44
wxGridCellAttr * m_fieldNameAttr
wxGridCellAttr * m_urlAttr
virtual void doPopupSelection(wxCommandEvent &event)
SCH_FIELD_VALIDATOR m_valueValidator
bool GetValueAsBool(int aRow, int aCol) override
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
wxGridCellAttr * m_vAlignAttr
virtual void showPopupMenu(wxMenu &menu)
void SetValue(int aRow, int aCol, const wxString &aValue) override
wxGridCellAttr * m_orientationAttr
wxGridCellAttr * m_valueAttr
EDA_UNITS_T m_userUnits
Struct TEMPLATE_FIELDNAME holds a name of a component&#39;s field, field value, and default visibility...
bool Destroy() override
Our version of Destroy() which is virtual from wxWidgets.
wxString StringFromValue(EDA_UNITS_T aUnits, int aValue, bool aAddUnitSymbol, bool aUseMils)
Function StringFromValue returns the string from aValue according to units (inch, mm ...
Definition: base_units.cpp:210
bool IsType(FRAME_T aType) const
Definition for part library class.
Definition of the SCH_FIELD class for Eeschema.
FIELDS_GRID_TABLE(DIALOG_SHIM *aDialog, SCH_BASE_FRAME *aFrame, LIB_PART *aPart)
void SetValueAsBool(int aRow, int aCol, bool aValue) override
#define VALUE
A shim class between EDA_DRAW_FRAME and several derived classes: LIB_EDIT_FRAME, LIB_VIEW_FRAME, and SCH_EDIT_FRAME, and it brings in a common way of handling the provided virtual functions for the derived classes.
wxGridCellAttr * m_footprintAttr
virtual void doPopupSelection(wxCommandEvent &event) override
VTBL_ENTRY bool ShowModal(wxString *aResult=NULL, wxWindow *aResultantFocusWindow=NULL)
Function ShowModal puts up this wxFrame as if it were a modal dialog, with all other instantiated wxF...
Custom text control validator definitions.