diff options
Diffstat (limited to 'wx+/popup_dlg.cpp')
-rwxr-xr-x | wx+/popup_dlg.cpp | 604 |
1 files changed, 302 insertions, 302 deletions
diff --git a/wx+/popup_dlg.cpp b/wx+/popup_dlg.cpp index dca93658..120bf852 100755 --- a/wx+/popup_dlg.cpp +++ b/wx+/popup_dlg.cpp @@ -1,302 +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"
-
-
-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());
-}
+// ***************************************************************************** +// * 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()); +} |