You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

299 lines
8.6 KiB

  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. #include <invoke_pcb_dialog.h>
  26. #include <dialog_fp_plugin_options_base.h>
  27. #include <fp_lib_table.h>
  28. #include <grid_tricks.h>
  29. #include <widgets/wx_grid.h>
  30. #include <bitmaps.h>
  31. #include <macros.h>
  32. #define INITIAL_HELP \
  33. _( "Select an <b>Option Choice</b> in the listbox above, and then click the <b>Append Selected Option</b> button." )
  34. using std::string;
  35. /**
  36. * DIALOG_FP_PLUGIN_OPTIONS
  37. * is an options editor in the form of a two column name/value
  38. * spreadsheet like (table) UI. It takes hints from a pcbnew PLUGIN as to
  39. * supported options.
  40. */
  41. class DIALOG_FP_PLUGIN_OPTIONS : public DIALOG_FP_PLUGIN_OPTIONS_BASE
  42. {
  43. public:
  44. DIALOG_FP_PLUGIN_OPTIONS( wxWindow* aParent, const wxString& aNickname,
  45. const wxString& aPluginType, const wxString& aOptions,
  46. wxString* aResult ) :
  47. DIALOG_FP_PLUGIN_OPTIONS_BASE( aParent ),
  48. m_callers_options( aOptions ),
  49. m_result( aResult ),
  50. m_initial_help( INITIAL_HELP ),
  51. m_grid_widths_dirty( true )
  52. {
  53. SetTitle( wxString::Format( _( "Options for Library '%s'" ), aNickname ) );
  54. // Give a bit more room for combobox editors
  55. m_grid->SetDefaultRowSize( m_grid->GetDefaultRowSize() + 4 );
  56. m_grid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
  57. // add Cut, Copy, and Paste to wxGrid
  58. m_grid->PushEventHandler( new GRID_TRICKS( m_grid ) );
  59. // Option Choices Panel:
  60. IO_MGR::PCB_FILE_T pi_type = IO_MGR::EnumFromStr( aPluginType );
  61. PLUGIN::RELEASER pi( IO_MGR::PluginFind( pi_type ) );
  62. pi->FootprintLibOptions( &m_choices );
  63. if( m_choices.size() )
  64. {
  65. unsigned int row = 0;
  66. for( PROPERTIES::const_iterator it = m_choices.begin(); it != m_choices.end(); ++it, ++row )
  67. {
  68. wxString item = FROM_UTF8( it->first.c_str() );
  69. m_listbox->InsertItems( 1, &item, row );
  70. }
  71. }
  72. m_html->SetPage( m_initial_help );
  73. // Configure button logos
  74. m_append_button->SetBitmap( KiBitmap( BITMAPS::small_plus ) );
  75. m_delete_button->SetBitmap( KiBitmap( BITMAPS::small_trash ) );
  76. // initial focus on the grid please.
  77. SetInitialFocus( m_grid );
  78. m_sdbSizer1OK->SetDefault();
  79. }
  80. ~DIALOG_FP_PLUGIN_OPTIONS() override
  81. {
  82. // destroy GRID_TRICKS before m_grid.
  83. m_grid->PopEventHandler( true );
  84. }
  85. bool TransferDataToWindow() override
  86. {
  87. if( !DIALOG_SHIM::TransferDataToWindow() )
  88. return false;
  89. // Fill the grid with existing aOptions
  90. string options = TO_UTF8( m_callers_options );
  91. PROPERTIES* props = LIB_TABLE::ParseOptions( options );
  92. if( props )
  93. {
  94. if( (int) props->size() > m_grid->GetNumberRows() )
  95. m_grid->AppendRows( props->size() - m_grid->GetNumberRows() );
  96. int row = 0;
  97. for( PROPERTIES::const_iterator it = props->begin(); it != props->end(); ++it, ++row )
  98. {
  99. m_grid->SetCellValue( row, 0, FROM_UTF8( it->first.c_str() ) );
  100. m_grid->SetCellValue( row, 1, it->second );
  101. }
  102. delete props;
  103. }
  104. return true;
  105. }
  106. bool TransferDataFromWindow() override
  107. {
  108. if( !m_grid->CommitPendingChanges() )
  109. return false;
  110. if( !DIALOG_SHIM::TransferDataFromWindow() )
  111. return false;
  112. PROPERTIES props;
  113. const int rowCount = m_grid->GetNumberRows();
  114. for( int row = 0; row<rowCount; ++row )
  115. {
  116. string name = TO_UTF8( m_grid->GetCellValue( row, 0 ).Trim( false ).Trim() );
  117. UTF8 value = m_grid->GetCellValue( row, 1 ).Trim( false ).Trim();
  118. if( name.size() )
  119. {
  120. props[name] = value;
  121. }
  122. }
  123. *m_result = LIB_TABLE::FormatOptions( &props );
  124. return true;
  125. }
  126. private:
  127. const wxString& m_callers_options;
  128. wxString* m_result;
  129. PROPERTIES m_choices;
  130. wxString m_initial_help;
  131. bool m_grid_widths_dirty;
  132. int appendRow()
  133. {
  134. int row = m_grid->GetNumberRows();
  135. m_grid->AppendRows( 1 );
  136. // wx documentation is wrong, SetGridCursor does not make visible.
  137. m_grid->MakeCellVisible( row, 0 );
  138. m_grid->SetGridCursor( row, 0 );
  139. return row;
  140. }
  141. void appendOption()
  142. {
  143. int selected_row = m_listbox->GetSelection();
  144. if( selected_row != wxNOT_FOUND )
  145. {
  146. wxString option = m_listbox->GetString( selected_row );
  147. int row_count = m_grid->GetNumberRows();
  148. int row;
  149. for( row=0; row<row_count; ++row )
  150. {
  151. wxString col0 = m_grid->GetCellValue( row, 0 );
  152. if( !col0 ) // empty col0
  153. break;
  154. }
  155. if( row == row_count )
  156. row = appendRow();
  157. m_grid->SetCellValue( row, 0, option );
  158. m_grid_widths_dirty = true;
  159. }
  160. }
  161. //-----<event handlers>------------------------------------------------------
  162. void onListBoxItemSelected( wxCommandEvent& event ) override
  163. {
  164. // change the help text based on the m_listbox selection:
  165. if( event.IsSelection() )
  166. {
  167. string option = TO_UTF8( event.GetString() );
  168. UTF8 help_text;
  169. if( m_choices.Value( option.c_str(), &help_text ) )
  170. m_html->SetPage( help_text );
  171. else
  172. m_html->SetPage( m_initial_help );
  173. }
  174. }
  175. void onListBoxItemDoubleClicked( wxCommandEvent& event ) override
  176. {
  177. appendOption();
  178. }
  179. void onAppendOption( wxCommandEvent& ) override
  180. {
  181. if( !m_grid->CommitPendingChanges() )
  182. return;
  183. appendOption();
  184. }
  185. void onAppendRow( wxCommandEvent& ) override
  186. {
  187. if( !m_grid->CommitPendingChanges() )
  188. return;
  189. appendRow();
  190. }
  191. void onDeleteRow( wxCommandEvent& ) override
  192. {
  193. if( !m_grid->CommitPendingChanges() )
  194. return;
  195. int curRow = m_grid->GetGridCursorRow();
  196. m_grid->DeleteRows( curRow );
  197. m_grid_widths_dirty = true;
  198. curRow = std::max( 0, curRow - 1 );
  199. m_grid->MakeCellVisible( curRow, m_grid->GetGridCursorCol() );
  200. m_grid->SetGridCursor( curRow, m_grid->GetGridCursorCol() );
  201. }
  202. void onGridCellChange( wxGridEvent& aEvent ) override
  203. {
  204. m_grid_widths_dirty = true;
  205. aEvent.Skip();
  206. }
  207. void onUpdateUI( wxUpdateUIEvent& ) override
  208. {
  209. if( m_grid_widths_dirty && !m_grid->IsCellEditControlShown() )
  210. {
  211. int width = m_grid->GetClientRect().GetWidth();
  212. m_grid->AutoSizeColumn( 0 );
  213. m_grid->SetColSize( 0, std::max( 120, m_grid->GetColSize( 0 ) ) );
  214. m_grid->SetColSize( 1, width - m_grid->GetColSize( 0 ) );
  215. m_grid_widths_dirty = false;
  216. }
  217. }
  218. void onSize( wxSizeEvent& aEvent ) override
  219. {
  220. m_grid_widths_dirty = true;
  221. aEvent.Skip();
  222. }
  223. };
  224. void InvokePluginOptionsEditor( wxWindow* aCaller, const wxString& aNickname,
  225. const wxString& aPluginType, const wxString& aOptions,
  226. wxString* aResult )
  227. {
  228. DIALOG_FP_PLUGIN_OPTIONS dlg( aCaller, aNickname, aPluginType, aOptions, aResult );
  229. dlg.ShowModal();
  230. }