Skip to content

Commit 6bbee66

Browse files
committed
Small UX/layout improvement to dialog warning on unsaved changes
1 parent 49930f3 commit 6bbee66

1 file changed

Lines changed: 87 additions & 15 deletions

File tree

src/gui/gameframe.cc

Lines changed: 87 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <wx/dcps.h>
3535
#endif // !defined(__WXMSW__) || wxUSE_POSTSCRIPT
3636
#include <wx/splitter.h>
37+
#include <wx/artprov.h>
3738

3839
#include "gambit.h"
3940

@@ -1311,24 +1312,95 @@ void GameFrame::OnUnsplit(wxSplitterEvent &)
13111312

13121313
namespace {
13131314

1314-
wxString CloseWarningMessage(GameDocument *p_doc)
1315+
struct CloseWarningText {
1316+
wxString primary;
1317+
wxString secondary;
1318+
};
1319+
1320+
CloseWarningText CloseWarningMessage(GameDocument *p_doc)
13151321
{
1316-
if (p_doc->IsGameModified() && !p_doc->IsWorkspaceModified()) {
1317-
return _("This game has unsaved changes.\n\n"
1318-
"Close without saving?");
1322+
const bool gameModified = p_doc->IsGameModified();
1323+
const bool workspaceModified = p_doc->IsWorkspaceModified();
1324+
1325+
if (gameModified && !workspaceModified) {
1326+
return {_("This game has unsaved changes."),
1327+
_("If you close this window now, changes to the game will be lost.")};
13191328
}
1320-
if (!p_doc->IsGameModified() && p_doc->IsWorkspaceModified()) {
1321-
return _("There are unsaved computational results.\n\n"
1322-
"These can be saved in a Gambit workspace file.\n"
1323-
"Close without saving?");
1329+
1330+
if (!gameModified && workspaceModified) {
1331+
return {_("There are unsaved computational results."),
1332+
_("These results can be saved in a Gambit workspace file. "
1333+
"If you close this window now, the unsaved results will be lost.")};
13241334
}
1325-
if (p_doc->IsGameModified() && p_doc->IsWorkspaceModified()) {
1326-
return _("This game has unsaved changes, and there are unsaved computational results.\n\n"
1327-
"Close without saving?");
1335+
1336+
if (gameModified && workspaceModified) {
1337+
return {_("This game and its computational results have unsaved changes."),
1338+
_("If you close this window now, changes to the game and unsaved "
1339+
"computational results will be lost.")};
13281340
}
1329-
return wxEmptyString;
1341+
1342+
return {wxEmptyString, wxEmptyString};
13301343
}
13311344

1345+
class CloseWarningDialog final : public wxDialog {
1346+
public:
1347+
CloseWarningDialog(wxWindow *parent, const CloseWarningText &text)
1348+
: wxDialog(parent, wxID_ANY, _("Unsaved Changes"), wxDefaultPosition, wxDefaultSize,
1349+
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
1350+
{
1351+
auto *topSizer = new wxBoxSizer(wxVERTICAL);
1352+
1353+
auto *contentSizer = new wxBoxSizer(wxHORIZONTAL);
1354+
contentSizer->Add(new wxStaticBitmap(this, wxID_ANY,
1355+
wxArtProvider::GetBitmap(wxART_WARNING, wxART_MESSAGE_BOX,
1356+
wxSize(32, 32))),
1357+
0, wxALIGN_TOP | wxRIGHT, FromDIP(16));
1358+
1359+
auto *textSizer = new wxBoxSizer(wxVERTICAL);
1360+
1361+
auto *primary = new wxStaticText(this, wxID_ANY, text.primary);
1362+
auto font = primary->GetFont();
1363+
font.SetWeight(wxFONTWEIGHT_BOLD);
1364+
primary->SetFont(font);
1365+
1366+
auto *secondary = new wxStaticText(this, wxID_ANY, text.secondary);
1367+
secondary->Wrap(FromDIP(460));
1368+
1369+
auto *question = new wxStaticText(this, wxID_ANY, _("Close without saving?"));
1370+
question->Wrap(FromDIP(460));
1371+
1372+
textSizer->Add(primary, 0, wxBOTTOM, FromDIP(8));
1373+
textSizer->Add(secondary, 0, wxBOTTOM, FromDIP(12));
1374+
textSizer->Add(question, 0);
1375+
1376+
contentSizer->Add(textSizer, 1, wxEXPAND);
1377+
1378+
topSizer->Add(contentSizer, 1, wxEXPAND | wxALL, FromDIP(20));
1379+
1380+
auto *buttonSizer = new wxBoxSizer(wxHORIZONTAL);
1381+
1382+
auto *cancelButton = new wxButton(this, wxID_CANCEL, _("Cancel"));
1383+
auto *closeButton = new wxButton(this, wxID_YES, _("Close Without Saving"));
1384+
1385+
buttonSizer->AddStretchSpacer();
1386+
buttonSizer->Add(cancelButton, 0, wxRIGHT, FromDIP(8));
1387+
buttonSizer->Add(closeButton, 0);
1388+
1389+
topSizer->Add(buttonSizer, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, FromDIP(20));
1390+
1391+
SetSizerAndFit(topSizer);
1392+
SetMinSize(wxSize(FromDIP(540), -1));
1393+
1394+
SetEscapeId(wxID_CANCEL);
1395+
SetAffirmativeId(wxID_YES);
1396+
1397+
cancelButton->SetDefault();
1398+
cancelButton->SetFocus();
1399+
1400+
CentreOnParent();
1401+
}
1402+
};
1403+
13321404
} // namespace
13331405

13341406
void GameFrame::OnCloseWindow(wxCloseEvent &p_event)
@@ -1339,10 +1411,10 @@ void GameFrame::OnCloseWindow(wxCloseEvent &p_event)
13391411
}
13401412

13411413
if (m_doc->IsModified()) {
1342-
const int response = wxMessageBox(CloseWarningMessage(m_doc), _("Unsaved Changes"),
1343-
wxYES_NO | wxNO_DEFAULT | wxICON_WARNING, this);
1414+
const auto warning = CloseWarningMessage(m_doc);
13441415

1345-
if (response != wxYES) {
1416+
CloseWarningDialog dialog(this, warning);
1417+
if (dialog.ShowModal() != wxID_YES) {
13461418
p_event.Veto();
13471419
return;
13481420
}

0 commit comments

Comments
 (0)