summaryrefslogtreecommitdiff
path: root/wx+
diff options
context:
space:
mode:
authorB Stack <bgstack15@gmail.com>2020-05-17 11:17:28 -0400
committerB Stack <bgstack15@gmail.com>2020-05-17 11:17:28 -0400
commitf0f3f094c5fa05bafe1963d1ea13f1be39a6673b (patch)
tree1f52055b2f26fc2389d3ab4eb8d8d1e234a6316a /wx+
parentMerge branch '10.23' into 'master' (diff)
downloadFreeFileSync-f0f3f094c5fa05bafe1963d1ea13f1be39a6673b.tar.gz
FreeFileSync-f0f3f094c5fa05bafe1963d1ea13f1be39a6673b.tar.bz2
FreeFileSync-f0f3f094c5fa05bafe1963d1ea13f1be39a6673b.zip
add upstream 10.24
Diffstat (limited to 'wx+')
-rw-r--r--wx+/choice_enum.h54
-rw-r--r--wx+/dc.h12
-rw-r--r--wx+/focus.h12
-rw-r--r--wx+/image_resources.cpp95
-rw-r--r--wx+/image_resources.h7
-rw-r--r--wx+/popup_dlg.cpp34
-rw-r--r--wx+/popup_dlg_generated.h1
-rw-r--r--wx+/taskbar.cpp19
-rw-r--r--wx+/taskbar.h42
9 files changed, 195 insertions, 81 deletions
diff --git a/wx+/choice_enum.h b/wx+/choice_enum.h
index f2c93927..e11b9991 100644
--- a/wx+/choice_enum.h
+++ b/wx+/choice_enum.h
@@ -7,6 +7,7 @@
#ifndef CHOICE_ENUM_H_132413545345687
#define CHOICE_ENUM_H_132413545345687
+#include <unordered_map>
#include <vector>
#include <wx/choice.h>
@@ -43,8 +44,11 @@ struct EnumDescrList
descrList.push_back({ value, { text, tooltip } });
return *this;
}
+
using DescrList = std::vector<std::pair<Enum, std::pair<wxString, wxString>>>;
DescrList descrList;
+
+ std::unordered_map<const wxChoice*, std::vector<wxString>> itemsSetLast;
};
template <class Enum> void setEnumVal(const EnumDescrList<Enum>& mapping, wxChoice& ctrl, Enum value);
template <class Enum> Enum getEnumVal(const EnumDescrList<Enum>& mapping, const wxChoice& ctrl);
@@ -65,26 +69,34 @@ template <class Enum> void updateTooltipEnumVal(const EnumDescrList<Enum>& mappi
//--------------- impelementation -------------------------------------------
template <class Enum>
-void setEnumVal(const EnumDescrList<Enum>& mapping, wxChoice& ctrl, Enum value)
+void setEnumVal(EnumDescrList<Enum>& mapping, wxChoice& ctrl, Enum value)
{
- ctrl.Clear();
+ auto& itemsSetLast = mapping.itemsSetLast[&ctrl];
- int selectedPos = 0;
+ std::vector<wxString> items;
for (auto it = mapping.descrList.begin(); it != mapping.descrList.end(); ++it)
+ items.push_back(it->second.first);
+
+ if (items != itemsSetLast)
{
- ctrl.Append(it->second.first);
- if (it->first == value)
- {
- selectedPos = it - mapping.descrList.begin();
-
- if (it->second.second.empty())
- ctrl.UnsetToolTip();
- else
- ctrl.SetToolTip(it->second.second);
- }
+ ctrl.Set(items); //expensive as fuck! => only call when absolutely needed!
+ itemsSetLast = std::move(items);
}
+ //-----------------------------------------------------------------
- ctrl.SetSelection(selectedPos);
+ const auto it = std::find_if(mapping.descrList.begin(), mapping.descrList.end(), [&](const auto& mapItem) { return mapItem.first == value; });
+ if (it != mapping.descrList.end())
+ {
+ if (const wxString& tooltip = it->second.second;
+ !tooltip.empty())
+ ctrl.SetToolTip(tooltip);
+ else
+ ctrl.UnsetToolTip();
+
+ const int selectedPos = it - mapping.descrList.begin();
+ ctrl.SetSelection(selectedPos);
+ }
+ else assert(false);
}
template <class Enum>
@@ -103,11 +115,17 @@ Enum getEnumVal(const EnumDescrList<Enum>& mapping, const wxChoice& ctrl)
template <class Enum> void updateTooltipEnumVal(const EnumDescrList<Enum>& mapping, wxChoice& ctrl)
{
- const Enum currentValue = getEnumVal(mapping, ctrl);
+ const int selectedPos = ctrl.GetSelection();
- for (const auto& [enumValue, textAndTooltip] : mapping.descrList)
- if (currentValue == enumValue)
- ctrl.SetToolTip(textAndTooltip.second);
+ if (0 <= selectedPos && selectedPos < static_cast<int>(mapping.descrList.size()))
+ {
+ if (const auto& [text, tooltip] = mapping.descrList[selectedPos].second;
+ !tooltip.empty())
+ ctrl.SetToolTip(tooltip);
+ else
+ ctrl.UnsetToolTip();
+ }
+ else assert(false);
}
}
diff --git a/wx+/dc.h b/wx+/dc.h
index 757942ca..f1b067ac 100644
--- a/wx+/dc.h
+++ b/wx+/dc.h
@@ -73,8 +73,8 @@ class RecursiveDcClipper
public:
RecursiveDcClipper(wxDC& dc, const wxRect& r) : dc_(dc)
{
- auto it = refDcToAreaMap().find(&dc);
- if (it != refDcToAreaMap().end())
+ auto it = clippingAreas.find(&dc);
+ if (it != clippingAreas.end())
{
oldRect_ = it->second;
@@ -86,7 +86,7 @@ public:
else
{
dc_.SetClippingRegion(r);
- refDcToAreaMap().emplace(&dc_, r);
+ clippingAreas.emplace(&dc_, r);
}
}
@@ -96,15 +96,15 @@ public:
if (oldRect_)
{
dc_.SetClippingRegion(*oldRect_);
- refDcToAreaMap()[&dc_] = *oldRect_;
+ clippingAreas[&dc_] = *oldRect_;
}
else
- refDcToAreaMap().erase(&dc_);
+ clippingAreas.erase(&dc_);
}
private:
//associate "active" clipping area with each DC
- static std::unordered_map<wxDC*, wxRect>& refDcToAreaMap() { static std::unordered_map<wxDC*, wxRect> clippingAreas; return clippingAreas; }
+ inline static std::unordered_map<wxDC*, wxRect> clippingAreas;
std::optional<wxRect> oldRect_;
wxDC& dc_;
diff --git a/wx+/focus.h b/wx+/focus.h
index 4ba5f3f5..297d0754 100644
--- a/wx+/focus.h
+++ b/wx+/focus.h
@@ -24,6 +24,18 @@ bool isComponentOf(const wxWindow* child, const wxWindow* top)
inline
+wxWindow& getRootWindow(wxWindow& child)
+{
+ wxWindow* root = &child;
+ for (;;)
+ if (wxWindow* parent = root->GetParent())
+ root = parent;
+ else
+ return *root;
+}
+
+
+inline
wxTopLevelWindow* getTopLevelWindow(wxWindow* child)
{
for (wxWindow* wnd = child; wnd != nullptr; wnd = wnd->GetParent())
diff --git a/wx+/image_resources.cpp b/wx+/image_resources.cpp
index 255a352e..5328b845 100644
--- a/wx+/image_resources.cpp
+++ b/wx+/image_resources.cpp
@@ -83,21 +83,21 @@ ImageHolder dpiScale(int width, int height, int dpiWidth, int dpiHeight, const u
}
-auto getScalerTask(const wxString& name, const wxImage& img, int hqScale, Protected<std::vector<std::pair<std::wstring, ImageHolder>>>& result)
+auto getScalerTask(const std::string& imageName, const wxImage& img, int hqScale, Protected<std::vector<std::pair<std::string, ImageHolder>>>& result)
{
- return [name = copyStringTo<std::wstring>(name), //don't trust wxString to be thread-safe like an int
- width = img.GetWidth(),
- height = img.GetHeight(),
- dpiWidth = fastFromDIP(img.GetWidth()),
- dpiHeight = fastFromDIP(img.GetHeight()), //don't call (wxWidgets function!) fastFromDIP() from worker thread
- rgb = img.GetData(),
- alpha = img.GetAlpha(),
- hqScale, &result]
+ return [imageName,
+ width = img.GetWidth(),
+ height = img.GetHeight(),
+ dpiWidth = fastFromDIP(img.GetWidth()),
+ dpiHeight = fastFromDIP(img.GetHeight()), //don't call (wxWidgets function!) fastFromDIP() from worker thread
+ rgb = img.GetData(),
+ alpha = img.GetAlpha(),
+ hqScale, &result]
{
ImageHolder ih = dpiScale(width, height,
dpiWidth, dpiHeight,
rgb, alpha, hqScale);
- result.access([&](std::vector<std::pair<std::wstring, ImageHolder>>& r) { r.emplace_back(name, std::move(ih)); });
+ result.access([&](std::vector<std::pair<std::string, ImageHolder>>& r) { r.emplace_back(imageName, std::move(ih)); });
};
}
@@ -109,19 +109,19 @@ public:
~DpiParallelScaler() { threadGroup_ = {}; } //DpiParallelScaler must out-live threadGroup!!!
- void add(const wxString& name, const wxImage& img)
+ void add(const std::string& imageName, const wxImage& img)
{
imgKeeper_.push_back(img); //retain (ref-counted) wxImage so that the rgb/alpha pointers remain valid after passed to threads
- threadGroup_->run(getScalerTask(name, img, hqScale_, result_));
+ threadGroup_->run(getScalerTask(imageName, img, hqScale_, result_));
}
- std::map<wxString, wxBitmap> waitAndGetResult()
+ std::map<std::string, wxBitmap> waitAndGetResult()
{
threadGroup_->wait();
- std::map<wxString, wxBitmap> output;
+ std::map<std::string, wxBitmap> output;
- result_.access([&](std::vector<std::pair<std::wstring, ImageHolder>>& r)
+ result_.access([&](std::vector<std::pair<std::string, ImageHolder>>& r)
{
for (auto& [imageName, ih] : r)
{
@@ -137,7 +137,7 @@ public:
private:
const int hqScale_;
std::vector<wxImage> imgKeeper_;
- Protected<std::vector<std::pair<std::wstring, ImageHolder>>> result_;
+ Protected<std::vector<std::pair<std::string, ImageHolder>>> result_;
using TaskType = FunctionReturnTypeT<decltype(&getScalerTask)>;
std::optional<ThreadGroup<TaskType>> threadGroup_{ ThreadGroup<TaskType>(std::max<int>(std::thread::hardware_concurrency(), 1), "xBRZ Scaler") };
@@ -169,25 +169,25 @@ public:
dpiScaler_.reset();
}
- const wxBitmap& getImage (const wxString& name);
- const wxAnimation& getAnimation(const wxString& name) const;
+ const wxBitmap& getImage (const std::string& name);
+ const wxAnimation& getAnimation(const std::string& name) const;
private:
GlobalBitmaps (const GlobalBitmaps&) = delete;
GlobalBitmaps& operator=(const GlobalBitmaps&) = delete;
- std::map<wxString, wxBitmap> bitmaps_;
- std::map<wxString, wxAnimation> anims_;
+ std::map<std::string, wxBitmap> bitmaps_;
+ std::map<std::string, wxAnimation> anims_;
std::unique_ptr<DpiParallelScaler> dpiScaler_;
};
-void GlobalBitmaps::init(const Zstring& zipPath)
+void GlobalBitmaps::init(const Zstring& zipPath) //throw FileError
{
assert(bitmaps_.empty() && anims_.empty());
- std::vector<std::pair<wxString /*file name*/, std::string /*byte stream*/>> streams;
+ std::vector<std::pair<Zstring /*file name*/, std::string /*byte stream*/>> streams;
try //to load from ZIP first:
{
@@ -199,7 +199,7 @@ void GlobalBitmaps::init(const Zstring& zipPath)
while (const auto& entry = std::unique_ptr<wxZipEntry>(zipStream.GetNextEntry())) //take ownership!
if (std::string stream(entry->GetSize(), '\0'); !stream.empty() && zipStream.ReadAll(&stream[0], stream.size()))
- streams.emplace_back(entry->GetName(), std::move(stream));
+ streams.emplace_back(utfTo<Zstring>(entry->GetName()), std::move(stream));
else
assert(false);
}
@@ -208,13 +208,11 @@ void GlobalBitmaps::init(const Zstring& zipPath)
traverseFolder(beforeLast(zipPath, Zstr(".zip"), IF_MISSING_RETURN_NONE), [&](const FileInfo& fi)
{
if (endsWith(fi.fullPath, Zstr(".png")))
- try
- {
- std::string stream = loadBinContainer<std::string>(fi.fullPath, nullptr /*notifyUnbufferedIO*/); //throw FileError
- streams.emplace_back(utfTo<wxString>(fi.itemName), std::move(stream));
- }
- catch (FileError&) { assert(false); }
- }, nullptr, nullptr, [](const std::wstring& errorMsg) { assert(false); }); //errors are not really critical in this context
+ {
+ std::string stream = loadBinContainer<std::string>(fi.fullPath, nullptr /*notifyUnbufferedIO*/); //throw FileError
+ streams.emplace_back(fi.itemName, std::move(stream));
+ }
+ }, nullptr, nullptr, [](const std::wstring& errorMsg) { throw FileError(errorMsg); });
}
//--------------------------------------------------------------------
@@ -228,12 +226,11 @@ void GlobalBitmaps::init(const Zstring& zipPath)
dpiScaler_ = std::make_unique<DpiParallelScaler>(hqScale);
for (const auto& [fileName, stream] : streams)
- {
- wxMemoryInputStream wxstream(stream.c_str(), stream.size()); //stream does not take ownership of data
- //bonus: work around wxWidgets bug: wxAnimation::Load() requires seekable input stream (zip-input stream is not seekable)
-
- if (endsWith(fileName, L".png"))
+ if (endsWith(fileName, Zstr(".png")))
{
+ wxMemoryInputStream wxstream(stream.c_str(), stream.size()); //stream does not take ownership of data
+ //bonus: work around wxWidgets bug: wxAnimation::Load() requires seekable input stream (zip-input stream is not seekable)
+
wxImage img(wxstream, wxBITMAP_TYPE_PNG);
assert(img.IsOk());
@@ -241,13 +238,17 @@ void GlobalBitmaps::init(const Zstring& zipPath)
//=> there's only one type of wxImage: with alpha channel, no mask!!!
convertToVanillaImage(img);
+ const std::string imageName = utfTo<std::string>(beforeLast(fileName, Zstr("."), IF_MISSING_RETURN_NONE));
if (dpiScaler_)
- dpiScaler_->add(fileName, img); //scale in parallel!
+ dpiScaler_->add(imageName, img); //scale in parallel!
else
- bitmaps_.emplace(fileName, img);
+ bitmaps_.emplace(imageName, img);
+
+ //alternative: wxBitmap::NewFromPNGData(stream.c_str(), stream.size())?
+ // => Windows: just a (slow!) wrapper for wxBitmpat(wxImage())!
}
#if 0
- else if (endsWith(name, L".gif"))
+ else if (endsWith(fileName, Zstr(".gif")))
{
[[maybe_unused]] const bool loadSuccess = anims_[fileName].Load(wxstream, wxANIMATION_TYPE_GIF);
assert(loadSuccess);
@@ -255,11 +256,10 @@ void GlobalBitmaps::init(const Zstring& zipPath)
#endif
else
assert(false);
- }
}
-const wxBitmap& GlobalBitmaps::getImage(const wxString& name)
+const wxBitmap& GlobalBitmaps::getImage(const std::string& name)
{
//test: this function is first called about 220ms after GlobalBitmaps::init() has ended
// => should be enough time to finish xBRZ scaling in parallel (which takes 50ms)
@@ -270,18 +270,19 @@ const wxBitmap& GlobalBitmaps::getImage(const wxString& name)
dpiScaler_.reset();
}
- auto it = bitmaps_.find(contains(name, L'.') ? name : name + L".png"); //assume .png ending if nothing else specified
- if (it != bitmaps_.end())
+ if (auto it = bitmaps_.find(name);
+ it != bitmaps_.end())
return it->second;
+
assert(false);
return wxNullBitmap;
}
-const wxAnimation& GlobalBitmaps::getAnimation(const wxString& name) const
+const wxAnimation& GlobalBitmaps::getAnimation(const std::string& name) const
{
- auto it = anims_.find(contains(name, L'.') ? name : name + L".gif");
- if (it != anims_.end())
+ if (auto it = anims_.find(name);
+ it != anims_.end())
return it->second;
assert(false);
return wxNullAnimation;
@@ -307,7 +308,7 @@ void zen::cleanupResourceImages()
}
-const wxBitmap& zen::getResourceImage(const wxString& name)
+const wxBitmap& zen::getResourceImage(const std::string& name)
{
if (std::shared_ptr<GlobalBitmaps> inst = GlobalBitmaps::instance())
return inst->getImage(name);
@@ -316,7 +317,7 @@ const wxBitmap& zen::getResourceImage(const wxString& name)
}
-const wxAnimation& zen::getResourceAnimation(const wxString& name)
+const wxAnimation& zen::getResourceAnimation(const std::string& name)
{
if (std::shared_ptr<GlobalBitmaps> inst = GlobalBitmaps::instance())
return inst->getAnimation(name);
diff --git a/wx+/image_resources.h b/wx+/image_resources.h
index ff1d5648..b996d977 100644
--- a/wx+/image_resources.h
+++ b/wx+/image_resources.h
@@ -14,11 +14,12 @@
namespace zen
{
-void initResourceImages(const Zstring& zipPath); //pass resources .zip file at application startup
+//pass resources .zip file at application startup
+void initResourceImages(const Zstring& zipPath); //throw FileError
void cleanupResourceImages();
-const wxBitmap& getResourceImage (const wxString& name);
-const wxAnimation& getResourceAnimation(const wxString& name);
+const wxBitmap& getResourceImage (const std::string& name);
+const wxAnimation& getResourceAnimation(const std::string& name);
}
#endif //IMAGE_RESOURCES_H_8740257825342532457
diff --git a/wx+/popup_dlg.cpp b/wx+/popup_dlg.cpp
index c677cf57..2011a228 100644
--- a/wx+/popup_dlg.cpp
+++ b/wx+/popup_dlg.cpp
@@ -7,10 +7,11 @@
#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 "font_size.h"
+#include "image_resources.h"
#include "popup_dlg_generated.h"
+#include "std_button_layout.h"
+#include "taskbar.h"
using namespace zen;
@@ -75,6 +76,26 @@ public:
buttonToDisableWhenChecked_(cfg.buttonToDisableWhenChecked)
{
+
+ if (type != DialogInfoType::info)
+ try
+ {
+ taskbar_ = std::make_unique<Taskbar>(parent); //throw TaskbarNotAvailable
+ switch (type)
+ {
+ case DialogInfoType::info:
+ break;
+ case DialogInfoType::warning:
+ taskbar_->setStatus(Taskbar::STATUS_WARNING);
+ break;
+ case DialogInfoType::error:
+ taskbar_->setStatus(Taskbar::STATUS_ERROR);
+ break;
+ }
+ }
+ catch (const TaskbarNotAvailable&) {}
+
+
wxBitmap iconTmp;
wxString titleTmp;
switch (type)
@@ -82,14 +103,14 @@ public:
case DialogInfoType::info:
//"Information" is meaningless as caption text!
//confirmation doesn't use info icon
- //iconTmp = getResourceImage(L"msg_info");
+ //iconTmp = getResourceImage("msg_info");
break;
case DialogInfoType::warning:
- iconTmp = getResourceImage(L"msg_warning");
+ iconTmp = getResourceImage("msg_warning");
titleTmp = _("Warning");
break;
case DialogInfoType::error:
- iconTmp = getResourceImage(L"msg_error");
+ iconTmp = getResourceImage("msg_error");
titleTmp = _("Error");
break;
}
@@ -267,6 +288,7 @@ private:
bool* checkBoxValue_;
const QuestionButton2 buttonToDisableWhenChecked_;
+ std::unique_ptr<Taskbar> taskbar_;
};
//########################################################################################
diff --git a/wx+/popup_dlg_generated.h b/wx+/popup_dlg_generated.h
index 2b09289b..33cc4872 100644
--- a/wx+/popup_dlg_generated.h
+++ b/wx+/popup_dlg_generated.h
@@ -68,4 +68,3 @@ public:
~PopupDialogGenerated();
};
-
diff --git a/wx+/taskbar.cpp b/wx+/taskbar.cpp
new file mode 100644
index 00000000..2cc31504
--- /dev/null
+++ b/wx+/taskbar.cpp
@@ -0,0 +1,19 @@
+// *****************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: https://www.gnu.org/licenses/gpl-3.0 *
+// * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved *
+// *****************************************************************************
+
+#include "taskbar.h"
+
+
+using namespace zen;
+
+
+class Taskbar::Impl {};
+
+Taskbar::Taskbar(wxWindow* window) { throw TaskbarNotAvailable(); }
+Taskbar::~Taskbar() {}
+
+void Taskbar::setStatus(Status status) {}
+void Taskbar::setProgress(double fraction) {}
diff --git a/wx+/taskbar.h b/wx+/taskbar.h
new file mode 100644
index 00000000..985d89b4
--- /dev/null
+++ b/wx+/taskbar.h
@@ -0,0 +1,42 @@
+// *****************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: https://www.gnu.org/licenses/gpl-3.0 *
+// * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved *
+// *****************************************************************************
+
+#ifndef TASKBAR_H_98170845709124456
+#define TASKBAR_H_98170845709124456
+
+#include <memory>
+#include <wx/window.h>
+
+
+namespace zen
+{
+class TaskbarNotAvailable {};
+
+class Taskbar
+{
+public:
+ Taskbar(wxWindow* window); //throw TaskbarNotAvailable
+ ~Taskbar();
+
+ enum Status
+ {
+ STATUS_NORMAL,
+ STATUS_INDETERMINATE,
+ STATUS_WARNING,
+ STATUS_ERROR,
+ STATUS_PAUSED
+ };
+
+ void setStatus(Status status); //noexcept
+ void setProgress(double fraction); //between [0, 1]; noexcept
+
+private:
+ class Impl;
+ const std::unique_ptr<Impl> pimpl_;
+};
+}
+
+#endif //TASKBAR_H_98170845709124456
bgstack15