diff options
author | Daniel Wilhelm <shieldwed@outlook.com> | 2019-12-14 15:52:53 +0000 |
---|---|---|
committer | Daniel Wilhelm <shieldwed@outlook.com> | 2019-12-14 15:52:53 +0000 |
commit | cc75e50ca861529d50601d247fd66f806fcb23a8 (patch) | |
tree | e2c5c7b1f98e64011b1ee8ca4e9bb9157510dfe7 /wx+ | |
parent | Merge branch '10.17' into 'master' (diff) | |
parent | add upstream 10.18 (diff) | |
download | FreeFileSync-cc75e50ca861529d50601d247fd66f806fcb23a8.tar.gz FreeFileSync-cc75e50ca861529d50601d247fd66f806fcb23a8.tar.bz2 FreeFileSync-cc75e50ca861529d50601d247fd66f806fcb23a8.zip |
Merge branch '10.18' into 'master'10.18
add upstream 10.18
See merge request opensource-tracking/FreeFileSync!15
Diffstat (limited to 'wx+')
-rw-r--r-- | wx+/async_task.h | 2 | ||||
-rw-r--r-- | wx+/context_menu.h | 5 | ||||
-rw-r--r-- | wx+/dc.h | 2 | ||||
-rw-r--r-- | wx+/font_size.h | 4 | ||||
-rw-r--r-- | wx+/graph.cpp | 13 | ||||
-rw-r--r-- | wx+/grid.cpp | 67 | ||||
-rw-r--r-- | wx+/grid.h | 16 | ||||
-rw-r--r-- | wx+/image_resources.cpp | 109 | ||||
-rw-r--r-- | wx+/image_tools.cpp | 10 | ||||
-rw-r--r-- | wx+/image_tools.h | 4 | ||||
-rw-r--r-- | wx+/rtl.h | 10 | ||||
-rw-r--r-- | wx+/toggle_button.h | 25 |
12 files changed, 150 insertions, 117 deletions
diff --git a/wx+/async_task.h b/wx+/async_task.h index 04eac61c..1599c4d7 100644 --- a/wx+/async_task.h +++ b/wx+/async_task.h @@ -85,7 +85,7 @@ public: std::vector<std::unique_ptr<Task>> readyTasks; //Reentrancy; access to AsyncTasks::add is not protected! => evaluate outside eraseIf - eraseIf(tasks_, [&](std::unique_ptr<Task>& task) + std::erase_if(tasks_, [&](std::unique_ptr<Task>& task) { if (task->resultReady()) { diff --git a/wx+/context_menu.h b/wx+/context_menu.h index d856db03..08a313bf 100644 --- a/wx+/context_menu.h +++ b/wx+/context_menu.h @@ -14,7 +14,7 @@ #include <wx/app.h> /* -A context menu supporting C++11 lambda callbacks! +A context menu supporting lambda callbacks! Usage: ContextMenu menu; @@ -56,7 +56,7 @@ public: void addSeparator() { menu_->AppendSeparator(); } - void addSubmenu(const wxString& label, ContextMenu& submenu, const wxBitmap* bmp = nullptr) //invalidates submenu! + void addSubmenu(const wxString& label, ContextMenu& submenu, const wxBitmap* bmp = nullptr, bool enabled = true) //invalidates submenu! { //transfer submenu commands: commandList_.insert(submenu.commandList_.begin(), submenu.commandList_.end()); @@ -67,6 +67,7 @@ public: wxMenuItem* newItem = new wxMenuItem(menu_.get(), wxID_ANY, label, L"", wxITEM_NORMAL, submenu.menu_.release()); //menu owns item, item owns submenu! if (bmp) newItem->SetBitmap(*bmp); //do not set AFTER appending item! wxWidgets screws up for yet another crappy reason menu_->Append(newItem); + if (!enabled) newItem->Enable(false); } void popup(wxWindow& wnd, const wxPoint& pos = wxDefaultPosition) //show popup menu + process lambdas @@ -56,7 +56,7 @@ int fastFromDIP(int d) //like wxWindow::FromDIP (but tied to primary monitor and #else //https://github.com/wxWidgets/wxWidgets/blob/master/src/common/wincmn.cpp#L2865 static_assert(GTK_MAJOR_VERSION == 2); //GTK2 doesn't properly support high DPI: https://freefilesync.org/forum/viewtopic.php?t=6114 - //=> requires general fix at wxWidgets-level + //=> requires general fix at wxWidgets-level assert(wxTheApp); //only call after wxWidgets was initalized! static const int dpiY = wxScreenDC().GetPPI().y; //perf: buffering for calls to ::GetDeviceCaps() needed!? const int defaultDpi = 96; diff --git a/wx+/font_size.h b/wx+/font_size.h index 2f2d377c..d25dfede 100644 --- a/wx+/font_size.h +++ b/wx+/font_size.h @@ -35,7 +35,7 @@ void setRelativeFontSize(wxWindow& control, double factor) wxFont font = control.GetFont(); font.SetPointSize(numeric::round(wxNORMAL_FONT->GetPointSize() * factor)); control.SetFont(font); -}; +} inline @@ -46,7 +46,7 @@ void setMainInstructionFont(wxWindow& control) font.SetWeight(wxFONTWEIGHT_BOLD); control.SetFont(font); -}; +} } #endif //FONT_SIZE_H_23849632846734343234532 diff --git a/wx+/graph.cpp b/wx+/graph.cpp index aac2cc10..a6d0f19d 100644 --- a/wx+/graph.cpp +++ b/wx+/graph.cpp @@ -151,7 +151,7 @@ void drawXLabel(wxDC& dc, double xMin, double xMax, int blockCount, const Conver return; wxDCPenChanger dummy(dc, wxColor(192, 192, 192)); //light grey => not accessible! but no big deal... - wxDCTextColourChanger dummy2(dc, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); + wxDCTextColourChanger textColor(dc, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); const double valRangePerBlock = (xMax - xMin) / blockCount; @@ -179,7 +179,7 @@ void drawYLabel(wxDC& dc, double yMin, double yMax, int blockCount, const Conver return; wxDCPenChanger dummy(dc, wxColor(192, 192, 192)); //light grey => not accessible! but no big deal... - wxDCTextColourChanger dummy2(dc, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); + wxDCTextColourChanger textColor(dc, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); const double valRangePerBlock = (yMax - yMin) / blockCount; @@ -225,13 +225,12 @@ void drawCornerText(wxDC& dc, const wxRect& graphArea, const wxString& txt, Grap drawPos.y += graphArea.height - boxExtent.GetHeight(); break; } - { + //add text shadow to improve readability: - wxDCTextColourChanger dummy(dc, colorBack); - dc.DrawText(txt, drawPos + border + wxSize(fastFromDIP(1), fastFromDIP(1))); - } + wxDCTextColourChanger textColor(dc, colorBack); + dc.DrawText(txt, drawPos + border + wxSize(fastFromDIP(1), fastFromDIP(1))); - wxDCTextColourChanger dummy(dc, colorText); + textColor.Set(colorText); dc.DrawText(txt, drawPos + border); } diff --git a/wx+/grid.cpp b/wx+/grid.cpp index 851146bc..0613e14f 100644 --- a/wx+/grid.cpp +++ b/wx+/grid.cpp @@ -249,7 +249,7 @@ wxRect GridData::drawColumnLabelBackground(wxDC& dc, const wxRect& rect, bool hi void GridData::drawColumnLabelText(wxDC& dc, const wxRect& rect, const std::wstring& text) { - wxDCTextColourChanger dummy(dc, getColorLabelText()); //accessibility: always set both foreground AND background colors! + wxDCTextColourChanger textColor(dc, getColorLabelText()); //accessibility: always set both foreground AND background colors! drawCellText(dc, rect, text, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); } @@ -452,9 +452,7 @@ public: { wxClientDC dc(this); - wxFont labelFont = GetFont(); - //labelFont.SetWeight(wxFONTWEIGHT_BOLD); - dc.SetFont(labelFont); //harmonize with RowLabelWin::render()! + dc.SetFont(GetFont()); //harmonize with RowLabelWin::render()! int bestWidth = 0; for (ptrdiff_t i = rowFrom; i <= rowTo; ++i) @@ -504,9 +502,7 @@ private: { clearArea(dc, rect, wxSystemSettings::GetColour(/*!renderAsEnabled(*this) ? wxSYS_COLOUR_BTNFACE :*/wxSYS_COLOUR_WINDOW)); - wxFont labelFont = GetFont(); - //labelFont.SetWeight(wxFONTWEIGHT_BOLD); - dc.SetFont(labelFont); //harmonize with RowLabelWin::getBestWidth()! + dc.SetFont(GetFont()); //harmonize with RowLabelWin::getBestWidth()! auto rowRange = getRowsOnClient(rect); //returns range [begin, end) for (auto row = rowRange.first; row < rowRange.second; ++row) @@ -524,7 +520,7 @@ private: { //clearArea(dc, rect, getColorRowLabel()); dc.GradientFillLinear(rect, getColorLabelGradientFrom(), getColorLabelGradientTo(), wxEAST); //clear overlapping cells - wxDCTextColourChanger dummy3(dc, getColorLabelText()); //accessibility: always set both foreground AND background colors! + wxDCTextColourChanger textColor(dc, getColorLabelText()); //accessibility: always set both foreground AND background colors! //label text wxRect textRect = rect; @@ -623,10 +619,10 @@ private: //coordinate with "colLabelHeight" in Grid constructor: wxFont labelFont = GetFont(); - labelFont.SetWeight(wxFONTWEIGHT_BOLD); + labelFont.MakeBold(); dc.SetFont(labelFont); - wxDCTextColourChanger dummy(dc, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); //use user setting for labels + wxDCTextColourChanger textColor(dc, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); //use user setting for labels const int colLabelHeight = refParent().colLabelHeight_; @@ -893,7 +889,7 @@ private: dc.SetFont(GetFont()); //harmonize with Grid::getBestColumnSize() - wxDCTextColourChanger dummy(dc, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); //use user setting for labels + wxDCTextColourChanger textColor(dc, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); //use user setting for labels std::vector<ColumnWidth> absWidths = refParent().getColWidths(); //resolve stretched widths { @@ -1313,7 +1309,7 @@ Grid::Grid(wxWindow* parent, { //coordinate with ColLabelWin::render(): wxFont labelFont = colLabelWin_->GetFont(); - labelFont.SetWeight(wxFONTWEIGHT_BOLD); + labelFont.MakeBold(); return labelFont.GetPixelSize().GetHeight(); }(); @@ -1491,22 +1487,51 @@ wxSize Grid::GetSizeAvailableForScrollTarget(const wxSize& size) }(); //2. try(!) to determine scrollbar sizes: +#if GTK_MAJOR_VERSION == 2 + /* Ubuntu 19.10: "scrollbar-spacing" has a default value of 3: https://developer.gnome.org/gtk2/stable/GtkScrolledWindow.html#GtkScrolledWindow--s-scrollbar-spacing + => the default Ubuntu theme (but also our Gtk2Styles.rc) set it to 0, but still the first call to gtk_widget_style_get() returns 3: why? + => maybe styles are applied asynchronously? GetClientSize() is affected by this, so can't use! + => always ignore spacing to get consistent scrollbar dimensions! */ + GtkScrolledWindow* scrollWin = GTK_SCROLLED_WINDOW(wxWindow::m_widget); + assert(scrollWin); + GtkWidget* rangeH = ::gtk_scrolled_window_get_hscrollbar(scrollWin); + GtkWidget* rangeV = ::gtk_scrolled_window_get_vscrollbar(scrollWin); + + GtkRequisition reqH = {}; + GtkRequisition reqV = {}; + if (rangeH) ::gtk_widget_size_request(rangeH, &reqH); + if (rangeV) ::gtk_widget_size_request(rangeV, &reqV); + assert(reqH.width > 0 && reqH.height > 0); + assert(reqV.width > 0 && reqV.height > 0); + + const wxSize scrollBarSizeTmp(reqV.width, reqH.height); + assert(scrollBarHeightH_ == 0 || scrollBarHeightH_ == scrollBarSizeTmp.y); + assert(scrollBarWidthV_ == 0 || scrollBarWidthV_ == scrollBarSizeTmp.x); + +#elif GTK_MAJOR_VERSION == 3 + //scrollbar size increases dynamically on mouse-hover! + //see "overlay scrolling": https://developer.gnome.org/gtk3/stable/GtkScrolledWindow.html#gtk-scrolled-window-set-overlay-scrolling + //luckily "scrollbar-spacing" is stable on GTK3 const wxSize scrollBarSizeTmp = GetSize() - GetClientSize(); - assert(scrollBarHeightH_ == 0 || scrollBarSizeTmp.y == 0 || scrollBarHeightH_ == scrollBarSizeTmp.y); - assert(scrollBarWidthV_ == 0 || scrollBarSizeTmp.x == 0 || scrollBarWidthV_ == scrollBarSizeTmp.x); + + assert(scrollBarSizeTmp.x == 0 || scrollBarSizeTmp.x == 6 || scrollBarSizeTmp.x == 13); //lame hard-coded numbers (from Ubuntu 19.10) + assert(scrollBarSizeTmp.y == 0 || scrollBarSizeTmp.y == 6 || scrollBarSizeTmp.y == 13); //=> but let's have a *close* eye on scrollbar fluctuation! +#else +#error unknown GTK version! +#endif scrollBarHeightH_ = std::max(scrollBarHeightH_, scrollBarSizeTmp.y); scrollBarWidthV_ = std::max(scrollBarWidthV_, scrollBarSizeTmp.x); //this function is called again by wxScrollHelper::AdjustScrollbars() if SB_SHOW_ALWAYS-scrollbars are not yet shown => scrollbar size > 0 eventually! - + //----------------------------------------------------------------------------- //harmonize with Grid::updateWindowSizes()! wxSize sizeAvail = size - wxSize(rowLabelWidth, colLabelHeight_); //EXCEPTION: space consumed by SB_SHOW_ALWAYS-scrollbars is *never* available for "scroll target"; see wxScrollHelper::AdjustScrollbars() if (showScrollbarH_ == SB_SHOW_ALWAYS) - sizeAvail.y -= scrollBarHeightH_; + sizeAvail.y -= (scrollBarHeightH_ > 0 ? scrollBarHeightH_ : /*fallback:*/ scrollBarWidthV_); if (showScrollbarV_ == SB_SHOW_ALWAYS) - sizeAvail.x -= scrollBarWidthV_; + sizeAvail.x -= (scrollBarWidthV_ > 0 ? scrollBarWidthV_ : /*fallback:*/ scrollBarHeightH_); return wxSize(std::max(0, sizeAvail.x), std::max(0, sizeAvail.y)); @@ -1879,10 +1904,10 @@ void Grid::showScrollBars(Grid::ScrollBarStatus horizontal, Grid::ScrollBarStatu assert(false); return GTK_POLICY_AUTOMATIC; }; - - GtkWidget* gridWidget = wxWindow::m_widget; - GtkScrolledWindow* scrolledWindow = GTK_SCROLLED_WINDOW(gridWidget); - ::gtk_scrolled_window_set_policy(scrolledWindow, + + GtkScrolledWindow* scrollWin = GTK_SCROLLED_WINDOW(wxWindow::m_widget); + assert(scrollWin); + ::gtk_scrolled_window_set_policy(scrollWin, mapStatus(horizontal), mapStatus(vertical)); @@ -333,15 +333,13 @@ private: ColumnType colToType(size_t col) const; //returns ColumnType::NONE on error - /* - Visual layout: - -------------------------------- - |CornerWin | ColLabelWin | - |------------------------------| - |RowLabelWin | MainWin | - | | | - -------------------------------- - */ + /* Grid window layout: + _______________________________ + | CornerWin | ColLabelWin | + |_____________|_______________| + | RowLabelWin | MainWin | + | | | + |_____________|_______________| */ CornerWin* cornerWin_; RowLabelWin* rowLabelWin_; ColLabelWin* colLabelWin_; diff --git a/wx+/image_resources.cpp b/wx+/image_resources.cpp index faabbb2a..91189ba6 100644 --- a/wx+/image_resources.cpp +++ b/wx+/image_resources.cpp @@ -11,10 +11,10 @@ #include <zen/globals.h> #include <zen/perf.h> #include <zen/thread.h> -#include <wx/wfstream.h> +#include <zen/file_io.h> #include <wx/zipstrm.h> -#include <wx/image.h> #include <wx/mstream.h> +#include <wx/image.h> #include <xBRZ/src/xbrz.h> #include <xBRZ/src/xbrz_tools.h> #include "image_tools.h" @@ -143,24 +143,6 @@ private: //hardware_concurrency() == 0 if "not computable or well defined" }; - -void loadAnimFromZip(wxZipInputStream& zipInput, wxAnimation& anim) -{ - //work around wxWidgets bug: - //construct seekable input stream (zip-input stream is not seekable) for wxAnimation::Load() - //luckily this method call is very fast: below measurement precision! - std::vector<std::byte> data; - data.reserve(10000); - - int newValue = 0; - while ((newValue = zipInput.GetC()) != wxEOF) - data.push_back(static_cast<std::byte>(newValue)); - - wxMemoryInputStream seekAbleStream(&data.front(), data.size()); //stream does not take ownership of data - - anim.Load(seekAbleStream, wxANIMATION_TYPE_GIF); -} - //================================================================================================ //================================================================================================ @@ -204,44 +186,59 @@ void GlobalBitmaps::init(const Zstring& filePath) { assert(bitmaps_.empty() && anims_.empty()); - wxFFileInputStream input(utfTo<wxString>(filePath)); - if (input.IsOk()) //if not... we don't want to react too harsh here + //wxFFileInputStream/wxZipInputStream loads in junks of 512 bytes => WTF!!! => implement sane file loading: + try { - //activate support for .png files - wxImage::AddHandler(new wxPNGHandler); //ownership passed - - wxZipInputStream streamIn(input, wxConvUTF8); - //do NOT rely on wxConvLocal! On failure shows unhelpful popup "Cannot convert from the charset 'Unknown encoding (-1)'!" - - //do we need xBRZ scaling for high quality DPI images? - const int hqScale = std::clamp<int>(std::ceil(fastFromDIP(1000) / 1000.0), 1, xbrz::SCALE_FACTOR_MAX); - //even for 125% DPI scaling, "2xBRZ + bilinear downscale" gives a better result than mere "125% bilinear upscale"! - if (hqScale > 1) - dpiScaler_ = std::make_unique<DpiParallelScaler>(hqScale); - - while (const auto& entry = std::unique_ptr<wxZipEntry>(streamIn.GetNextEntry())) //take ownership!) - { - const wxString name = entry->GetName(); - - if (endsWith(name, L".png")) - { - wxImage img(streamIn, wxBITMAP_TYPE_PNG); - - //end this alpha/no-alpha/mask/wxDC::DrawBitmap/RTL/high-contrast-scheme interoperability nightmare here and now!!!! - //=> there's only one type of wxImage: with alpha channel, no mask!!! - convertToVanillaImage(img); - - if (dpiScaler_) - dpiScaler_->add(name, img); //scale in parallel! - else - bitmaps_.emplace(name, img); - } - else if (endsWith(name, L".gif")) - loadAnimFromZip(streamIn, anims_[name]); - else - assert(false); - } + const std::string rawStream = loadBinContainer<std::string>(filePath, nullptr /*notifyUnbufferedIO*/); //throw FileError + wxMemoryInputStream memStream(rawStream.c_str(), rawStream.size()); //does not take ownership + wxZipInputStream zipStream(memStream, wxConvUTF8); + //do NOT rely on wxConvLocal! On failure shows unhelpful popup "Cannot convert from the charset 'Unknown encoding (-1)'!" + + //activate support for .png files + wxImage::AddHandler(new wxPNGHandler); //ownership passed + + //do we need xBRZ scaling for high quality DPI images? + const int hqScale = std::clamp<int>(std::ceil(fastFromDIP(1000) / 1000.0), 1, xbrz::SCALE_FACTOR_MAX); + //even for 125% DPI scaling, "2xBRZ + bilinear downscale" gives a better result than mere "125% bilinear upscale"! + if (hqScale > 1) + dpiScaler_ = std::make_unique<DpiParallelScaler>(hqScale); + + while (const auto& entry = std::unique_ptr<wxZipEntry>(zipStream.GetNextEntry())) //take ownership!) + { + const wxString name = entry->GetName(); + + if (endsWith(name, L".png")) + { + wxImage img(zipStream, wxBITMAP_TYPE_PNG); + assert(img.IsOk()); + + //end this alpha/no-alpha/mask/wxDC::DrawBitmap/RTL/high-contrast-scheme interoperability nightmare here and now!!!! + //=> there's only one type of wxImage: with alpha channel, no mask!!! + convertToVanillaImage(img); + + if (dpiScaler_) + dpiScaler_->add(name, img); //scale in parallel! + else + bitmaps_.emplace(name, img); + } + else if (endsWith(name, L".gif")) + { + //work around wxWidgets bug: wxAnimation::Load() requires seekable input stream (zip-input stream is not seekable) + std::string stream(entry->GetSize(), '\0'); + if (!stream.empty() && zipStream.ReadAll(&stream[0], stream.size())) + { + wxMemoryInputStream seekAbleStream(stream.c_str(), stream.size()); //stream does not take ownership of data + [[maybe_unused]] const bool loadSuccess = anims_[name].Load(seekAbleStream, wxANIMATION_TYPE_GIF); + assert(loadSuccess); + } + else + assert(false); + } + else + assert(false); + } } + catch (FileError&) { assert(false); } } diff --git a/wx+/image_tools.cpp b/wx+/image_tools.cpp index b314e801..0f248057 100644 --- a/wx+/image_tools.cpp +++ b/wx+/image_tools.cpp @@ -203,15 +203,15 @@ wxImage zen::createImageFromText(const wxString& text, const wxFont& font, const } -wxBitmap zen::layOver(const wxBitmap& back, const wxBitmap& front, int alignment) +wxImage zen::layOver(const wxImage& back, const wxImage& front, int alignment) { if (!front.IsOk()) return back; + assert(front.HasAlpha() && back.HasAlpha()); const int width = std::max(back.GetWidth(), front.GetWidth()); const int height = std::max(back.GetHeight(), front.GetHeight()); - assert(front.HasAlpha() == back.HasAlpha()); //we don't support mixed-mode brittleness! - const int offsetX = [&] + const int offsetX = [&] { if (alignment & wxALIGN_RIGHT) return back.GetWidth() - front.GetWidth(); @@ -239,8 +239,8 @@ wxBitmap zen::layOver(const wxBitmap& back, const wxBitmap& front, int alignmen ::memset(output.GetAlpha(), wxIMAGE_ALPHA_TRANSPARENT, width * height); const wxPoint posBack(std::max(-offsetX, 0), std::max(-offsetY, 0)); - writeToImage(output, back .ConvertToImage(), posBack); - writeToImage(output, front.ConvertToImage(), posBack + wxPoint(offsetX, offsetY)); + writeToImage(output, back , posBack); + writeToImage(output, front, posBack + wxPoint(offsetX, offsetY)); return output; } diff --git a/wx+/image_tools.h b/wx+/image_tools.h index 2a0dd0d4..d72597ef 100644 --- a/wx+/image_tools.h +++ b/wx+/image_tools.h @@ -34,7 +34,7 @@ wxImage stackImages(const wxImage& img1, const wxImage& img2, ImageStackLayout d wxImage createImageFromText(const wxString& text, const wxFont& font, const wxColor& col, ImageStackAlignment textAlign = ImageStackAlignment::LEFT); //CENTER/LEFT/RIGHT -wxBitmap layOver(const wxBitmap& back, const wxBitmap& front, int alignment = wxALIGN_CENTER); +wxImage layOver(const wxImage& back, const wxImage& front, int alignment = wxALIGN_CENTER); wxImage greyScale(const wxImage& img); //greyscale + brightness adaption wxBitmap greyScale(const wxBitmap& bmp); // @@ -213,7 +213,7 @@ wxColor gradient(const wxColor& from, const wxColor& to, double fraction) inline wxColor hsvColor(double h, double s, double v) //h within [0, 360), s, v within [0, 1] { - //https://de.wikipedia.org/wiki/HSV-Farbraum + //https://en.wikipedia.org/wiki/HSL_and_HSV //make input values fit into bounds if (h > 360) @@ -20,6 +20,7 @@ void drawBitmapRtlNoMirror(wxDC& dc, const wxBitmap& bmp, const wxRect& rect, in //wxDC::DrawIcon DOES mirror by default -> implement RTL support when needed wxBitmap mirrorIfRtl(const wxBitmap& bmp); +wxImage mirrorIfRtl(const wxImage& bmp); //manual text flow correction: https://www.w3.org/International/articles/inline-bidi-markup/ @@ -93,6 +94,15 @@ void drawBitmapRtlNoMirror(wxDC& dc, const wxBitmap& bmp, const wxRect& rect, in } +inline +wxImage mirrorIfRtl(const wxImage& bmp) +{ + if (wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft) + return bmp.Mirror(); + else + return bmp;} + + inline wxBitmap mirrorIfRtl(const wxBitmap& bmp) { diff --git a/wx+/toggle_button.h b/wx+/toggle_button.h index f61c3857..98ca32b3 100644 --- a/wx+/toggle_button.h +++ b/wx+/toggle_button.h @@ -28,8 +28,8 @@ public: SetLayoutDirection(wxLayout_LeftToRight); //avoid mirroring RTL languages like Hebrew or Arabic } - void init(const wxBitmap& activeBmp, - const wxBitmap& inactiveBmp); + void init(const wxBitmap& bmpActive, + const wxBitmap& bmpInactive); void setActive(bool value); bool isActive() const { return active_; } @@ -37,8 +37,8 @@ public: private: bool active_ = false; - wxBitmap activeBmp_; - wxBitmap inactiveBmp_; + wxBitmap bmpActive_; + wxBitmap bmpInactive_; }; @@ -49,21 +49,24 @@ private: //######################## implementation ######################## inline -void ToggleButton::init(const wxBitmap& activeBmp, - const wxBitmap& inactiveBmp) +void ToggleButton::init(const wxBitmap& bmpActive, + const wxBitmap& bmpInactive) { - activeBmp_ = activeBmp; - inactiveBmp_ = inactiveBmp; + bmpActive_ = bmpActive; + bmpInactive_ = bmpInactive; - setActive(active_); + setImage(*this, active_ ? bmpActive_ : bmpInactive_); } inline void ToggleButton::setActive(bool value) { - active_ = value; - setImage(*this, active_ ? activeBmp_ : inactiveBmp_); + if (active_ != value) + { + active_ = value; + setImage(*this, active_ ? bmpActive_ : bmpInactive_); + } } } |