KiCad PCB EDA Suite
dialog_fp_plugin_options.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) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
5  * Copyright (C) 2013 CERN
6  * Copyright (C) 2013-2016 KiCad Developers, see change_log.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 
27 #include <fctsys.h>
28 #include <invoke_pcb_dialog.h>
30 #include <fp_lib_table.h>
31 #include <grid_tricks.h>
32 
33 
34 #define INITIAL_HELP \
35  _( "Select an <b>Option Choice</b> in the listbox above, and then click the <b>Append Selected Option</b> button." )
36 
37 
38 using std::string;
39 
40 // re-enter the dialog with the column sizes preserved from last time.
41 static int col_width_option;
42 static int col_width_value;
43 
44 
52 {
53 
54 public:
55  DIALOG_FP_PLUGIN_OPTIONS( wxTopLevelWindow* aParent,
56  const wxString& aNickname, const wxString& aPluginType,
57  const wxString& aOptions, wxString* aResult ) :
59  m_callers_options( aOptions ),
60  m_result( aResult ),
62  {
63  wxString title = wxString::Format(
64  _( "Options for Library '%s'" ), GetChars( aNickname ) );
65 
66  SetTitle( title );
67 
68  // add Cut, Copy, and Paste to wxGrid
69  m_grid->PushEventHandler( new GRID_TRICKS( m_grid ) );
70 
71  m_grid->SetColMinimalWidth( 1, 250 );
72 
73  // Fill the grid with existing aOptions
74  string options = TO_UTF8( aOptions );
75 
76  PROPERTIES* props = LIB_TABLE::ParseOptions( options );
77 
78  if( props )
79  {
80  if( (int) props->size() > m_grid->GetNumberRows() )
81  m_grid->AppendRows( props->size() - m_grid->GetNumberRows() );
82 
83  int row = 0;
84  for( PROPERTIES::const_iterator it = props->begin(); it != props->end(); ++it, ++row )
85  {
86  m_grid->SetCellValue( row, 0, FROM_UTF8( it->first.c_str() ) );
87  m_grid->SetCellValue( row, 1, it->second );
88  }
89 
90  delete props;
91  }
92 
93  // Option Choices Panel:
94 
95  IO_MGR::PCB_FILE_T pi_type = IO_MGR::EnumFromStr( aPluginType );
96  PLUGIN::RELEASER pi( IO_MGR::PluginFind( pi_type ) );
97 
99 
100  if( m_choices.size() )
101  {
102  int row = 0;
103  for( PROPERTIES::const_iterator it = m_choices.begin(); it != m_choices.end(); ++it, ++row )
104  {
105  wxString item = FROM_UTF8( it->first.c_str() );
106 
107  m_listbox->InsertItems( 1, &item, row );
108  }
109  }
110 
111  m_html->SetPage( m_initial_help );
112 
113  if( !col_width_option )
114  {
115  m_grid->AutoSizeColumns( false );
116  }
117  else
118  {
119  m_grid->SetColSize( 0, col_width_option );
120  m_grid->SetColSize( 1, col_width_value );
121  }
122 
123  Fit();
124 
125  // initial focus on the grid please.
126  m_grid->SetFocus();
127  }
128 
130  {
131  // destroy GRID_TRICKS before m_grid.
132  m_grid->PopEventHandler( true );
133  }
134 
135 
136 private:
137  const wxString& m_callers_options;
138  wxString* m_result;
140  wxString m_initial_help;
141 
142 
145  int getCursorCol() const
146  {
147  return m_grid->GetGridCursorCol();
148  }
149 
152  int getCursorRow() const
153  {
154  return m_grid->GetGridCursorRow();
155  }
156 
157  wxArrayString getRow( int aRow )
158  {
159  wxArrayString row;
160 
161  const int col_count = m_grid->GetNumberCols();
162  for( int col = 0; col < col_count; ++col )
163  {
164  row.Add( m_grid->GetCellValue( aRow, col ) );
165  }
166 
167  return row;
168  }
169 
170  void setRow( int aRow, const wxArrayString& aPair )
171  {
172  const int col_count = m_grid->GetNumberCols();
173  for( int col = 0; col < col_count; ++col )
174  {
175  m_grid->SetCellValue( aRow, col, aPair[col] );
176  }
177  }
178 
179  wxString makeResult()
180  {
181  PROPERTIES props;
182  const int rowCount = m_grid->GetNumberRows();
183 
184  for( int row = 0; row<rowCount; ++row )
185  {
186  string name = TO_UTF8( m_grid->GetCellValue( row, 0 ).Trim( false ).Trim() );
187  UTF8 value = m_grid->GetCellValue( row, 1 ).Trim( false ).Trim();
188 
189  if( name.size() )
190  {
191  props[name] = value;
192  }
193  }
194 
195  return LIB_TABLE::FormatOptions( &props );
196  }
197 
199  {
200  col_width_option = m_grid->GetColSize( 0 );
201  col_width_value = m_grid->GetColSize( 1 );
202  }
203 
204  void abort()
205  {
206  saveColSizes();
207 
208  *m_result = m_callers_options; // tell caller "no change"
209  EndModal( 0 );
210  }
211 
212  int appendRow()
213  {
214  if( m_grid->AppendRows( 1 ) )
215  {
216  int last_row = m_grid->GetNumberRows() - 1;
217 
218  // wx documentation is wrong, SetGridCursor does not make visible.
219  m_grid->MakeCellVisible( last_row, 0 );
220  m_grid->SetGridCursor( last_row, 0 );
221 
222  return last_row;
223  }
224 
225  return -1;
226  }
227 
229  {
230  int selected_row = m_listbox->GetSelection();
231  if( selected_row != wxNOT_FOUND )
232  {
233  wxString option = m_listbox->GetString( selected_row );
234 
235  int row_count = m_grid->GetNumberRows();
236  int row;
237 
238  for( row=0; row<row_count; ++row )
239  {
240  wxString col0 = m_grid->GetCellValue( row, 0 );
241 
242  if( !col0 ) // empty col0
243  break;
244  }
245 
246  if( row == row_count )
247  row = appendRow();
248 
249  m_grid->SetCellValue( row, 0, option );
250  m_grid->AutoSizeColumns( false );
251  }
252  }
253 
254  //-----<event handlers>------------------------------------------------------
255 
256  void onListBoxItemSelected( wxCommandEvent& event ) override
257  {
258  // change the help text based on the m_listbox selection:
259  if( event.IsSelection() )
260  {
261  string option = TO_UTF8( event.GetString() );
262  UTF8 help_text;
263 
264  if( m_choices.Value( option.c_str(), &help_text ) )
265  {
266  wxString page = help_text;
267 
268  m_html->SetPage( page );
269  }
270  else
271  {
272  m_html->SetPage( m_initial_help );
273  }
274  }
275  }
276 
277  void onListBoxItemDoubleClicked( wxCommandEvent& event ) override
278  {
279  appendOption();
280  }
281 
282  void onAppendOption( wxCommandEvent& event ) override
283  {
284  appendOption();
285  }
286 
287  void onAppendRow( wxMouseEvent& event ) override
288  {
289  appendRow();
290  }
291 
292  void onDeleteRow( wxMouseEvent& event ) override
293  {
294  int rowCount = m_grid->GetNumberRows();
295  int curRow = getCursorRow();
296 
297  m_grid->DeleteRows( curRow );
298 
299  if( curRow && curRow == rowCount - 1 )
300  {
301  m_grid->MakeCellVisible( curRow-1, getCursorCol() );
302  m_grid->SetGridCursor( curRow-1, getCursorCol() );
303  }
304  }
305 
306  void onMoveUp( wxMouseEvent& event ) override
307  {
308  int curRow = getCursorRow();
309  if( curRow >= 1 )
310  {
311  int curCol = getCursorCol();
312 
313  wxArrayString move_me = getRow( curRow );
314 
315  m_grid->DeleteRows( curRow );
316  --curRow;
317  m_grid->InsertRows( curRow );
318 
319  setRow( curRow, move_me );
320 
321  wxGridTableBase* tbl = m_grid->GetTable();
322 
323  if( tbl->GetView() )
324  {
325  // fire a msg to cause redrawing
326  wxGridTableMessage msg( tbl,
327  wxGRIDTABLE_NOTIFY_ROWS_INSERTED,
328  curRow,
329  0 );
330 
331  tbl->GetView()->ProcessTableMessage( msg );
332  }
333 
334  m_grid->MakeCellVisible( curRow, curCol );
335  m_grid->SetGridCursor( curRow, curCol );
336  }
337  }
338 
339  void onMoveDown( wxMouseEvent& event ) override
340  {
341  int curRow = getCursorRow();
342  if( curRow + 1 < m_grid->GetNumberRows() )
343  {
344  int curCol = getCursorCol();
345 
346  wxArrayString move_me = getRow( curRow );
347 
348  m_grid->DeleteRows( curRow );
349  ++curRow;
350  m_grid->InsertRows( curRow );
351  setRow( curRow, move_me );
352 
353  wxGridTableBase* tbl = m_grid->GetTable();
354 
355  if( tbl->GetView() )
356  {
357  // fire a msg to cause redrawing
358  wxGridTableMessage msg( tbl,
359  wxGRIDTABLE_NOTIFY_ROWS_INSERTED,
360  curRow - 1,
361  0 );
362 
363  tbl->GetView()->ProcessTableMessage( msg );
364  }
365 
366  m_grid->MakeCellVisible( curRow, curCol );
367  m_grid->SetGridCursor( curRow, curCol );
368  }
369  }
370 
371  void onCancelButtonClick( wxCommandEvent& event ) override
372  {
373  abort();
374  }
375 
376  void onCancelCaptionButtonClick( wxCloseEvent& event ) override
377  {
378  abort();
379  }
380 
381  void onOKButtonClick( wxCommandEvent& event ) override
382  {
383  saveColSizes();
384 
385  *m_result = makeResult(); // change from edits
386  EndModal( 1 );
387  }
388  //-----</event handlers>-----------------------------------------------------
389 };
390 
391 
392 void InvokePluginOptionsEditor( wxTopLevelWindow* aCaller,
393  const wxString& aNickname, const wxString& aPluginType,
394  const wxString& aOptions, wxString* aResult )
395 {
396  DIALOG_FP_PLUGIN_OPTIONS dlg( aCaller, aNickname, aPluginType, aOptions, aResult );
397 
398  dlg.ShowModal();
399 }
int getCursorCol() const
If the cursor is not on a valid cell, because there are no rows at all, return -1, else return a 0 based column index.
Class UTF8 is an 8 bit std::string that is assuredly encoded in UTF8, and supplies special conversion...
Definition: utf8.h:53
Class DIALOG_FP_PLUGIN_OPTIONS_BASE.
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes...
Definition: macros.h:53
void onMoveUp(wxMouseEvent &event) override
void onCancelCaptionButtonClick(wxCloseEvent &event) override
#define INITIAL_HELP
bool Value(const char *aName, UTF8 *aFetchedValue=NULL) const
Function Value fetches a property by aName and returns true if that property was found, else false.
Definition: properties.cpp:24
void InvokePluginOptionsEditor(wxTopLevelWindow *aCaller, const wxString &aNickname, const wxString &aPluginType, const wxString &aOptions, wxString *aResult)
Function InvokePluginOptionsEditor calls DIALOG_FP_PLUGIN_OPTIONS dialog so that plugin options set c...
Class GRID_TRICKS is used to add cut, copy, and paste to an otherwise unmodied wxGrid instance...
Definition: grid_tricks.h:34
void onAppendOption(wxCommandEvent &event) override
Class PROPERTIES is a name/value tuple with unique names and optional values.
Definition: properties.h:34
static int col_width_option
static UTF8 FormatOptions(const PROPERTIES *aProperties)
Function FormatOptions.
Class RELEASER releases a PLUGIN in the context of a potential thrown exception, through its destruct...
Definition: io_mgr.h:476
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
static PROPERTIES * ParseOptions(const std::string &aOptionsList)
Function ParseOptions.
static PCB_FILE_T EnumFromStr(const wxString &aFileType)
Function EnumFromStr returns the PCB_FILE_T from the corresponding plugin type name: "kicad"...
Definition: io_mgr.cpp:137
static int col_width_value
Class DIALOG_FP_PLUGIN_OPTIONS is an options editor in the form of a two column name/value spreadshee...
void onCancelButtonClick(wxCommandEvent &event) override
void onMoveDown(wxMouseEvent &event) override
int getCursorRow() const
If the cursor is not on a valid cell, because there are no rows at all, return -1, else return a 0 based row index.
void onListBoxItemSelected(wxCommandEvent &event) override
void onAppendRow(wxMouseEvent &event) override
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
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
static PLUGIN * PluginFind(PCB_FILE_T aFileType)
Function PluginFind returns a PLUGIN which the caller can use to import, export, save, or load design documents.
Definition: io_mgr.cpp:58
void onListBoxItemDoubleClicked(wxCommandEvent &event) override
void onOKButtonClick(wxCommandEvent &event) override
const char * name
PCB_FILE_T
Enum PCB_FILE_T is a set of file types that the IO_MGR knows about, and for which there has been a pl...
Definition: io_mgr.h:51
DIALOG_FP_PLUGIN_OPTIONS(wxTopLevelWindow *aParent, const wxString &aNickname, const wxString &aPluginType, const wxString &aOptions, wxString *aResult)
virtual void FootprintLibOptions(PROPERTIES *aListToAppendTo) const
Function FootprintLibOptions appends supported PLUGIN options to aListToAppenTo along with internatio...
Definition: plugin.cpp:122
void setRow(int aRow, const wxArrayString &aPair)
void onDeleteRow(wxMouseEvent &event) override