diff options
author | B Stack <bgstack15@gmail.com> | 2020-12-08 13:14:11 +0000 |
---|---|---|
committer | B Stack <bgstack15@gmail.com> | 2020-12-08 13:14:11 +0000 |
commit | 35adf35f7d3b7744d58d7ff27fcaf1bb843060aa (patch) | |
tree | 8e5414c3b8a914f57a1d4dc92ee0e55ae1f6e9ee /wx+/no_flicker.h | |
parent | Merge branch '11.3' into 'master' (diff) | |
parent | add upstream 11.4 (diff) | |
download | FreeFileSync-11.4.tar.gz FreeFileSync-11.4.tar.bz2 FreeFileSync-11.4.zip |
Merge branch '11.4' into 'master'11.4
add upstream 11.4
See merge request opensource-tracking/FreeFileSync!28
Diffstat (limited to 'wx+/no_flicker.h')
-rw-r--r-- | wx+/no_flicker.h | 81 |
1 files changed, 79 insertions, 2 deletions
diff --git a/wx+/no_flicker.h b/wx+/no_flicker.h index 03969c00..53e47bb5 100644 --- a/wx+/no_flicker.h +++ b/wx+/no_flicker.h @@ -7,13 +7,18 @@ #ifndef NO_FLICKER_H_893421590321532 #define NO_FLICKER_H_893421590321532 +#include <zen/string_tools.h> +#include <zen/scope_guard.h> #include <wx/textctrl.h> #include <wx/stattext.h> +#include <wx/richtext/richtextctrl.h> +#include <wx/wupdlock.h> namespace zen { -inline +namespace +{ void setText(wxTextCtrl& control, const wxString& newText, bool* additionalLayoutChange = nullptr) { const wxString& label = control.GetValue(); //perf: don't call twice! @@ -24,7 +29,7 @@ void setText(wxTextCtrl& control, const wxString& newText, bool* additionalLayou control.ChangeValue(newText); } -inline + void setText(wxStaticText& control, wxString newText, bool* additionalLayoutChange = nullptr) { @@ -35,6 +40,78 @@ void setText(wxStaticText& control, wxString newText, bool* additionalLayoutChan if (label != newText) control.SetLabel(newText); } + + +void setTextWithUrls(wxRichTextCtrl& richCtrl, const wxString& newText) +{ + enum class BlockType + { + text, + url, + }; + std::vector<std::pair<BlockType, wxString>> blocks; + + for (auto it = newText.begin();;) + { + const wchar_t urlPrefix[] = L"https://"; + const auto itUrl = std::search(it, newText.end(), + urlPrefix, urlPrefix + strLength(urlPrefix)); + if (it != itUrl) + blocks.emplace_back(BlockType::text, wxString(it, itUrl)); + + if (itUrl == newText.end()) + break; + + auto itUrlEnd = std::find_if(itUrl, newText.end(), [](wchar_t c) { return isWhiteSpace(c); }); + blocks.emplace_back(BlockType::url, wxString(itUrl, itUrlEnd)); + it = itUrlEnd; + } + richCtrl.BeginSuppressUndo(); + ZEN_ON_SCOPE_EXIT(richCtrl.EndSuppressUndo()); + + //fix mouse scroll speed: why the FUCK is this even necessary! + richCtrl.SetLineHeight(richCtrl.GetCharHeight()); + + //get rid of margins and space between text blocks/"paragraphs" + richCtrl.SetMargins({0, 0}); + richCtrl.BeginParagraphSpacing(0, 0); + ZEN_ON_SCOPE_EXIT(richCtrl.EndParagraphSpacing()); + + richCtrl.Clear(); + + if (std::any_of(blocks.begin(), blocks.end(), [](const auto& item) { return item.first == BlockType::url; })) + { + wxRichTextAttr urlStyle; + urlStyle.SetTextColour(*wxBLUE); + urlStyle.SetFontUnderlined(true); + + for (const auto& [type, text] : blocks) + switch (type) + { + case BlockType::text: + richCtrl.WriteText(text); + break; + + case BlockType::url: + richCtrl.BeginStyle(urlStyle); + ZEN_ON_SCOPE_EXIT(richCtrl.EndStyle()); + richCtrl.BeginURL(text); + ZEN_ON_SCOPE_EXIT(richCtrl.EndURL()); + richCtrl.WriteText(text); + break; + } + + //register only once! => use a global function pointer, so that Unbind() works correctly: + using LaunchUrlFun = void(*)(wxTextUrlEvent& event); + static const LaunchUrlFun launchUrl = [](wxTextUrlEvent& event) { wxLaunchDefaultBrowser(event.GetString()); }; + + [[maybe_unused]] const bool unbindOk = richCtrl.Unbind(wxEVT_TEXT_URL, launchUrl); + richCtrl.Bind(wxEVT_TEXT_URL, launchUrl); + } + else + richCtrl.WriteText(newText); +} +} } #endif //NO_FLICKER_H_893421590321532 |