KiCad PCB EDA Suite
grid_text_button_helpers.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-2019 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 <wx/combo.h>
25 #include <bitmap_types.h>
26 #include <bitmaps.h>
27 #include <kiway.h>
28 #include <kiway_player.h>
29 #include <dialog_shim.h>
30 
32 #include <eda_doc.h>
33 
34 
35 //-------- Renderer ---------------------------------------------------------------------
36 // None required; just render as normal text.
37 
38 
39 
40 //-------- Editor Base Class ------------------------------------------------------------
41 //
42 // Note: this implementation is an adaptation of wxGridCellChoiceEditor
43 
44 
46 {
47  return Combo()->GetValue();
48 }
49 
50 
51 void GRID_CELL_TEXT_BUTTON::SetSize( const wxRect& aRect )
52 {
53  wxRect rect( aRect );
54  rect.Inflate( -1 );
55 
56 #if defined( __WXMAC__ )
57  rect.Inflate( 3 ); // no FOCUS_RING, even on Mac
58 #endif
59 
60  Combo()->SetSize( rect, wxSIZE_ALLOW_MINUS_ONE );
61 }
62 
63 
64 void GRID_CELL_TEXT_BUTTON::StartingKey( wxKeyEvent& event )
65 {
66  // Note: this is a copy of wxGridCellTextEditor's StartingKey()
67 
68  // Since this is now happening in the EVT_CHAR event EmulateKeyPress is no
69  // longer an appropriate way to get the character into the text control.
70  // Do it ourselves instead. We know that if we get this far that we have
71  // a valid character, so not a whole lot of testing needs to be done.
72 
73  wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( Combo() );
74  int ch;
75 
76  bool isPrintable;
77 
78 #if wxUSE_UNICODE
79  ch = event.GetUnicodeKey();
80 
81  if( ch != WXK_NONE )
82  isPrintable = true;
83  else
84 #endif // wxUSE_UNICODE
85  {
86  ch = event.GetKeyCode();
87  isPrintable = ch >= WXK_SPACE && ch < WXK_START;
88  }
89 
90  switch( ch )
91  {
92  case WXK_DELETE:
93  // Delete the initial character when starting to edit with DELETE.
94  textEntry->Remove( 0, 1 );
95  break;
96 
97  case WXK_BACK:
98  // Delete the last character when starting to edit with BACKSPACE.
99  {
100  const long pos = textEntry->GetLastPosition();
101  textEntry->Remove( pos - 1, pos );
102  }
103  break;
104 
105  default:
106  if( isPrintable )
107  textEntry->WriteText( static_cast<wxChar>( ch ) );
108  break;
109  }
110 }
111 
112 
113 void GRID_CELL_TEXT_BUTTON::BeginEdit( int aRow, int aCol, wxGrid* aGrid )
114 {
115  auto evtHandler = static_cast< wxGridCellEditorEvtHandler* >( m_control->GetEventHandler() );
116 
117  // Don't immediately end if we get a kill focus event within BeginEdit
118  evtHandler->SetInSetFocus( true );
119 
120  m_value = aGrid->GetTable()->GetValue( aRow, aCol );
121 
122  Combo()->SetValue( m_value );
123  Combo()->SetFocus();
124 }
125 
126 
127 bool GRID_CELL_TEXT_BUTTON::EndEdit( int, int, const wxGrid*, const wxString&, wxString *aNewVal )
128 {
129  const wxString value = Combo()->GetValue();
130 
131  if( value == m_value )
132  return false;
133 
134  m_value = value;
135 
136  if( aNewVal )
137  *aNewVal = value;
138 
139  return true;
140 }
141 
142 
143 void GRID_CELL_TEXT_BUTTON::ApplyEdit( int aRow, int aCol, wxGrid* aGrid )
144 {
145  aGrid->GetTable()->SetValue( aRow, aCol, m_value );
146 }
147 
148 
150 {
151  Combo()->SetValue( m_value );
152 }
153 
154 
155 #if wxUSE_VALIDATORS
156 void GRID_CELL_TEXT_BUTTON::SetValidator( const wxValidator& validator )
157 {
158  m_validator.reset( static_cast< wxValidator* >( validator.Clone() ) );
159 }
160 #endif
161 
162 
163 class TEXT_BUTTON_SYMBOL_CHOOSER : public wxComboCtrl
164 {
165 public:
166  TEXT_BUTTON_SYMBOL_CHOOSER( wxWindow* aParent, DIALOG_SHIM* aParentDlg,
167  const wxString& aPreselect ) :
168  wxComboCtrl( aParent ),
169  m_dlg( aParentDlg ),
170  m_preselect( aPreselect )
171  {
172  SetButtonBitmaps( KiBitmap( small_library_xpm ) );
173  }
174 
175 protected:
176  void DoSetPopupControl( wxComboPopup* popup ) override
177  {
178  m_popup = nullptr;
179  }
180 
181  void OnButtonClick() override
182  {
183  // pick a footprint using the footprint picker.
184  wxString compid = GetValue();
185 
186  if( compid.IsEmpty() )
187  compid = m_preselect;
188 
190 
191  if( frame->ShowModal( &compid, m_dlg ) )
192  SetValue( compid );
193 
194  frame->Destroy();
195  }
196 
198  wxString m_preselect;
199 };
200 
201 
202 void GRID_CELL_SYMBOL_ID_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
203  wxEvtHandler* aEventHandler )
204 {
205  m_control = new TEXT_BUTTON_SYMBOL_CHOOSER( aParent, m_dlg, m_preselect );
206 
207  wxGridCellEditor::Create( aParent, aId, aEventHandler );
208 }
209 
210 
211 class TEXT_BUTTON_FP_CHOOSER : public wxComboCtrl
212 {
213 public:
214  TEXT_BUTTON_FP_CHOOSER( wxWindow* aParent, DIALOG_SHIM* aParentDlg,
215  const wxString& aPreselect ) :
216  wxComboCtrl( aParent ),
217  m_dlg( aParentDlg ),
218  m_preselect( aPreselect )
219  {
220  SetButtonBitmaps( KiBitmap( small_library_xpm ) );
221  }
222 
223 protected:
224  void DoSetPopupControl( wxComboPopup* popup ) override
225  {
226  m_popup = nullptr;
227  }
228 
229  void OnButtonClick() override
230  {
231  // pick a footprint using the footprint picker.
232  wxString fpid = GetValue();
233 
234  if( fpid.IsEmpty() )
235  fpid = m_preselect;
236 
238 
239  if( frame->ShowModal( &fpid, m_dlg ) )
240  SetValue( fpid );
241 
242  frame->Destroy();
243  }
244 
246  wxString m_preselect;
247 };
248 
249 
250 void GRID_CELL_FOOTPRINT_ID_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
251  wxEvtHandler* aEventHandler )
252 {
253  m_control = new TEXT_BUTTON_FP_CHOOSER( aParent, m_dlg, m_preselect );
254 
255 #if wxUSE_VALIDATORS
256  // validate text in textctrl, if validator is set
257  if ( m_validator )
258  {
259  Combo()->SetValidator( *m_validator );
260  }
261 #endif
262 
263  wxGridCellEditor::Create( aParent, aId, aEventHandler );
264 }
265 
266 
267 class TEXT_BUTTON_URL : public wxComboCtrl
268 {
269 public:
270  TEXT_BUTTON_URL( wxWindow* aParent, DIALOG_SHIM* aParentDlg ) :
271  wxComboCtrl( aParent ),
272  m_dlg( aParentDlg )
273  {
274  SetButtonBitmaps( KiBitmap( www_xpm ) );
275  }
276 
277 protected:
278  void DoSetPopupControl( wxComboPopup* popup ) override
279  {
280  m_popup = nullptr;
281  }
282 
283  void OnButtonClick() override
284  {
285  wxString filename = GetValue();
286 
287  if( !filename.IsEmpty() && filename != wxT( "~" ) )
288  GetAssociatedDocument( m_dlg, GetValue() );
289  }
290 
292 };
293 
294 
295 void GRID_CELL_URL_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
296  wxEvtHandler* aEventHandler )
297 {
298  m_control = new TEXT_BUTTON_URL( aParent, m_dlg );
299 
300 #if wxUSE_VALIDATORS
301  // validate text in textctrl, if validator is set
302  if ( m_validator )
303  {
304  Combo()->SetValidator( *m_validator );
305  }
306 #endif
307 
308  wxGridCellEditor::Create( aParent, aId, aEventHandler );
309 }
310 
311 
312 class TEXT_BUTTON_FILE_BROWSER : public wxComboCtrl
313 {
314 public:
315  TEXT_BUTTON_FILE_BROWSER( wxWindow* aParent, DIALOG_SHIM* aParentDlg,
316  wxString* aCurrentDir, wxString* aExt = nullptr ) :
317  wxComboCtrl( aParent ),
318  m_dlg( aParentDlg ),
319  m_currentDir( aCurrentDir ),
320  m_ext( aExt )
321  {
322  SetButtonBitmaps( KiBitmap( folder_xpm ) );
323  }
324 
325 protected:
326  void DoSetPopupControl( wxComboPopup* popup ) override
327  {
328  m_popup = nullptr;
329  }
330 
331  void OnButtonClick() override
332  {
333  wxString path = GetValue();
334 
335  if( path.IsEmpty() )
336  path = *m_currentDir;
337  else
338  path = ExpandEnvVarSubstitutions( path );
339 
340  if( m_ext )
341  {
342  wxFileDialog dlg( nullptr, _( "Select a File" ), path, wxEmptyString, *m_ext,
343  wxFD_FILE_MUST_EXIST | wxFD_OPEN );
344 
345  if( dlg.ShowModal() == wxID_OK )
346  {
347  SetValue( dlg.GetPath() );
348  *m_currentDir = dlg.GetPath();
349  }
350  }
351  else
352  {
353  wxDirDialog dlg( nullptr, _( "Select Path" ), path,
354  wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST );
355 
356  if( dlg.ShowModal() == wxID_OK )
357  {
358  SetValue( dlg.GetPath() );
359  *m_currentDir = dlg.GetPath();
360  }
361  }
362  }
363 
365  wxString* m_currentDir;
366  wxString* m_ext;
367 };
368 
369 
370 void GRID_CELL_PATH_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
371  wxEvtHandler* aEventHandler )
372 {
373  m_control = new TEXT_BUTTON_FILE_BROWSER( aParent, m_dlg, m_currentDir );
374 
375 #if wxUSE_VALIDATORS
376  // validate text in textctrl, if validator is set
377  if ( m_validator )
378  {
379  Combo()->SetValidator( *m_validator );
380  }
381 #endif
382 
383  wxGridCellEditor::Create( aParent, aId, aEventHandler );
384 }
385 
386 
387 void GRID_CELL_SYMLIB_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
388  wxEvtHandler* aEventHandler )
389 {
390  m_control = new TEXT_BUTTON_FILE_BROWSER( aParent, m_dlg, m_currentDir, &m_ext );
391 
392 #if wxUSE_VALIDATORS
393  // validate text in textctrl, if validator is set
394  if ( m_validator )
395  {
396  Combo()->SetValidator( *m_validator );
397  }
398 #endif
399 
400  wxGridCellEditor::Create( aParent, aId, aEventHandler );
401 }
402 
403 
TEXT_BUTTON_FILE_BROWSER(wxWindow *aParent, DIALOG_SHIM *aParentDlg, wxString *aCurrentDir, wxString *aExt=nullptr)
Class KIWAY_PLAYER is a wxFrame capable of the OpenProjectFiles function, meaning it can load a porti...
Definition: kiway_player.h:127
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_player.h:61
void StartingKey(wxKeyEvent &event) override
This file is part of the common library.
void Create(wxWindow *aParent, wxWindowID aId, wxEvtHandler *aEventHandler) override
void Create(wxWindow *aParent, wxWindowID aId, wxEvtHandler *aEventHandler) override
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
Class DIALOG_SHIM may sit in the inheritance tree between wxDialog and any class written by wxFormBui...
Definition: dialog_shim.h:83
TEXT_BUTTON_URL(wxWindow *aParent, DIALOG_SHIM *aParentDlg)
void DoSetPopupControl(wxComboPopup *popup) override
void SetSize(const wxRect &aRect) override
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Construct a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:79
void BeginEdit(int aRow, int aCol, wxGrid *aGrid) override
TEXT_BUTTON_FP_CHOOSER(wxWindow *aParent, DIALOG_SHIM *aParentDlg, const wxString &aPreselect)
const wxString ExpandEnvVarSubstitutions(const wxString &aString)
Replace any environment variable references with their values.
Definition: common.cpp:458
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:321
TEXT_BUTTON_SYMBOL_CHOOSER(wxWindow *aParent, DIALOG_SHIM *aParentDlg, const wxString &aPreselect)
wxComboCtrl * Combo() const
void DoSetPopupControl(wxComboPopup *popup) override
void Create(wxWindow *aParent, wxWindowID aId, wxEvtHandler *aEventHandler) override
void DoSetPopupControl(wxComboPopup *popup) override
wxString GetValue() const override
void Create(wxWindow *aParent, wxWindowID aId, wxEvtHandler *aEventHandler) override
void ApplyEdit(int aRow, int aCol, wxGrid *aGrid) override
void DoSetPopupControl(wxComboPopup *popup) override
bool Destroy() override
Our version of Destroy() which is virtual from wxWidgets.
void Create(wxWindow *aParent, wxWindowID aId, wxEvtHandler *aEventHandler) override
bool EndEdit(int, int, const wxGrid *, const wxString &, wxString *aNewVal) 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...