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  // wxComboCtrl inherits from wxTextEntry, so can staticly cast
74  wxTextEntry* textEntry = static_cast<wxTextEntry*>( Combo() );
75  int ch;
76 
77  bool isPrintable;
78 
79 #if wxUSE_UNICODE
80  ch = event.GetUnicodeKey();
81 
82  if( ch != WXK_NONE )
83  isPrintable = true;
84  else
85 #endif // wxUSE_UNICODE
86  {
87  ch = event.GetKeyCode();
88  isPrintable = ch >= WXK_SPACE && ch < WXK_START;
89  }
90 
91  switch( ch )
92  {
93  case WXK_DELETE:
94  // Delete the initial character when starting to edit with DELETE.
95  textEntry->Remove( 0, 1 );
96  break;
97 
98  case WXK_BACK:
99  // Delete the last character when starting to edit with BACKSPACE.
100  {
101  const long pos = textEntry->GetLastPosition();
102  textEntry->Remove( pos - 1, pos );
103  }
104  break;
105 
106  default:
107  if( isPrintable )
108  textEntry->WriteText( static_cast<wxChar>( ch ) );
109  break;
110  }
111 }
112 
113 
114 void GRID_CELL_TEXT_BUTTON::BeginEdit( int aRow, int aCol, wxGrid* aGrid )
115 {
116  auto evtHandler = static_cast< wxGridCellEditorEvtHandler* >( m_control->GetEventHandler() );
117 
118  // Don't immediately end if we get a kill focus event within BeginEdit
119  evtHandler->SetInSetFocus( true );
120 
121  m_value = aGrid->GetTable()->GetValue( aRow, aCol );
122 
123  Combo()->SetValue( m_value );
124  Combo()->SetFocus();
125 }
126 
127 
128 bool GRID_CELL_TEXT_BUTTON::EndEdit( int, int, const wxGrid*, const wxString&, wxString *aNewVal )
129 {
130  const wxString value = Combo()->GetValue();
131 
132  if( value == m_value )
133  return false;
134 
135  m_value = value;
136 
137  if( aNewVal )
138  *aNewVal = value;
139 
140  return true;
141 }
142 
143 
144 void GRID_CELL_TEXT_BUTTON::ApplyEdit( int aRow, int aCol, wxGrid* aGrid )
145 {
146  aGrid->GetTable()->SetValue( aRow, aCol, m_value );
147 }
148 
149 
151 {
152  Combo()->SetValue( m_value );
153 }
154 
155 
156 #if wxUSE_VALIDATORS
157 void GRID_CELL_TEXT_BUTTON::SetValidator( const wxValidator& validator )
158 {
159  m_validator.reset( static_cast< wxValidator* >( validator.Clone() ) );
160 }
161 #endif
162 
163 
164 class TEXT_BUTTON_SYMBOL_CHOOSER : public wxComboCtrl
165 {
166 public:
167  TEXT_BUTTON_SYMBOL_CHOOSER( wxWindow* aParent, DIALOG_SHIM* aParentDlg,
168  const wxString& aPreselect ) :
169  wxComboCtrl( aParent ),
170  m_dlg( aParentDlg ),
171  m_preselect( aPreselect )
172  {
173  SetButtonBitmaps( KiBitmap( small_library_xpm ) );
174  }
175 
176 protected:
177  void DoSetPopupControl( wxComboPopup* popup ) override
178  {
179  m_popup = nullptr;
180  }
181 
182  void OnButtonClick() override
183  {
184  // pick a footprint using the footprint picker.
185  wxString compid = GetValue();
186 
187  if( compid.IsEmpty() )
188  compid = m_preselect;
189 
191 
192  if( frame->ShowModal( &compid, m_dlg ) )
193  SetValue( compid );
194 
195  frame->Destroy();
196  }
197 
199  wxString m_preselect;
200 };
201 
202 
203 void GRID_CELL_SYMBOL_ID_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
204  wxEvtHandler* aEventHandler )
205 {
206  m_control = new TEXT_BUTTON_SYMBOL_CHOOSER( aParent, m_dlg, m_preselect );
207 
208  wxGridCellEditor::Create( aParent, aId, aEventHandler );
209 }
210 
211 
212 class TEXT_BUTTON_FP_CHOOSER : public wxComboCtrl
213 {
214 public:
215  TEXT_BUTTON_FP_CHOOSER( wxWindow* aParent, DIALOG_SHIM* aParentDlg,
216  const wxString& aPreselect ) :
217  wxComboCtrl( aParent ),
218  m_dlg( aParentDlg ),
219  m_preselect( aPreselect )
220  {
221  SetButtonBitmaps( KiBitmap( small_library_xpm ) );
222  }
223 
224 protected:
225  void DoSetPopupControl( wxComboPopup* popup ) override
226  {
227  m_popup = nullptr;
228  }
229 
230  void OnButtonClick() override
231  {
232  // pick a footprint using the footprint picker.
233  wxString fpid = GetValue();
234 
235  if( fpid.IsEmpty() )
236  fpid = m_preselect;
237 
239 
240  if( frame->ShowModal( &fpid, m_dlg ) )
241  SetValue( fpid );
242 
243  frame->Destroy();
244  }
245 
247  wxString m_preselect;
248 };
249 
250 
251 void GRID_CELL_FOOTPRINT_ID_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
252  wxEvtHandler* aEventHandler )
253 {
254  m_control = new TEXT_BUTTON_FP_CHOOSER( aParent, m_dlg, m_preselect );
255 
256 #if wxUSE_VALIDATORS
257  // validate text in textctrl, if validator is set
258  if ( m_validator )
259  {
260  Combo()->SetValidator( *m_validator );
261  }
262 #endif
263 
264  wxGridCellEditor::Create( aParent, aId, aEventHandler );
265 }
266 
267 
268 class TEXT_BUTTON_URL : public wxComboCtrl
269 {
270 public:
271  TEXT_BUTTON_URL( wxWindow* aParent, DIALOG_SHIM* aParentDlg ) :
272  wxComboCtrl( aParent ),
273  m_dlg( aParentDlg )
274  {
275  SetButtonBitmaps( KiBitmap( www_xpm ) );
276  }
277 
278 protected:
279  void DoSetPopupControl( wxComboPopup* popup ) override
280  {
281  m_popup = nullptr;
282  }
283 
284  void OnButtonClick() override
285  {
286  wxString filename = GetValue();
287 
288  if( !filename.IsEmpty() && filename != wxT( "~" ) )
289  GetAssociatedDocument( m_dlg, GetValue() );
290  }
291 
293 };
294 
295 
296 void GRID_CELL_URL_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
297  wxEvtHandler* aEventHandler )
298 {
299  m_control = new TEXT_BUTTON_URL( aParent, m_dlg );
300 
301 #if wxUSE_VALIDATORS
302  // validate text in textctrl, if validator is set
303  if ( m_validator )
304  {
305  Combo()->SetValidator( *m_validator );
306  }
307 #endif
308 
309  wxGridCellEditor::Create( aParent, aId, aEventHandler );
310 }
311 
312 
313 class TEXT_BUTTON_FILE_BROWSER : public wxComboCtrl
314 {
315 public:
316  TEXT_BUTTON_FILE_BROWSER( wxWindow* aParent, DIALOG_SHIM* aParentDlg,
317  wxString* aCurrentDir, wxString* aExt = nullptr ) :
318  wxComboCtrl( aParent ),
319  m_dlg( aParentDlg ),
320  m_currentDir( aCurrentDir ),
321  m_ext( aExt )
322  {
323  SetButtonBitmaps( KiBitmap( folder_xpm ) );
324  }
325 
326 protected:
327  void DoSetPopupControl( wxComboPopup* popup ) override
328  {
329  m_popup = nullptr;
330  }
331 
332  void OnButtonClick() override
333  {
334  wxString path = GetValue();
335 
336  if( path.IsEmpty() )
337  path = *m_currentDir;
338  else
339  path = ExpandEnvVarSubstitutions( path );
340 
341  if( m_ext )
342  {
343  wxFileDialog dlg( nullptr, _( "Select a File" ), path, wxEmptyString, *m_ext,
344  wxFD_FILE_MUST_EXIST | wxFD_OPEN );
345 
346  if( dlg.ShowModal() == wxID_OK )
347  {
348  SetValue( dlg.GetPath() );
349  *m_currentDir = dlg.GetPath();
350  }
351  }
352  else
353  {
354  wxDirDialog dlg( nullptr, _( "Select Path" ), path,
355  wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST );
356 
357  if( dlg.ShowModal() == wxID_OK )
358  {
359  SetValue( dlg.GetPath() );
360  *m_currentDir = dlg.GetPath();
361  }
362  }
363  }
364 
366  wxString* m_currentDir;
367  wxString* m_ext;
368 };
369 
370 
371 void GRID_CELL_PATH_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
372  wxEvtHandler* aEventHandler )
373 {
374  if( m_ext.IsEmpty() )
375  m_control = new TEXT_BUTTON_FILE_BROWSER( aParent, m_dlg, m_currentDir );
376  else
377  m_control = new TEXT_BUTTON_FILE_BROWSER( aParent, m_dlg, m_currentDir, &m_ext );
378 
379 #if wxUSE_VALIDATORS
380  // validate text in textctrl, if validator is set
381  if ( m_validator )
382  {
383  Combo()->SetValidator( *m_validator );
384  }
385 #endif
386 
387  wxGridCellEditor::Create( aParent, aId, aEventHandler );
388 }
389 
390 
391 void GRID_CELL_SYMLIB_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
392  wxEvtHandler* aEventHandler )
393 {
394  m_control = new TEXT_BUTTON_FILE_BROWSER( aParent, m_dlg, m_currentDir, &m_ext );
395 
396 #if wxUSE_VALIDATORS
397  // validate text in textctrl, if validator is set
398  if ( m_validator )
399  {
400  Combo()->SetValidator( *m_validator );
401  }
402 #endif
403 
404  wxGridCellEditor::Create( aParent, aId, aEventHandler );
405 }
406 
407 
TEXT_BUTTON_FILE_BROWSER(wxWindow *aParent, DIALOG_SHIM *aParentDlg, wxString *aCurrentDir, wxString *aExt=nullptr)
const BITMAP_OPAQUE folder_xpm[1]
Definition: folder.cpp:20
KIWAY_PLAYER is a wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of ...
Definition: kiway_player.h:59
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_holder.h:56
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:80
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition: dialog_shim.h:84
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:80
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:525
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:341
TEXT_BUTTON_SYMBOL_CHOOSER(wxWindow *aParent, DIALOG_SHIM *aParentDlg, const wxString &aPreselect)
wxComboCtrl * Combo() const
void DoSetPopupControl(wxComboPopup *popup) override
const BITMAP_OPAQUE small_library_xpm[1]
void Create(wxWindow *aParent, wxWindowID aId, wxEvtHandler *aEventHandler) override
void DoSetPopupControl(wxComboPopup *popup) override
const BITMAP_OPAQUE www_xpm[1]
Definition: www.cpp:30
wxString GetValue() const override
void Create(wxWindow *aParent, wxWindowID aId, wxEvtHandler *aEventHandler) override
#define _(s)
Definition: 3d_actions.cpp:33
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
virtual 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...