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>
35
36
42
43
44PANEL_TEXT_VARIABLES::PANEL_TEXT_VARIABLES( wxWindow* aParent, PROJECT* aProject ) :
46 m_project( aProject ),
48 m_errorRow( -1 ),
49 m_errorCol( -1 )
50{
53
54 m_TextVars->ClearRows();
55 m_TextVars->SetUseNativeColLabels();
56
57 // prohibit these characters in the alias names: []{}()%~<>"='`;:.,&?/\|$
58 m_nameValidator.SetStyle( wxFILTER_EXCLUDE_CHAR_LIST );
59 m_nameValidator.SetCharExcludes( wxT( "{}[]()%~<>\"='`;:.,&?/\\|$" ) );
60
61 m_TextVars->PushEventHandler( new GRID_TRICKS( m_TextVars, [this]( wxCommandEvent& aEvent )
62 {
63 OnAddTextVar( aEvent );
64 } ) );
65 m_TextVars->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
66
67 // wxFormBuilder doesn't include this event...
68 m_TextVars->Connect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( PANEL_TEXT_VARIABLES::OnGridCellChanging ),
69 nullptr, this );
70
71 Bind( wxEVT_IDLE,
72 [this]( wxIdleEvent& aEvent )
73 {
74 // Careful of consuming CPU in an idle event handler. Check the ticker first to
75 // see if there's even a possibility of the text variables having changed.
76 if( m_project->GetTextVarsTicker() > m_lastCheckedTicker )
77 {
78 wxWindow* dialog = wxGetTopLevelParent( this );
79 wxWindow* topLevelFocus = wxGetTopLevelParent( wxWindow::FindFocus() );
80
81 if( topLevelFocus == dialog && m_lastLoaded != m_project->GetTextVars() )
83 }
84 } );
85
86 m_TextVars->SetupColumnAutosizer( TV_VALUE_COL );
87}
88
89
91{
92 // Delete the GRID_TRICKS.
93 m_TextVars->PopEventHandler( true );
94
95 m_TextVars->Disconnect( wxEVT_GRID_CELL_CHANGING,
96 wxGridEventHandler( PANEL_TEXT_VARIABLES::OnGridCellChanging ),
97 nullptr, this );
98}
99
100
102{
103 // MUST update the ticker before calling IsOK (or we'll end up re-entering through the idle
104 // event until we crash the stack).
105 m_lastCheckedTicker = m_project->GetTextVarsTicker();
106
107 if( IsOK( m_parent, _( "The text variables have been changed outside the Setup dialog.\n"
108 "Do you wish to reload them?" ) ) )
109 {
110 m_TextVars->ClearRows();
111
112 m_lastLoaded = m_project->GetTextVars();
113
114 for( const auto& var : m_lastLoaded )
115 AppendTextVar( var.first, var.second );
116 }
117}
118
119
121{
122 m_lastLoaded = m_project->GetTextVars();
123 m_lastCheckedTicker = m_project->GetTextVarsTicker();
124
125 for( const auto& var : m_lastLoaded )
126 AppendTextVar( var.first, var.second );
127
128 return true;
129}
130
131
132void PANEL_TEXT_VARIABLES::AppendTextVar( const wxString& aName, const wxString& aValue )
133{
134 int i = m_TextVars->GetNumberRows();
135
136 m_TextVars->AppendRows( 1 );
137
138 m_TextVars->SetCellValue( i, TV_NAME_COL, aName );
139
140 wxGridCellAttr* nameCellAttr = m_TextVars->GetOrCreateCellAttr( i, TV_NAME_COL );
141 wxGridCellTextEditor* nameTextEditor = new GRID_CELL_TEXT_EDITOR();
142 nameTextEditor->SetValidator( m_nameValidator );
143 nameCellAttr->SetEditor( nameTextEditor );
144 nameCellAttr->DecRef();
145
146 m_TextVars->SetCellValue( i, TV_VALUE_COL, aValue );
147}
148
149
151{
152 if( !m_TextVars->CommitPendingChanges() )
153 return false;
154
155 for( int row = 0; row < m_TextVars->GetNumberRows(); ++row )
156 {
157 if( m_TextVars->GetCellValue( row, TV_NAME_COL ).IsEmpty() )
158 {
159 m_errorRow = row;
161 m_errorMsg = _( "Variable name cannot be empty." );
162 return false;
163 }
164 }
165
166 std::map<wxString, wxString>& variables = m_project->GetTextVars();
167
168 variables.clear();
169
170 for( int row = 0; row < m_TextVars->GetNumberRows(); ++row )
171 {
172 wxString name = m_TextVars->GetCellValue( row, TV_NAME_COL );
173 wxString value = m_TextVars->GetCellValue( row, TV_VALUE_COL );
174 variables[ name ] = value;
175 }
176
177 return true;
178}
179
180
182{
183 int row = event.GetRow();
184 int col = event.GetCol();
185 wxString text = event.GetString();
186
187 if( text.IsEmpty() && col == TV_NAME_COL )
188 {
189 m_errorMsg = _( "Variable name cannot be empty." );
190 m_errorRow = row;
191 m_errorCol = col;
192
193 event.Veto();
194 }
195}
196
197
198void PANEL_TEXT_VARIABLES::OnAddTextVar( wxCommandEvent& event )
199{
200 m_TextVars->OnAddRow(
201 [&]() -> std::pair<int, int>
202 {
203 AppendTextVar( wxEmptyString, wxEmptyString );
204 return { m_TextVars->GetNumberRows() - 1, TV_NAME_COL };
205 } );
206}
207
208
209void PANEL_TEXT_VARIABLES::OnRemoveTextVar( wxCommandEvent& event )
210{
211 m_TextVars->OnDeleteRows(
212 [&]( int row )
213 {
214 m_TextVars->DeleteRows( row, 1 );
215 } );
216}
217
218
219void PANEL_TEXT_VARIABLES::OnUpdateUI( wxUpdateUIEvent& event )
220{
221 // Handle a grid error. This is delayed to OnUpdateUI so that we can change focus
222 // even when the original validation was triggered from a killFocus event (and for
223 // dialog with notebooks, so that the corresponding notebook page can be shown in
224 // the background when triggered from an OK).
225 if( !m_errorMsg.IsEmpty() )
226 {
227 // We will re-enter this routine when the error dialog is displayed, so make
228 // sure we don't keep putting up more dialogs.
229 wxString errorMsg = m_errorMsg;
230 m_errorMsg = wxEmptyString;
231
232 wxWindow* topLevelParent = wxGetTopLevelParent( this );
233
234 DisplayErrorMessage( topLevelParent, errorMsg );
235
236 m_TextVars->SetFocus();
237 m_TextVars->MakeCellVisible( m_errorRow, m_errorCol );
238 m_TextVars->SetGridCursor( m_errorRow, m_errorCol );
239
240 m_TextVars->EnableCellEditControl( true );
241 m_TextVars->ShowCellEditControl();
242 }
243
244 event.Skip();
245}
246
247
249{
250 // Fetch from other project...
251 m_lastLoaded = aOtherProject->GetTextVars();
252
253 // ... but use ticker from current project:
254 m_lastCheckedTicker = m_project->GetTextVarsTicker();
255
256 m_TextVars->ClearRows();
257
258 for( const auto& var : m_lastLoaded )
259 AppendTextVar( var.first, var.second );
260}
const char * name
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
PANEL_TEXT_VARIABLES_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
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
virtual std::map< wxString, wxString > & GetTextVars() const
Definition project.cpp:111
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)
Custom text control validator definitions.