diff options
author | Daniel Wilhelm <shieldwed@outlook.com> | 2017-02-13 21:25:04 -0700 |
---|---|---|
committer | Daniel Wilhelm <shieldwed@outlook.com> | 2017-02-13 21:25:04 -0700 |
commit | 9d071d2a2cec9a7662a02669488569a017f0ea35 (patch) | |
tree | c83a623fbdff098339b66d21ea2e81f3f67344ae /wx+/popup_dlg.cpp | |
parent | 8.8 (diff) | |
download | FreeFileSync-9d071d2a2cec9a7662a02669488569a017f0ea35.tar.gz FreeFileSync-9d071d2a2cec9a7662a02669488569a017f0ea35.tar.bz2 FreeFileSync-9d071d2a2cec9a7662a02669488569a017f0ea35.zip |
8.9
Diffstat (limited to 'wx+/popup_dlg.cpp')
-rwxr-xr-x[-rw-r--r--] | wx+/popup_dlg.cpp | 614 |
1 files changed, 302 insertions, 312 deletions
diff --git a/wx+/popup_dlg.cpp b/wx+/popup_dlg.cpp index f96884d9..dca93658 100644..100755 --- a/wx+/popup_dlg.cpp +++ b/wx+/popup_dlg.cpp @@ -1,312 +1,302 @@ -// ***************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 * -// * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved * -// ***************************************************************************** - -#include "popup_dlg.h" -#include <wx/app.h> -#include <wx/display.h> -#include <wx+/std_button_layout.h> -#include <wx+/font_size.h> -#include <wx+/image_resources.h> -#include "popup_dlg_generated.h" - -#ifdef ZEN_WIN - #include <wx+/mouse_move_dlg.h> -#endif - -using namespace zen; - -namespace -{ -void setAsStandard(wxButton& btn) -{ - btn.SetDefault(); - btn.SetFocus(); -} - - -void setBestInitialSize(wxTextCtrl& ctrl, const wxString& text, wxSize maxSize) -{ - const int scrollbarWidth = 30; - if (maxSize.x <= scrollbarWidth) //implicitly checks for non-zero, too! - return; - maxSize.x -= scrollbarWidth; - - int bestWidth = 0; - int rowCount = 0; - int rowHeight = 0; - - auto evalLineExtent = [&](const wxSize& sz) -> bool //return true when done - { - if (sz.x > bestWidth) - bestWidth = std::min(maxSize.x, sz.x); - - rowCount += (sz.x + maxSize.x - 1) / maxSize.x; //integer round up: consider line-wraps! - rowHeight = std::max(rowHeight, sz.y); //all rows *should* have same height - - return rowCount * rowHeight >= maxSize.y; - }; - - for (auto it = text.begin();;) - { - auto itEnd = std::find(it, text.end(), L'\n'); - wxString line(it, itEnd); - if (line.empty()) - line = L" "; //GetTextExtent() returns (0, 0) for empty strings! - - wxSize sz = ctrl.GetTextExtent(line); //exactly gives row height, but does *not* consider newlines - if (evalLineExtent(sz)) - break; - - if (itEnd == text.end()) - break; - it = itEnd + 1; - } - -#if defined ZEN_WIN || defined ZEN_LINUX - const int rowGap = 0; -#elif defined ZEN_MAC - const int rowGap = 1; -#endif - const wxSize bestSize(bestWidth + scrollbarWidth, std::min(rowCount * (rowHeight + rowGap), maxSize.y)); - ctrl.SetMinSize(bestSize); //alas, SetMinClientSize() is just not working! -} -} - - -class zen::StandardPopupDialog : public PopupDialogGenerated -{ -public: - StandardPopupDialog(wxWindow* parent, DialogInfoType type, const PopupDialogCfg& cfg) : - PopupDialogGenerated(parent), - checkBoxValue_(cfg.checkBoxValue) - { -#ifdef ZEN_WIN - new zen::MouseMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere...; ownership passed to "this" -#endif - wxBitmap iconTmp; - wxString titleTmp; - switch (type) - { - case DialogInfoType::INFO: - //"Information" is meaningless as caption text! - //confirmation doesn't use info icon - //iconTmp = getResourceImage(L"msg_info"); - break; - case DialogInfoType::WARNING: - iconTmp = getResourceImage(L"msg_warning"); - titleTmp = _("Warning"); - break; - case DialogInfoType::ERROR2: - iconTmp = getResourceImage(L"msg_error"); - titleTmp = _("Error"); - break; - } - if (cfg.icon.IsOk()) - iconTmp = cfg.icon; - - if (!cfg.title.empty()) - titleTmp = cfg.title; - //----------------------------------------------- - m_bitmapMsgType->SetBitmap(iconTmp); - - if (titleTmp.empty()) - SetTitle(wxTheApp->GetAppDisplayName()); - else - { - if (parent && parent->IsShownOnScreen()) - SetTitle(titleTmp); - else - SetTitle(wxTheApp->GetAppDisplayName() + L" - " + titleTmp); - } - - int maxWidth = 500; - int maxHeight = 400; //try to determine better value based on actual display resolution: - - if (parent) - { - const int disPos = wxDisplay::GetFromWindow(parent); //window must be visible - if (disPos != wxNOT_FOUND) - maxHeight = wxDisplay(disPos).GetClientArea().GetHeight() * 2 / 3; - } - - assert(!cfg.textMain.empty() || !cfg.textDetail.empty()); - if (!cfg.textMain.empty()) - { - setMainInstructionFont(*m_staticTextMain); - m_staticTextMain->SetLabel(cfg.textMain); - m_staticTextMain->Wrap(maxWidth); //call *after* SetLabel() - } - else - m_staticTextMain->Hide(); - - if (!cfg.textDetail.empty()) - { - const wxString& text = L"\n" + trimCpy(cfg.textDetail) + L"\n"; //add empty top/bottom lines *instead* of using border space! - setBestInitialSize(*m_textCtrlTextDetail, text, wxSize(maxWidth, maxHeight)); - m_textCtrlTextDetail->ChangeValue(text); - } - else - m_textCtrlTextDetail->Hide(); - - if (checkBoxValue_) - { - assert(contains(cfg.checkBoxLabel, L"&")); - m_checkBoxCustom->SetLabel(cfg.checkBoxLabel); - m_checkBoxCustom->SetValue(*checkBoxValue_); - } - else - m_checkBoxCustom->Hide(); - - Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(StandardPopupDialog::OnKeyPressed), nullptr, this); //dialog-specific local key events - } - -private: - void OnClose (wxCloseEvent& event) override { EndModal(static_cast<int>(ConfirmationButton3::CANCEL)); } - void OnCancel(wxCommandEvent& event) override { EndModal(static_cast<int>(ConfirmationButton3::CANCEL)); } - - void OnKeyPressed(wxKeyEvent& event) - { - switch (event.GetKeyCode()) - { - case WXK_RETURN: - case WXK_NUMPAD_ENTER: - { - wxCommandEvent dummy(wxEVT_COMMAND_BUTTON_CLICKED); - OnButtonAffirmative(dummy); - return; - } - - case WXK_ESCAPE: //handle case where cancel button is hidden! - EndModal(static_cast<int>(ConfirmationButton3::CANCEL)); - return; - } - event.Skip(); - } - - void OnButtonAffirmative(wxCommandEvent& event) override - { - if (checkBoxValue_) - *checkBoxValue_ = m_checkBoxCustom->GetValue(); - EndModal(static_cast<int>(ConfirmationButton3::DO_IT)); - } - - void OnButtonNegative(wxCommandEvent& event) override - { - if (checkBoxValue_) - *checkBoxValue_ = m_checkBoxCustom->GetValue(); - EndModal(static_cast<int>(ConfirmationButton3::DONT_DO_IT)); - } - - bool* checkBoxValue_; -}; - - -namespace -{ -class NotificationDialog : public StandardPopupDialog -{ -public: - NotificationDialog(wxWindow* parent, DialogInfoType type, const PopupDialogCfg& cfg) : - StandardPopupDialog(parent, type, cfg) - { - m_buttonAffirmative->SetLabel(_("Close")); //UX Guide: use "Close" for errors, warnings and windows in which users can't make changes (no ampersand!) - m_buttonNegative->Hide(); - m_buttonCancel->Hide(); - - //set std order after button visibility was set - setStandardButtonLayout(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonAffirmative)); - setAsStandard(*m_buttonAffirmative); - GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() - Center(); //needs to be re-applied after a dialog size change! - } -}; - - -class ConfirmationDialog : public StandardPopupDialog -{ -public: - ConfirmationDialog(wxWindow* parent, DialogInfoType type, const PopupDialogCfg& cfg, const wxString& labelDoIt) : - StandardPopupDialog(parent, type, cfg) - { - assert(contains(labelDoIt, L"&")); - m_buttonAffirmative->SetLabel(labelDoIt); - m_buttonNegative->Hide(); - - //set std order after button visibility was set - setStandardButtonLayout(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonAffirmative).setCancel(m_buttonCancel)); - setAsStandard(*m_buttonAffirmative); - GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() - Center(); //needs to be re-applied after a dialog size change! - } -}; -} - -class zen::ConfirmationDialog3 : public StandardPopupDialog -{ -public: - ConfirmationDialog3(wxWindow* parent, DialogInfoType type, const PopupDialogCfg3& cfg, const wxString& labelDoIt, const wxString& labelDontDoIt) : - StandardPopupDialog(parent, type, cfg.pdCfg_), - buttonToDisableWhenChecked_(cfg.buttonToDisableWhenChecked_) - { - assert(contains(labelDoIt, L"&")); - assert(contains(labelDontDoIt, L"&")); - m_buttonAffirmative->SetLabel(labelDoIt); - m_buttonNegative ->SetLabel(labelDontDoIt); - - //m_buttonAffirmative->SetId(wxID_IGNORE); -> setting id after button creation breaks "mouse snap to" functionality - //m_buttonNegative ->SetId(wxID_RETRY); -> also wxWidgets docs seem to hide some info: "Normally, the identifier should be provided on creation and should not be modified subsequently." - - updateGui(); - - //set std order after button visibility was set - setStandardButtonLayout(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonAffirmative).setNegative(m_buttonNegative).setCancel(m_buttonCancel)); - setAsStandard(*m_buttonAffirmative); - GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() - Center(); //needs to be re-applied after a dialog size change! - } - -private: - void OnCheckBoxClick(wxCommandEvent& event) override { updateGui(); event.Skip(); } - - void updateGui() - { - switch (buttonToDisableWhenChecked_) - { - case ConfirmationButton3::DO_IT: - m_buttonAffirmative->Enable(!m_checkBoxCustom->GetValue()); - break; - case ConfirmationButton3::DONT_DO_IT: - m_buttonNegative->Enable(!m_checkBoxCustom->GetValue()); - break; - case ConfirmationButton3::CANCEL: - break; - } - } - - const ConfirmationButton3 buttonToDisableWhenChecked_; -}; - -//######################################################################################## - -void zen::showNotificationDialog(wxWindow* parent, DialogInfoType type, const PopupDialogCfg& cfg) -{ - NotificationDialog dlg(parent, type, cfg); - dlg.ShowModal(); -} - - -ConfirmationButton zen::showConfirmationDialog(wxWindow* parent, DialogInfoType type, const PopupDialogCfg& cfg, const wxString& labelDoIt) -{ - ConfirmationDialog dlg(parent, type, cfg, labelDoIt); - return static_cast<ConfirmationButton>(dlg.ShowModal()); -} - - -ConfirmationButton3 zen::showConfirmationDialog3(wxWindow* parent, DialogInfoType type, const PopupDialogCfg3& cfg, const wxString& labelDoIt, const wxString& labelDontDoIt) -{ - ConfirmationDialog3 dlg(parent, type, cfg, labelDoIt, labelDontDoIt); - return static_cast<ConfirmationButton3>(dlg.ShowModal()); -} +// *****************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 *
+// * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved *
+// *****************************************************************************
+
+#include "popup_dlg.h"
+#include <wx/app.h>
+#include <wx/display.h>
+#include <wx+/std_button_layout.h>
+#include <wx+/font_size.h>
+#include <wx+/image_resources.h>
+#include "popup_dlg_generated.h"
+
+
+using namespace zen;
+
+namespace
+{
+void setAsStandard(wxButton& btn)
+{
+ btn.SetDefault();
+ btn.SetFocus();
+}
+
+
+void setBestInitialSize(wxTextCtrl& ctrl, const wxString& text, wxSize maxSize)
+{
+ const int scrollbarWidth = 30;
+ if (maxSize.x <= scrollbarWidth) //implicitly checks for non-zero, too!
+ return;
+ maxSize.x -= scrollbarWidth;
+
+ int bestWidth = 0;
+ int rowCount = 0;
+ int rowHeight = 0;
+
+ auto evalLineExtent = [&](const wxSize& sz) -> bool //return true when done
+ {
+ if (sz.x > bestWidth)
+ bestWidth = std::min(maxSize.x, sz.x);
+
+ rowCount += (sz.x + maxSize.x - 1) / maxSize.x; //integer round up: consider line-wraps!
+ rowHeight = std::max(rowHeight, sz.y); //all rows *should* have same height
+
+ return rowCount * rowHeight >= maxSize.y;
+ };
+
+ for (auto it = text.begin();;)
+ {
+ auto itEnd = std::find(it, text.end(), L'\n');
+ wxString line(it, itEnd);
+ if (line.empty())
+ line = L" "; //GetTextExtent() returns (0, 0) for empty strings!
+
+ wxSize sz = ctrl.GetTextExtent(line); //exactly gives row height, but does *not* consider newlines
+ if (evalLineExtent(sz))
+ break;
+
+ if (itEnd == text.end())
+ break;
+ it = itEnd + 1;
+ }
+
+ const int rowGap = 0;
+ const wxSize bestSize(bestWidth + scrollbarWidth, std::min(rowCount * (rowHeight + rowGap), maxSize.y));
+ ctrl.SetMinSize(bestSize); //alas, SetMinClientSize() is just not working!
+}
+}
+
+
+class zen::StandardPopupDialog : public PopupDialogGenerated
+{
+public:
+ StandardPopupDialog(wxWindow* parent, DialogInfoType type, const PopupDialogCfg& cfg) :
+ PopupDialogGenerated(parent),
+ checkBoxValue_(cfg.checkBoxValue)
+ {
+ wxBitmap iconTmp;
+ wxString titleTmp;
+ switch (type)
+ {
+ case DialogInfoType::INFO:
+ //"Information" is meaningless as caption text!
+ //confirmation doesn't use info icon
+ //iconTmp = getResourceImage(L"msg_info");
+ break;
+ case DialogInfoType::WARNING:
+ iconTmp = getResourceImage(L"msg_warning");
+ titleTmp = _("Warning");
+ break;
+ case DialogInfoType::ERROR2:
+ iconTmp = getResourceImage(L"msg_error");
+ titleTmp = _("Error");
+ break;
+ }
+ if (cfg.icon.IsOk())
+ iconTmp = cfg.icon;
+
+ if (!cfg.title.empty())
+ titleTmp = cfg.title;
+ //-----------------------------------------------
+ m_bitmapMsgType->SetBitmap(iconTmp);
+
+ if (titleTmp.empty())
+ SetTitle(wxTheApp->GetAppDisplayName());
+ else
+ {
+ if (parent && parent->IsShownOnScreen())
+ SetTitle(titleTmp);
+ else
+ SetTitle(wxTheApp->GetAppDisplayName() + L" - " + titleTmp);
+ }
+
+ int maxWidth = 500;
+ int maxHeight = 400; //try to determine better value based on actual display resolution:
+
+ if (parent)
+ {
+ const int disPos = wxDisplay::GetFromWindow(parent); //window must be visible
+ if (disPos != wxNOT_FOUND)
+ maxHeight = wxDisplay(disPos).GetClientArea().GetHeight() * 2 / 3;
+ }
+
+ assert(!cfg.textMain.empty() || !cfg.textDetail.empty());
+ if (!cfg.textMain.empty())
+ {
+ setMainInstructionFont(*m_staticTextMain);
+ m_staticTextMain->SetLabel(cfg.textMain);
+ m_staticTextMain->Wrap(maxWidth); //call *after* SetLabel()
+ }
+ else
+ m_staticTextMain->Hide();
+
+ if (!cfg.textDetail.empty())
+ {
+ const wxString& text = L"\n" + trimCpy(cfg.textDetail) + L"\n"; //add empty top/bottom lines *instead* of using border space!
+ setBestInitialSize(*m_textCtrlTextDetail, text, wxSize(maxWidth, maxHeight));
+ m_textCtrlTextDetail->ChangeValue(text);
+ }
+ else
+ m_textCtrlTextDetail->Hide();
+
+ if (checkBoxValue_)
+ {
+ assert(contains(cfg.checkBoxLabel, L"&"));
+ m_checkBoxCustom->SetLabel(cfg.checkBoxLabel);
+ m_checkBoxCustom->SetValue(*checkBoxValue_);
+ }
+ else
+ m_checkBoxCustom->Hide();
+
+ Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(StandardPopupDialog::OnKeyPressed), nullptr, this); //dialog-specific local key events
+ }
+
+private:
+ void OnClose (wxCloseEvent& event) override { EndModal(static_cast<int>(ConfirmationButton3::CANCEL)); }
+ void OnCancel(wxCommandEvent& event) override { EndModal(static_cast<int>(ConfirmationButton3::CANCEL)); }
+
+ void OnKeyPressed(wxKeyEvent& event)
+ {
+ switch (event.GetKeyCode())
+ {
+ case WXK_RETURN:
+ case WXK_NUMPAD_ENTER:
+ {
+ wxCommandEvent dummy(wxEVT_COMMAND_BUTTON_CLICKED);
+ OnButtonAffirmative(dummy);
+ return;
+ }
+
+ case WXK_ESCAPE: //handle case where cancel button is hidden!
+ EndModal(static_cast<int>(ConfirmationButton3::CANCEL));
+ return;
+ }
+ event.Skip();
+ }
+
+ void OnButtonAffirmative(wxCommandEvent& event) override
+ {
+ if (checkBoxValue_)
+ *checkBoxValue_ = m_checkBoxCustom->GetValue();
+ EndModal(static_cast<int>(ConfirmationButton3::DO_IT));
+ }
+
+ void OnButtonNegative(wxCommandEvent& event) override
+ {
+ if (checkBoxValue_)
+ *checkBoxValue_ = m_checkBoxCustom->GetValue();
+ EndModal(static_cast<int>(ConfirmationButton3::DONT_DO_IT));
+ }
+
+ bool* checkBoxValue_;
+};
+
+
+namespace
+{
+class NotificationDialog : public StandardPopupDialog
+{
+public:
+ NotificationDialog(wxWindow* parent, DialogInfoType type, const PopupDialogCfg& cfg) :
+ StandardPopupDialog(parent, type, cfg)
+ {
+ m_buttonAffirmative->SetLabel(_("Close")); //UX Guide: use "Close" for errors, warnings and windows in which users can't make changes (no ampersand!)
+ m_buttonNegative->Hide();
+ m_buttonCancel->Hide();
+
+ //set std order after button visibility was set
+ setStandardButtonLayout(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonAffirmative));
+ setAsStandard(*m_buttonAffirmative);
+ GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize()
+ Center(); //needs to be re-applied after a dialog size change!
+ }
+};
+
+
+class ConfirmationDialog : public StandardPopupDialog
+{
+public:
+ ConfirmationDialog(wxWindow* parent, DialogInfoType type, const PopupDialogCfg& cfg, const wxString& labelDoIt) :
+ StandardPopupDialog(parent, type, cfg)
+ {
+ assert(contains(labelDoIt, L"&"));
+ m_buttonAffirmative->SetLabel(labelDoIt);
+ m_buttonNegative->Hide();
+
+ //set std order after button visibility was set
+ setStandardButtonLayout(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonAffirmative).setCancel(m_buttonCancel));
+ setAsStandard(*m_buttonAffirmative);
+ GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize()
+ Center(); //needs to be re-applied after a dialog size change!
+ }
+};
+}
+
+class zen::ConfirmationDialog3 : public StandardPopupDialog
+{
+public:
+ ConfirmationDialog3(wxWindow* parent, DialogInfoType type, const PopupDialogCfg3& cfg, const wxString& labelDoIt, const wxString& labelDontDoIt) :
+ StandardPopupDialog(parent, type, cfg.pdCfg_),
+ buttonToDisableWhenChecked_(cfg.buttonToDisableWhenChecked_)
+ {
+ assert(contains(labelDoIt, L"&"));
+ assert(contains(labelDontDoIt, L"&"));
+ m_buttonAffirmative->SetLabel(labelDoIt);
+ m_buttonNegative ->SetLabel(labelDontDoIt);
+
+ //m_buttonAffirmative->SetId(wxID_IGNORE); -> setting id after button creation breaks "mouse snap to" functionality
+ //m_buttonNegative ->SetId(wxID_RETRY); -> also wxWidgets docs seem to hide some info: "Normally, the identifier should be provided on creation and should not be modified subsequently."
+
+ updateGui();
+
+ //set std order after button visibility was set
+ setStandardButtonLayout(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonAffirmative).setNegative(m_buttonNegative).setCancel(m_buttonCancel));
+ setAsStandard(*m_buttonAffirmative);
+ GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize()
+ Center(); //needs to be re-applied after a dialog size change!
+ }
+
+private:
+ void OnCheckBoxClick(wxCommandEvent& event) override { updateGui(); event.Skip(); }
+
+ void updateGui()
+ {
+ switch (buttonToDisableWhenChecked_)
+ {
+ case ConfirmationButton3::DO_IT:
+ m_buttonAffirmative->Enable(!m_checkBoxCustom->GetValue());
+ break;
+ case ConfirmationButton3::DONT_DO_IT:
+ m_buttonNegative->Enable(!m_checkBoxCustom->GetValue());
+ break;
+ case ConfirmationButton3::CANCEL:
+ break;
+ }
+ }
+
+ const ConfirmationButton3 buttonToDisableWhenChecked_;
+};
+
+//########################################################################################
+
+void zen::showNotificationDialog(wxWindow* parent, DialogInfoType type, const PopupDialogCfg& cfg)
+{
+ NotificationDialog dlg(parent, type, cfg);
+ dlg.ShowModal();
+}
+
+
+ConfirmationButton zen::showConfirmationDialog(wxWindow* parent, DialogInfoType type, const PopupDialogCfg& cfg, const wxString& labelDoIt)
+{
+ ConfirmationDialog dlg(parent, type, cfg, labelDoIt);
+ return static_cast<ConfirmationButton>(dlg.ShowModal());
+}
+
+
+ConfirmationButton3 zen::showConfirmationDialog3(wxWindow* parent, DialogInfoType type, const PopupDialogCfg3& cfg, const wxString& labelDoIt, const wxString& labelDontDoIt)
+{
+ ConfirmationDialog3 dlg(parent, type, cfg, labelDoIt, labelDontDoIt);
+ return static_cast<ConfirmationButton3>(dlg.ShowModal());
+}
|