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 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 void GRID_CELL_TEXT_BUTTON::SetSize( const wxRect& aRect )
51 {
52  wxRect rect( aRect );
53  rect.Inflate( -1 );
54 
55 #if defined( __WXMAC__ )
56  rect.Inflate( 3 ); // no FOCUS_RING, even on Mac
57 #endif
58 
59  Combo()->SetSize( rect, wxSIZE_ALLOW_MINUS_ONE );
60 }
61 
62 
63 void GRID_CELL_TEXT_BUTTON::StartingKey( wxKeyEvent& event )
64 {
65  // Note: this is a copy of wxGridCellTextEditor's StartingKey()
66 
67  // Since this is now happening in the EVT_CHAR event EmulateKeyPress is no
68  // longer an appropriate way to get the character into the text control.
69  // Do it ourselves instead. We know that if we get this far that we have
70  // a valid character, so not a whole lot of testing needs to be done.
71 
72  wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( Combo() );
73  int ch;
74 
75  bool isPrintable;
76 
77 #if wxUSE_UNICODE
78  ch = event.GetUnicodeKey();
79  if ( ch != WXK_NONE )
80  isPrintable = true;
81  else
82 #endif // wxUSE_UNICODE
83  {
84  ch = event.GetKeyCode();
85  isPrintable = ch >= WXK_SPACE && ch < WXK_START;
86  }
87 
88  switch (ch)
89  {
90  case WXK_DELETE:
91  // Delete the initial character when starting to edit with DELETE.
92  textEntry->Remove(0, 1);
93  break;
94 
95  case WXK_BACK:
96  // Delete the last character when starting to edit with BACKSPACE.
97  {
98  const long pos = textEntry->GetLastPosition();
99  textEntry->Remove(pos - 1, pos);
100  }
101  break;
102 
103  default:
104  if ( isPrintable )
105  textEntry->WriteText(static_cast<wxChar>(ch));
106  break;
107  }
108 }
109 
110 
111 void GRID_CELL_TEXT_BUTTON::BeginEdit( int aRow, int aCol, wxGrid* aGrid )
112 {
113  auto evtHandler = static_cast<wxGridCellEditorEvtHandler*>( m_control->GetEventHandler() );
114 
115  // Don't immediately end if we get a kill focus event within BeginEdit
116  evtHandler->SetInSetFocus( true );
117 
118  m_value = aGrid->GetTable()->GetValue( aRow, aCol );
119 
120  Combo()->SetValue( m_value );
121  Combo()->SetFocus();
122 }
123 
124 
125 bool GRID_CELL_TEXT_BUTTON::EndEdit( int , int , const wxGrid* , const wxString& , wxString *aNewVal )
126 {
127  const wxString value = Combo()->GetValue();
128 
129  if( value == m_value )
130  return false;
131 
132  m_value = value;
133 
134  if( aNewVal )
135  *aNewVal = value;
136 
137  return true;
138 }
139 
140 
141 void GRID_CELL_TEXT_BUTTON::ApplyEdit( int aRow, int aCol, wxGrid* aGrid )
142 {
143  aGrid->GetTable()->SetValue( aRow, aCol, m_value );
144 }
145 
146 
148 {
149  Combo()->SetValue( m_value );
150 }
151 
152 
157 class TEXT_BUTTON_SYMBOL_CHOOSER : public wxComboCtrl
158 {
159 public:
160  TEXT_BUTTON_SYMBOL_CHOOSER( wxWindow* aParent, DIALOG_SHIM* aParentDlg,
161  const wxString& aPreselect ) :
162  wxComboCtrl( aParent ),
163  m_dlg( aParentDlg ),
164  m_preselect( aPreselect )
165  {
166  SetButtonBitmaps( KiBitmap( small_library_xpm ) );
167  }
168 
169 protected:
170  void DoSetPopupControl( wxComboPopup* popup ) override
171  {
172  m_popup = nullptr;
173  }
174 
175  void OnButtonClick() override
176  {
177  // pick a footprint using the footprint picker.
178  wxString compid = GetValue();
179 
180  if( compid.IsEmpty() )
181  compid = m_preselect;
182 
184 
185  if( frame->ShowModal( &compid, m_dlg ) )
186  SetValue( compid );
187 
188  frame->Destroy();
189  }
190 
192  wxString m_preselect;
193 };
194 
195 
196 void GRID_CELL_SYMBOL_ID_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
197  wxEvtHandler* aEventHandler )
198 {
199  m_control = new TEXT_BUTTON_SYMBOL_CHOOSER( aParent, m_dlg, m_preselect );
200 
201  wxGridCellEditor::Create(aParent, aId, aEventHandler);
202 }
203 
204 
209 class TEXT_BUTTON_FP_CHOOSER : public wxComboCtrl
210 {
211 public:
212  TEXT_BUTTON_FP_CHOOSER( wxWindow* aParent, DIALOG_SHIM* aParentDlg,
213  const wxString& aPreselect ) :
214  wxComboCtrl( aParent ),
215  m_dlg( aParentDlg ),
216  m_preselect( aPreselect )
217  {
218  SetButtonBitmaps( KiBitmap( small_library_xpm ) );
219  }
220 
221 protected:
222  void DoSetPopupControl( wxComboPopup* popup ) override
223  {
224  m_popup = nullptr;
225  }
226 
227  void OnButtonClick() override
228  {
229  // pick a footprint using the footprint picker.
230  wxString fpid = GetValue();
231 
232  if( fpid.IsEmpty() )
233  fpid = m_preselect;
234 
236 
237  if( frame->ShowModal( &fpid, m_dlg ) )
238  SetValue( fpid );
239 
240  frame->Destroy();
241  }
242 
244  wxString m_preselect;
245 };
246 
247 
248 void GRID_CELL_FOOTPRINT_ID_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
249  wxEvtHandler* aEventHandler )
250 {
251  m_control = new TEXT_BUTTON_FP_CHOOSER( aParent, m_dlg, m_preselect );
252 
253  wxGridCellEditor::Create(aParent, aId, aEventHandler);
254 }
255 
256 
261 class TEXT_BUTTON_URL : public wxComboCtrl
262 {
263 public:
264  TEXT_BUTTON_URL( wxWindow* aParent, DIALOG_SHIM* aParentDlg ) :
265  wxComboCtrl( aParent ),
266  m_dlg( aParentDlg )
267  {
268  SetButtonBitmaps( KiBitmap( www_xpm ) );
269  }
270 
271 protected:
272  void DoSetPopupControl( wxComboPopup* popup ) override
273  {
274  m_popup = nullptr;
275  }
276 
277  void OnButtonClick() override
278  {
279  wxString filename = GetValue();
280 
281  if( !filename.IsEmpty() && filename != wxT( "~" ) )
282  GetAssociatedDocument( m_dlg, GetValue() );
283  }
284 
286 };
287 
288 
289 void GRID_CELL_URL_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
290  wxEvtHandler* aEventHandler )
291 {
292  m_control = new TEXT_BUTTON_URL( aParent, m_dlg );
293 
294  wxGridCellEditor::Create(aParent, aId, aEventHandler);
295 }
296 
297 
302 class TEXT_BUTTON_FILE_BROWSER : public wxComboCtrl
303 {
304 public:
305  TEXT_BUTTON_FILE_BROWSER( wxWindow* aParent, DIALOG_SHIM* aParentDlg,
306  wxString* aCurrentDir, wxString* aExt = nullptr ) :
307  wxComboCtrl( aParent ),
308  m_dlg( aParentDlg ),
309  m_currentDir( aCurrentDir ),
310  m_ext( aExt )
311  {
312  SetButtonBitmaps( KiBitmap( folder_xpm ) );
313  }
314 
315 protected:
316  void DoSetPopupControl( wxComboPopup* popup ) override
317  {
318  m_popup = nullptr;
319  }
320 
321  void OnButtonClick() override
322  {
323  wxString path = GetValue();
324 
325  if( path.IsEmpty() )
326  path = *m_currentDir;
327  else
328  path = ExpandEnvVarSubstitutions( path );
329 
330  if( m_ext )
331  {
332  wxFileDialog dlg( nullptr, _( "Select a File" ), path, wxEmptyString, *m_ext,
333  wxFD_FILE_MUST_EXIST | wxFD_OPEN );
334 
335  if( dlg.ShowModal() == wxID_OK )
336  {
337  SetValue( dlg.GetPath() );
338  *m_currentDir = dlg.GetPath();
339  }
340  }
341  else
342  {
343  wxDirDialog dlg( nullptr, _( "Select Path" ), path,
344  wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST );
345 
346  if( dlg.ShowModal() == wxID_OK )
347  {
348  SetValue( dlg.GetPath() );
349  *m_currentDir = dlg.GetPath();
350  }
351  }
352  }
353 
355  wxString* m_currentDir;
356  wxString* m_ext;
357 };
358 
359 
360 void GRID_CELL_PATH_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
361  wxEvtHandler* aEventHandler )
362 {
363  m_control = new TEXT_BUTTON_FILE_BROWSER( aParent, m_dlg, m_currentDir );
364 
365  wxGridCellEditor::Create(aParent, aId, aEventHandler);
366 }
367 
368 
369 void GRID_CELL_SYMLIB_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
370  wxEvtHandler* aEventHandler )
371 {
372  m_control = new TEXT_BUTTON_FILE_BROWSER( aParent, m_dlg, m_currentDir, &m_ext );
373 
374  wxGridCellEditor::Create(aParent, aId, aEventHandler);
375 }
376 
377 
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: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
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:300
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...