KiCad PCB EDA Suite
panel_text_variables.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) 2020-2021 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 <panel_text_variables.h>
25 
26 #include <bitmaps.h>
27 #include <confirm.h>
28 #include <validators.h>
29 #include <project.h>
30 #include <grid_tricks.h>
31 #include <widgets/wx_grid.h>
32 
33 #include <algorithm>
34 
36 {
39 };
40 
41 
42 PANEL_TEXT_VARIABLES::PANEL_TEXT_VARIABLES( wxWindow* aParent, PROJECT* aProject ) :
43  PANEL_TEXT_VARIABLES_BASE( aParent ),
44  m_project( aProject ),
45  m_errorRow( -1 ), m_errorCol( -1 ),
46  m_gridWidthsDirty( true )
47 {
50 
52 
53  // prohibit these characters in the alias names: []{}()%~<>"='`;:.,&?/\|$
54  m_nameValidator.SetStyle( wxFILTER_EXCLUDE_CHAR_LIST );
55  m_nameValidator.SetCharExcludes( wxT( "{}[]()%~<>\"='`;:.,&?/\\|$" ) );
56 
57  m_TextVars->PushEventHandler( new GRID_TRICKS( m_TextVars ) );
58  m_TextVars->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
59 
60  // wxFormBuilder doesn't include this event...
61  m_TextVars->Connect( wxEVT_GRID_CELL_CHANGING,
62  wxGridEventHandler( PANEL_TEXT_VARIABLES::OnGridCellChanging ),
63  nullptr, this );
64 }
65 
66 
68 {
69  // Delete the GRID_TRICKS.
70  m_TextVars->PopEventHandler( true );
71 
72  m_TextVars->Disconnect( wxEVT_GRID_CELL_CHANGING,
73  wxGridEventHandler( PANEL_TEXT_VARIABLES::OnGridCellChanging ),
74  nullptr, this );
75 }
76 
77 
79 {
80  std::map<wxString, wxString>& variables = m_project->GetTextVars();
81 
82  for( const auto& var : variables )
83  AppendTextVar( var.first, var.second );
84 
85  return true;
86 }
87 
88 
89 void PANEL_TEXT_VARIABLES::AppendTextVar( const wxString& aName, const wxString& aValue )
90 {
91  int i = m_TextVars->GetNumberRows();
92 
93  m_TextVars->AppendRows( 1 );
94 
95  m_TextVars->SetCellValue( i, TV_NAME_COL, aName );
96 
97  wxGridCellAttr* nameCellAttr = m_TextVars->GetOrCreateCellAttr( i, TV_NAME_COL );
98  wxGridCellTextEditor* nameTextEditor = new GRID_CELL_TEXT_EDITOR();
99  nameTextEditor->SetValidator( m_nameValidator );
100  nameCellAttr->SetEditor( nameTextEditor );
101  nameCellAttr->DecRef();
102 
103  m_TextVars->SetCellValue( i, TV_VALUE_COL, aValue );
104 }
105 
106 
108 {
110  return false;
111 
112  for( int row = 0; row < m_TextVars->GetNumberRows(); ++row )
113  {
114  if( m_TextVars->GetCellValue( row, TV_NAME_COL ).IsEmpty() )
115  {
116  m_errorRow = row;
118  m_errorMsg = _( "Variable name cannot be empty." );
119  return false;
120  }
121  }
122 
123  std::map<wxString, wxString>& variables = m_project->GetTextVars();
124 
125  variables.clear();
126 
127  for( int row = 0; row < m_TextVars->GetNumberRows(); ++row )
128  {
129  wxString name = m_TextVars->GetCellValue( row, TV_NAME_COL );
130  wxString value = m_TextVars->GetCellValue( row, TV_VALUE_COL );
131  variables[ name ] = value;
132  }
133 
134  return true;
135 }
136 
137 
139 {
140  int row = event.GetRow();
141  int col = event.GetCol();
142  wxString text = event.GetString();
143 
144  if( text.IsEmpty() && col == TV_NAME_COL )
145  {
146  m_errorMsg = _( "Variable name cannot be empty." );
147  m_errorRow = row;
148  m_errorCol = col;
149 
150  event.Veto();
151  }
152 }
153 
154 
155 void PANEL_TEXT_VARIABLES::OnAddTextVar( wxCommandEvent& event )
156 {
158  return;
159 
160  AppendTextVar( wxEmptyString, wxEmptyString );
161 
162  m_TextVars->MakeCellVisible( m_TextVars->GetNumberRows() - 1, TV_NAME_COL );
163  m_TextVars->SetGridCursor( m_TextVars->GetNumberRows() - 1, TV_NAME_COL );
164 
165  m_TextVars->EnableCellEditControl( true );
166  m_TextVars->ShowCellEditControl();
167 }
168 
169 
170 void PANEL_TEXT_VARIABLES::OnRemoveTextVar( wxCommandEvent& event )
171 {
172  int curRow = m_TextVars->GetGridCursorRow();
173 
174  if( curRow < 0 || m_TextVars->GetNumberRows() <= curRow )
175  return;
176 
177  m_TextVars->CommitPendingChanges( true /* silent mode; we don't care if it's valid */ );
178  m_TextVars->DeleteRows( curRow, 1 );
179 
180  m_TextVars->MakeCellVisible( std::max( 0, curRow-1 ), m_TextVars->GetGridCursorCol() );
181  m_TextVars->SetGridCursor( std::max( 0, curRow-1 ), m_TextVars->GetGridCursorCol() );
182 }
183 
184 
185 void PANEL_TEXT_VARIABLES::OnGridCellChange( wxGridEvent& aEvent )
186 {
187  m_gridWidthsDirty = true;
188 
189  aEvent.Skip();
190 }
191 
192 
193 void PANEL_TEXT_VARIABLES::OnUpdateUI( wxUpdateUIEvent& event )
194 {
195  if( m_gridWidthsDirty )
196  {
197  int width = m_TextVars->GetClientRect().GetWidth();
198 
199  m_TextVars->AutoSizeColumn( TV_NAME_COL );
200  m_TextVars->SetColSize( TV_NAME_COL, std::max( m_TextVars->GetColSize( TV_NAME_COL ),
201  120 ) );
202 
203  m_TextVars->SetColSize( TV_VALUE_COL, width - m_TextVars->GetColSize( TV_NAME_COL ) );
204  m_gridWidthsDirty = false;
205  }
206 
207  // Handle a grid error. This is delayed to OnUpdateUI so that we can change focus
208  // even when the original validation was triggered from a killFocus event (and for
209  // dialog with notebooks, so that the corresponding notebook page can be shown in
210  // the background when triggered from an OK).
211  if( !m_errorMsg.IsEmpty() )
212  {
213  // We will re-enter this routine when the error dialog is displayed, so make
214  // sure we don't keep putting up more dialogs.
215  wxString errorMsg = m_errorMsg;
216  m_errorMsg = wxEmptyString;
217 
218  DisplayErrorMessage( this, errorMsg );
219 
220  m_TextVars->SetFocus();
221  m_TextVars->MakeCellVisible( m_errorRow, m_errorCol );
222  m_TextVars->SetGridCursor( m_errorRow, m_errorCol );
223 
224  m_TextVars->EnableCellEditControl( true );
225  m_TextVars->ShowCellEditControl();
226  }
227 }
228 
229 
230 void PANEL_TEXT_VARIABLES::OnGridSize( wxSizeEvent& event )
231 {
232  m_gridWidthsDirty = true;
233 
234  event.Skip();
235 }
236 
virtual std::map< wxString, wxString > & GetTextVars() const
Definition: project.cpp:78
Container for project specific data.
Definition: project.h:62
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:284
void OnAddTextVar(wxCommandEvent &event) override
This file is part of the common library.
void OnGridSize(wxSizeEvent &event) override
bool TransferDataToWindow() override
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition: grid_tricks.h:55
void OnRemoveTextVar(wxCommandEvent &event) override
This class works around a bug in wxGrid where the first keystroke doesn't get sent through the valida...
Definition: validators.h:44
void OnGridCellChange(wxGridEvent &event) override
#define _(s)
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:190
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
wxTextValidator m_nameValidator
Class PANEL_TEXT_VARIABLES_BASE.
const char * name
Definition: DXF_plotter.cpp:56
bool TransferDataFromWindow() override
void ClearRows()
wxWidgets recently added an ASSERT which fires if the position is greater than or equal to the number...
Definition: wx_grid.h:106
PANEL_TEXT_VARIABLES(wxWindow *aParent, PROJECT *aProject)
void OnUpdateUI(wxUpdateUIEvent &event) override
void OnGridCellChanging(wxGridEvent &event)
Custom text control validator definitions.
void AppendTextVar(const wxString &aName, const wxString &aValue)