summaryrefslogtreecommitdiff
path: root/wx+
diff options
context:
space:
mode:
Diffstat (limited to 'wx+')
-rw-r--r--wx+/popup_dlg.cpp25
-rw-r--r--wx+/popup_dlg.h3
-rw-r--r--wx+/std_button_layout.h61
3 files changed, 62 insertions, 27 deletions
diff --git a/wx+/popup_dlg.cpp b/wx+/popup_dlg.cpp
index 88ed590b..3d4077c3 100644
--- a/wx+/popup_dlg.cpp
+++ b/wx+/popup_dlg.cpp
@@ -6,14 +6,17 @@
#include "popup_dlg.h"
#include <zen/basic_math.h>
+#include <zen/utf.h>
#include <wx/app.h>
#include <wx/display.h>
+#include <wx/sound.h>
#include "no_flicker.h"
#include "font_size.h"
#include "image_resources.h"
#include "popup_dlg_generated.h"
#include "std_button_layout.h"
#include "taskbar.h"
+ #include "window_tools.h"
using namespace zen;
@@ -194,6 +197,27 @@ public:
Bind(wxEVT_CHAR_HOOK, [this](wxKeyEvent& event) { onLocalKeyEvent(event); }); //dialog-specific local key events
+ //play sound reminder when waiting for user confirmation
+ if (!cfg.soundFileAlertPending.empty())
+ {
+ timer_.Bind(wxEVT_TIMER, [this, parent, alertSoundPath = cfg.soundFileAlertPending](wxTimerEvent& event)
+ {
+ //wxWidgets shows modal error dialog by default => "no, wxWidgets, NO!"
+ wxLog* oldLogTarget = wxLog::SetActiveTarget(new wxLogStderr); //transfer and receive ownership!
+ ZEN_ON_SCOPE_EXIT(delete wxLog::SetActiveTarget(oldLogTarget));
+
+ wxSound::Play(utfTo<wxString>(alertSoundPath), wxSOUND_ASYNC);
+
+ RequestUserAttention(wxUSER_ATTENTION_INFO);
+ /* wxUSER_ATTENTION_INFO: flashes window 3 times, unconditionally
+ wxUSER_ATTENTION_ERROR: flashes without limit, but *only* if not in foreground (FLASHW_TIMERNOFG) :( */
+ if (parent)
+ if (auto tlw = dynamic_cast<wxTopLevelWindow*>(&getRootWindow(*parent)))
+ tlw->RequestUserAttention(wxUSER_ATTENTION_INFO); //top-level window needed for the taskbar flash!
+ });
+ timer_.Start(60'000 /*unit: [ms]*/);
+ }
+
//------------------------------------------------------------------------------
StdButtons stdBtns;
stdBtns.setAffirmative(m_buttonAccept);
@@ -312,6 +336,7 @@ private:
bool* checkBoxValue_;
const ConfirmationButton3 buttonToDisableWhenChecked_;
std::unique_ptr<Taskbar> taskbar_;
+ wxTimer timer_;
};
//########################################################################################
diff --git a/wx+/popup_dlg.h b/wx+/popup_dlg.h
index bb7ba51b..11e96e3b 100644
--- a/wx+/popup_dlg.h
+++ b/wx+/popup_dlg.h
@@ -8,6 +8,7 @@
#define POPUP_DLG_H_820780154723456
#include <set>
+#include <zen/zstring.h>
#include <wx/window.h>
#include <wx/bitmap.h>
#include <wx/string.h>
@@ -68,6 +69,7 @@ struct PopupDialogCfg
PopupDialogCfg& setMainInstructions (const wxString& label) { textMain = label; return *this; } //set at least one of these!
PopupDialogCfg& setDetailInstructions(const wxString& label) { textDetail = label; return *this; } //
PopupDialogCfg& disableButton(ConfirmationButton3 button) { disabledButtons.insert(button); return *this; }
+ PopupDialogCfg& remindWhenPending(const Zstring& soundFilePath) { soundFileAlertPending = soundFilePath; return *this; }
PopupDialogCfg& setCheckBox(bool& value, const wxString& label, ConfirmationButton3 disableWhenChecked = ConfirmationButton3::cancel)
{
checkBoxValue = &value;
@@ -84,6 +86,7 @@ private:
wxString textMain;
wxString textDetail;
std::set<ConfirmationButton3> disabledButtons;
+ Zstring soundFileAlertPending;
bool* checkBoxValue = nullptr; //in/out
wxString checkBoxLabel;
ConfirmationButton3 buttonToDisableWhenChecked = ConfirmationButton3::cancel;
diff --git a/wx+/std_button_layout.h b/wx+/std_button_layout.h
index 25745132..e84b0c78 100644
--- a/wx+/std_button_layout.h
+++ b/wx+/std_button_layout.h
@@ -47,6 +47,11 @@ void setStandardButtonLayout(wxBoxSizer& sizer, const StdButtons& buttons)
{
assert(sizer.GetOrientation() == wxHORIZONTAL);
+ //GNOME Human Interface Guidelines: https://developer.gnome.org/hig-book/3.2/hig-book.html#alert-spacing
+ const int spaceH = fastFromDIP( 6); //OK
+ const int spaceRimH = fastFromDIP(12); //OK
+ const int spaceRimV = fastFromDIP(12); //OK
+
StdButtons buttonsTmp = buttons;
auto detach = [&](wxButton*& btn)
@@ -54,15 +59,11 @@ void setStandardButtonLayout(wxBoxSizer& sizer, const StdButtons& buttons)
if (btn)
{
assert(btn->GetContainingSizer() == &sizer);
- if (btn->IsShown())
- {
- bool rv = sizer.Detach(btn);
- assert(rv);
- if (!rv)
- btn = nullptr;
- }
- else
- btn = nullptr;
+ if (btn->IsShown() && sizer.Detach(btn))
+ return;
+
+ assert(false); //why is it hidden!?
+ btn = nullptr;
}
};
@@ -71,10 +72,30 @@ void setStandardButtonLayout(wxBoxSizer& sizer, const StdButtons& buttons)
detach(buttonsTmp.btnNo);
detach(buttonsTmp.btnCancel);
- //GNOME Human Interface Guidelines: https://developer.gnome.org/hig-book/3.2/hig-book.html#alert-spacing
- const int spaceH = fastFromDIP( 6); //OK
- const int spaceRimH = fastFromDIP(12); //OK
- const int spaceRimV = fastFromDIP(12); //OK
+
+ //"All your fixed-size spacers are belong to us!" => have a clean slate: consider repeated setStandardButtonLayout() calls
+ for (size_t pos = sizer.GetItemCount(); pos-- > 0;)
+ if (wxSizerItem& item = *sizer.GetItem(pos);
+ item.IsSpacer() && item.GetProportion() == 0 && item.GetSize().y == 0)
+ {
+ [[maybe_unused]] bool rv = sizer.Detach(pos);
+ assert(rv);
+ }
+
+ //set border on left considering existing items
+ if (!sizer.IsEmpty()) //for yet another retarded reason wxWidgets will have wxSizer::GetItem(0) cause an assert rather than just return nullptr as documented
+ if (wxSizerItem& item = *sizer.GetItem(static_cast<size_t>(0));
+ item.IsShown())
+ {
+ assert(item.GetBorder() <= spaceRimV); //pragmatic check: other controls in the sizer should not have a larger border
+
+ if (const int flag = item.GetFlag();
+ flag & wxLEFT)
+ item.SetFlag(flag & ~wxLEFT);
+
+ sizer.Prepend(spaceRimH, 0);
+ }
+
bool settingFirstButton = true;
auto attach = [&](wxButton* btn)
@@ -93,20 +114,6 @@ void setStandardButtonLayout(wxBoxSizer& sizer, const StdButtons& buttons)
}
};
- //set border on left considering existing items
- if (sizer.GetChildren().GetCount() > 0) //for yet another retarded reason wxWidgets will have wxSizer::GetItem(0) cause an assert rather than just return nullptr as documented
- if (wxSizerItem* item = sizer.GetItem(static_cast<size_t>(0)))
- {
- assert(item->GetBorder() <= spaceRimV); //pragmatic check: other controls in the sizer should not have a larger border
- int flag = item->GetFlag();
- if (flag & wxLEFT)
- {
- flag &= ~wxLEFT;
- item->SetFlag(flag);
- }
- sizer.Insert(static_cast<size_t>(0), spaceRimH, 0);
- }
-
sizer.Add(spaceRimH, 0);
attach(buttonsTmp.btnNo);
attach(buttonsTmp.btnCancel);
bgstack15