KiCad PCB EDA Suite
Loading...
Searching...
No Matches
confirm.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) 2007 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <confirm.h>
26
27#include <functional>
28#include <wx/app.h>
29#include <wx/stockitem.h>
30#include <wx/richmsgdlg.h>
31#include <wx/msgdlg.h>
32#include <wx/choicdlg.h>
33#include <wx/crt.h>
39static const wxChar traceConfirm[] = wxT( "KICAD_CONFIRM" );
40
41
42bool AskOverrideLock( wxWindow* aParent, const wxString& aMessage )
43{
44#ifdef __APPLE__
45 // wxMessageDialog gets the button spacing wrong on Mac so we have to use wxRichMessageDialog.
46 // Note that its warning icon is more like wxMessageDialog's error icon, so we use it instead
47 // of wxICON_ERROR.
48 wxRichMessageDialog dlg( aParent, aMessage, _( "File Open Warning" ),
49 wxYES_NO | wxICON_WARNING | wxCENTER );
50 dlg.SetExtendedMessage( _( "Interleaved saves may produce very unexpected results." )
51 + wxS( "\n" ) );
52 dlg.SetYesNoLabels( _( "&Cancel" ), _( "&Open Anyway" ) );
53#else
54 KICAD_MESSAGE_DIALOG_BASE dlg( aParent, aMessage, _( "File Open Warning" ),
55 wxYES_NO | wxICON_ERROR | wxCENTER );
56 dlg.SetExtendedMessage( _( "Interleaved saves may produce very unexpected results." ) );
57 dlg.SetYesNoLabels( _( "&Cancel" ), _( "&Open Anyway" ) );
58#endif
59
60 return dlg.ShowModal() == wxID_NO;
61}
62
63
64int UnsavedChangesDialog( wxWindow* parent, const wxString& aMessage, bool* aApplyToAll )
65{
66 static bool s_apply_to_all = false;
67
68 KICAD_RICH_MESSAGE_DIALOG_BASE dlg( parent, aMessage, _( "Save Changes?" ),
69 wxYES_NO | wxCANCEL |
70 wxYES_DEFAULT | wxICON_WARNING | wxCENTER );
71 dlg.SetExtendedMessage( _( "If you don't save, all your changes will be permanently lost." )
72 + wxS( "\n" ) );
73 dlg.SetYesNoLabels( _( "&Save" ), _( "&Discard Changes" ) );
74
75 if( aApplyToAll )
76 dlg.ShowCheckBox( _( "&Apply to all" ), s_apply_to_all );
77
78 int ret = dlg.ShowModal();
79
80 if( aApplyToAll )
81 {
82 *aApplyToAll = dlg.IsCheckBoxChecked();
83 s_apply_to_all = dlg.IsCheckBoxChecked();
84 }
85
86 // Returns wxID_YES, wxID_NO, or wxID_CANCEL
87 return ret;
88}
89
90
91int UnsavedChangesDialog( wxWindow* parent, const wxString& aMessage )
92{
93#ifdef __APPLE__
94 // wxMessageDialog gets the button order (and spacing) wrong on Mac so we have to use
95 // wxRichMessageDialog.
96 return UnsavedChangesDialog( parent, aMessage, nullptr );
97#else
98 int ret = wxID_CANCEL;
99
100 {
101 // Scoped so wxWindowDisabler and dlg are destroyed before we re-raise the parent
102#ifdef _WIN32
103 // wxMessageDialog on windows invokes TaskDialogIndirect which is a native function for a
104 // dialog. As a result it skips wxWidgets for modal management...and we don't parent frames
105 // properly among other things for Windows to do the right thing by default.
106 // Disable all the windows manually to avoid being able to hit this dialog from the tool
107 // frame and kicad frame at the same time.
108 wxWindowDisabler disable( true );
109#endif
110
111 KICAD_MESSAGE_DIALOG_BASE dlg( parent, aMessage, _( "Save Changes?" ),
112 wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxICON_WARNING | wxCENTER );
113 dlg.SetExtendedMessage( _( "If you don't save, all your changes will be permanently lost." ) );
114 dlg.SetYesNoLabels( _( "&Save" ), _( "&Discard Changes" ) );
115
116 // Returns wxID_YES, wxID_NO, or wxID_CANCEL
117 ret = dlg.ShowModal();
118 }
119
120#ifdef _WIN32
121 // Counterpart to wxWindowDisabler above. After it re-enables all windows, the OS must
122 // choose which to activate and may pick an unrelated application. Raise and focus the
123 // parent explicitly so the user isn't left in another window.
124 if( parent )
125 {
126 parent->Raise();
127 wxSafeYield();
128 parent->SetFocus();
129 }
130#endif
131
132 return ret;
133#endif
134}
135
136
137bool ConfirmRevertDialog( wxWindow* parent, const wxString& aMessage )
138{
139 KICAD_MESSAGE_DIALOG_BASE dlg( parent, aMessage, wxEmptyString,
140 wxOK | wxCANCEL | wxOK_DEFAULT | wxICON_WARNING | wxCENTER );
141 dlg.SetExtendedMessage( _( "Your current changes will be permanently lost." ) );
142 dlg.SetOKCancelLabels( _( "&Revert" ), _( "&Cancel" ) );
143
144 return dlg.ShowModal() == wxID_OK;
145}
146
147
149
150bool HandleUnsavedChanges( wxWindow* aParent, const wxString& aMessage,
151 const std::function<bool()>& aSaveFunction )
152{
155 {
156 case wxID_YES: return aSaveFunction();
157 case wxID_NO: return true; // proceed without saving
158 default:
159 case wxID_CANCEL: return false;
160 }
161}
162
167
168
169int OKOrCancelDialog( wxWindow* aParent, const wxString& aWarning, const wxString& aMessage,
170 const wxString& aDetailedMessage, const wxString& aOKLabel,
171 const wxString& aCancelLabel, bool* aApplyToAll )
172{
173 KICAD_RICH_MESSAGE_DIALOG_BASE dlg( aParent, aMessage, aWarning,
174 wxOK | wxCANCEL | wxOK_DEFAULT | wxICON_WARNING | wxCENTER );
175
176 dlg.SetOKCancelLabels( ( aOKLabel.IsEmpty() ) ? _( "&OK" ) : aOKLabel,
177 ( aCancelLabel.IsEmpty() ) ? _( "&Cancel" ) : aCancelLabel );
178
179 if( !aDetailedMessage.IsEmpty() )
180 dlg.SetExtendedMessage( aDetailedMessage );
181
182 if( aApplyToAll )
183 dlg.ShowCheckBox( _( "&Apply to all" ), true );
184
185 int ret = dlg.ShowModal();
186
187 if( aApplyToAll )
188 *aApplyToAll = dlg.IsCheckBoxChecked();
189
190 // Returns wxID_OK or wxID_CANCEL
191 return ret;
192}
193
194
195// DisplayError should be deprecated, use DisplayErrorMessage instead
196void DisplayError( wxWindow* aParent, const wxString& aText )
197{
198 if( !wxTheApp || !wxTheApp->IsMainLoopRunning() )
199 {
200 wxLogError( "%s", aText );
201 return;
202 }
203
204 if( !wxTheApp->IsGUI() )
205 {
206 wxFprintf( stderr, aText );
207 return;
208 }
209
211
212 dlg = new KICAD_MESSAGE_DIALOG_BASE( aParent, aText, _( "Error" ),
213 wxOK | wxCENTRE | wxRESIZE_BORDER |
214 wxICON_ERROR | wxSTAY_ON_TOP );
215
216 dlg->ShowModal();
217 dlg->Destroy();
218}
219
220
221void DisplayErrorMessage( wxWindow* aParent, const wxString& aText, const wxString& aExtraInfo )
222{
223 if( !wxTheApp || !wxTheApp->IsMainLoopRunning() )
224 {
225 wxLogError( "%s %s", aText, aExtraInfo );
226 return;
227 }
228
229 if( !wxTheApp->IsGUI() )
230 {
231 wxFprintf( stderr, aText );
232 return;
233 }
234
236
237 dlg = new KICAD_MESSAGE_DIALOG_BASE( aParent, aText, _( "Error" ),
238 wxOK | wxCENTRE | wxRESIZE_BORDER |
239 wxICON_ERROR | wxSTAY_ON_TOP );
240
241 if( !aExtraInfo.IsEmpty() )
242 dlg->SetExtendedMessage( aExtraInfo );
243
244 dlg->ShowModal();
245 dlg->Destroy();
246}
247
248
249void DisplayInfoMessage( wxWindow* aParent, const wxString& aMessage, const wxString& aExtraInfo )
250{
251 if( !wxTheApp || !wxTheApp->GetTopWindow() )
252 {
253 wxLogTrace( traceConfirm, wxS( "%s %s" ), aMessage, aExtraInfo );
254 return;
255 }
256
257 if( !wxTheApp->IsGUI() )
258 {
259 wxFprintf( stdout, "%s %s", aMessage, aExtraInfo );
260 return;
261 }
262
264 int icon = wxICON_INFORMATION;
265
266 dlg = new KICAD_MESSAGE_DIALOG_BASE( aParent, aMessage, _( "Information" ),
267 wxOK | wxCENTRE | wxRESIZE_BORDER |
268 icon | wxSTAY_ON_TOP );
269
270 if( !aExtraInfo.IsEmpty() )
271 dlg->SetExtendedMessage( aExtraInfo );
272
273 dlg->ShowModal();
274 dlg->Destroy();
275}
276
277
278bool IsOK( wxWindow* aParent, const wxString& aMessage )
279{
280 // wxMessageDialog no longer responds correctly to the <ESC> key (on at least OSX and MSW)
281 // so we're now using wxRichMessageDialog.
282 //
283 // Note also that we have to repurpose an OK/Cancel version of it because otherwise wxWidgets
284 // uses "destructive" spacing for the "No" button.
285
286#ifdef __APPLE__
287 // Why is wxICON_QUESTION a light-bulb on Mac? That has more of a hint or info connotation.
288 int icon = wxICON_WARNING;
289#else
290 int icon = wxICON_QUESTION;
291#endif
292
293 KICAD_MESSAGE_DIALOG dlg( aParent, aMessage, _( "Confirmation" ),
294 wxOK | wxCANCEL | wxOK_DEFAULT |
295 wxCENTRE | icon | wxSTAY_ON_TOP );
296
297 dlg.SetOKCancelLabels( _( "&Yes" ), _( "&No" ) );
298
299 return dlg.ShowModal() == wxID_OK;
300}
301
302
303int SelectSingleOption( wxWindow* aParent, const wxString& aTitle,
304 const wxString& aMessage, const wxArrayString& aOptions )
305{
306 wxSingleChoiceDialog dlg( aParent, aMessage, aTitle, aOptions );
307
308 if( dlg.ShowModal() != wxID_OK )
309 return -1;
310
311 return dlg.GetSelection();
312}
313
bool AskOverrideLock(wxWindow *aParent, const wxString &aMessage)
Display a dialog indicating the file is already open, with an option to reset the lock.
Definition confirm.cpp:42
int SelectSingleOption(wxWindow *aParent, const wxString &aTitle, const wxString &aMessage, const wxArrayString &aOptions)
Display a dialog with radioboxes asking the user to select an option.
Definition confirm.cpp:303
int OKOrCancelDialog(wxWindow *aParent, const wxString &aWarning, const wxString &aMessage, const wxString &aDetailedMessage, const wxString &aOKLabel, const wxString &aCancelLabel, bool *aApplyToAll)
Display a warning dialog with aMessage and returns the user response.
Definition confirm.cpp:169
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:278
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:249
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
Definition confirm.cpp:150
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:221
int UnsavedChangesDialog(wxWindow *parent, const wxString &aMessage, bool *aApplyToAll)
A specialized version of HandleUnsavedChanges which handles an apply-to-all checkbox.
Definition confirm.cpp:64
bool ConfirmRevertDialog(wxWindow *parent, const wxString &aMessage)
Display a confirmation dialog for a revert action.
Definition confirm.cpp:137
static int g_lastUnsavedChangesResult
Definition confirm.cpp:148
int GetLastUnsavedChangesResponse()
Return the result code from the last call to HandleUnsavedChanges(): wxID_YES, wxID_NO or wxID_CANCEL...
Definition confirm.cpp:163
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:196
This file is part of the common library.
#define KICAD_RICH_MESSAGE_DIALOG_BASE
Definition confirm.h:51
#define KICAD_MESSAGE_DIALOG
Definition confirm.h:52
#define KICAD_MESSAGE_DIALOG_BASE
Definition confirm.h:50
#define _(s)
static const wxChar traceConfirm[]
Flag to enable confirmation dialog debugging output.
Definition confirm.cpp:39