KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 The 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
25
26#include <algorithm>
27
28#include <bitmaps.h>
29#include <confirm.h>
30#include <validators.h>
31#include <project.h>
32#include <grid_tricks.h>
36
37
39{
42};
43
44
45PANEL_TEXT_VARIABLES::PANEL_TEXT_VARIABLES( wxWindow* aParent, PROJECT* aProject ) :
47 m_project( aProject ),
48 m_lastCheckedTicker( 0 ),
49 m_errorRow( -1 ),
50 m_errorCol( -1 )
51{
52 m_btnAddTextVar->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
53 m_btnDeleteTextVar->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
54
56 m_TextVars->SetUseNativeColLabels();
57
58 // prohibit these characters in the alias names: []{}()%~<>"='`;:.,&?/\|$
59 m_nameValidator.SetStyle( wxFILTER_EXCLUDE_CHAR_LIST );
60 m_nameValidator.SetCharExcludes( wxT( "{}[]()%~<>\"='`;:.,&?/\\|$" ) );
61
62 m_TextVars->PushEventHandler( new GRID_TRICKS( m_TextVars, [this]( wxCommandEvent& aEvent )
63 {
64 OnAddTextVar( aEvent );
65 } ) );
66 m_TextVars->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
67
68 // wxFormBuilder doesn't include this event...
69 m_TextVars->Connect( wxEVT_GRID_CELL_CHANGING,
70 wxGridEventHandler( PANEL_TEXT_VARIABLES::OnGridCellChanging ),
71 nullptr, this );
72
73 Bind( wxEVT_IDLE,
74 [this]( wxIdleEvent& aEvent )
75 {
76 // Careful of consuming CPU in an idle event handler. Check the ticker first to
77 // see if there's even a possibility of the text variables having changed.
79 {
80 wxWindow* dialog = wxGetTopLevelParent( this );
81 wxWindow* topLevelFocus = wxGetTopLevelParent( wxWindow::FindFocus() );
82
83 if( topLevelFocus == dialog && m_lastLoaded != m_project->GetTextVars() )
84 checkReload();
85 }
86 } );
87
88 m_autoSizer = std::make_unique<WX_GRID_AUTOSIZER>( *m_TextVars,
90 { TV_NAME_COL, 72 },
91 { TV_VALUE_COL, 120 },
92 },
94}
95
96
98{
99 // Delete the GRID_TRICKS.
100 m_TextVars->PopEventHandler( true );
101
102 m_TextVars->Disconnect( wxEVT_GRID_CELL_CHANGING,
103 wxGridEventHandler( PANEL_TEXT_VARIABLES::OnGridCellChanging ),
104 nullptr, this );
105}
106
107
109{
110 // MUST update the ticker before calling IsOK (or we'll end up re-entering through the idle
111 // event until we crash the stack).
113
114 if( IsOK( m_parent, _( "The text variables have been changed outside the Setup dialog.\n"
115 "Do you wish to reload them?" ) ) )
116 {
118
120
121 for( const auto& var : m_lastLoaded )
122 AppendTextVar( var.first, var.second );
123 }
124}
125
126
128{
131
132 for( const auto& var : m_lastLoaded )
133 AppendTextVar( var.first, var.second );
134
135 return true;
136}
137
138
139void PANEL_TEXT_VARIABLES::AppendTextVar( const wxString& aName, const wxString& aValue )
140{
141 int i = m_TextVars->GetNumberRows();
142
143 m_TextVars->AppendRows( 1 );
144
145 m_TextVars->SetCellValue( i, TV_NAME_COL, aName );
146
147 wxGridCellAttr* nameCellAttr = m_TextVars->GetOrCreateCellAttr( i, TV_NAME_COL );
148 wxGridCellTextEditor* nameTextEditor = new GRID_CELL_TEXT_EDITOR();
149 nameTextEditor->SetValidator( m_nameValidator );
150 nameCellAttr->SetEditor( nameTextEditor );
151 nameCellAttr->DecRef();
152
153 m_TextVars->SetCellValue( i, TV_VALUE_COL, aValue );
154}
155
156
158{
160 return false;
161
162 for( int row = 0; row < m_TextVars->GetNumberRows(); ++row )
163 {
164 if( m_TextVars->GetCellValue( row, TV_NAME_COL ).IsEmpty() )
165 {
166 m_errorRow = row;
168 m_errorMsg = _( "Variable name cannot be empty." );
169 return false;
170 }
171 }
172
173 std::map<wxString, wxString>& variables = m_project->GetTextVars();
174
175 variables.clear();
176
177 for( int row = 0; row < m_TextVars->GetNumberRows(); ++row )
178 {
179 wxString name = m_TextVars->GetCellValue( row, TV_NAME_COL );
180 wxString value = m_TextVars->GetCellValue( row, TV_VALUE_COL );
181 variables[ name ] = value;
182 }
183
184 return true;
185}
186
187
189{
190 int row = event.GetRow();
191 int col = event.GetCol();
192 wxString text = event.GetString();
193
194 if( text.IsEmpty() && col == TV_NAME_COL )
195 {
196 m_errorMsg = _( "Variable name cannot be empty." );
197 m_errorRow = row;
198 m_errorCol = col;
199
200 event.Veto();
201 }
202}
203
204
205void PANEL_TEXT_VARIABLES::OnAddTextVar( wxCommandEvent& event )
206{
208 [&]() -> std::pair<int, int>
209 {
210 AppendTextVar( wxEmptyString, wxEmptyString );
211 return { m_TextVars->GetNumberRows() - 1, TV_NAME_COL };
212 } );
213}
214
215
216void PANEL_TEXT_VARIABLES::OnRemoveTextVar( wxCommandEvent& event )
217{
219 [&]( int row )
220 {
221 m_TextVars->DeleteRows( row, 1 );
222 } );
223}
224
225
226void PANEL_TEXT_VARIABLES::OnUpdateUI( wxUpdateUIEvent& event )
227{
228 // Handle a grid error. This is delayed to OnUpdateUI so that we can change focus
229 // even when the original validation was triggered from a killFocus event (and for
230 // dialog with notebooks, so that the corresponding notebook page can be shown in
231 // the background when triggered from an OK).
232 if( !m_errorMsg.IsEmpty() )
233 {
234 // We will re-enter this routine when the error dialog is displayed, so make
235 // sure we don't keep putting up more dialogs.
236 wxString errorMsg = m_errorMsg;
237 m_errorMsg = wxEmptyString;
238
239 wxWindow* topLevelParent = wxGetTopLevelParent( this );
240
241 DisplayErrorMessage( topLevelParent, errorMsg );
242
243 m_TextVars->SetFocus();
244 m_TextVars->MakeCellVisible( m_errorRow, m_errorCol );
245 m_TextVars->SetGridCursor( m_errorRow, m_errorCol );
246
247 m_TextVars->EnableCellEditControl( true );
248 m_TextVars->ShowCellEditControl();
249 }
250}
251
252
254{
255 // Fetch from other project...
256 m_lastLoaded = aOtherProject->GetTextVars();
257
258 // ... but use ticker from current project:
260
262
263 for( const auto& var : m_lastLoaded )
264 AppendTextVar( var.first, var.second );
265}
const char * name
Definition: DXF_plotter.cpp:62
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition: bitmap.cpp:110
This class works around a bug in wxGrid where the first keystroke doesn't get sent through the valida...
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition: grid_tricks.h:61
Class PANEL_TEXT_VARIABLES_BASE.
STD_BITMAP_BUTTON * m_btnDeleteTextVar
std::unique_ptr< WX_GRID_AUTOSIZER > m_autoSizer
bool TransferDataToWindow() override
std::map< wxString, wxString > m_lastLoaded
void OnGridCellChanging(wxGridEvent &event)
void OnUpdateUI(wxUpdateUIEvent &event) override
void OnRemoveTextVar(wxCommandEvent &event) override
bool TransferDataFromWindow() override
void OnAddTextVar(wxCommandEvent &event) override
void AppendTextVar(const wxString &aName, const wxString &aValue)
wxTextValidator m_nameValidator
void ImportSettingsFrom(const PROJECT *aOtherProject)
PANEL_TEXT_VARIABLES(wxWindow *aParent, PROJECT *aProject)
Container for project specific data.
Definition: project.h:65
int GetTextVarsTicker() const
Definition: project.h:118
virtual std::map< wxString, wxString > & GetTextVars() const
Definition: project.cpp:98
void SetBitmap(const wxBitmapBundle &aBmp)
std::map< int, int > COL_MIN_WIDTHS
Map of column indices to minimum widths.
void OnDeleteRows(const std::function< void(int row)> &aDeleter)
Handles a row deletion event.
Definition: wx_grid.cpp:704
void OnAddRow(const std::function< std::pair< int, int >()> &aAdder)
Definition: wx_grid.cpp:684
void ClearRows()
wxWidgets recently added an ASSERT which fires if the position is greater than or equal to the number...
Definition: wx_grid.h:220
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:632
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:251
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:194
This file is part of the common library.
#define _(s)
@ TV_VALUE_COL
Custom text control validator definitions.