diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:18:53 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:18:53 +0200 |
commit | 32cb97237e7691d31977ab503c6ea4511e8eb3a8 (patch) | |
tree | 4e97b53e9f7b74e8cc5d7548507d9e82ae38e36f /wx+/rtl.h | |
parent | 4.6 (diff) | |
download | FreeFileSync-32cb97237e7691d31977ab503c6ea4511e8eb3a8.tar.gz FreeFileSync-32cb97237e7691d31977ab503c6ea4511e8eb3a8.tar.bz2 FreeFileSync-32cb97237e7691d31977ab503c6ea4511e8eb3a8.zip |
5.0
Diffstat (limited to 'wx+/rtl.h')
-rw-r--r-- | wx+/rtl.h | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/wx+/rtl.h b/wx+/rtl.h new file mode 100644 index 00000000..b8844ca8 --- /dev/null +++ b/wx+/rtl.h @@ -0,0 +1,121 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * +// ************************************************************************** + +#ifndef RTL_H_0183487180058718273432148 +#define RTL_H_0183487180058718273432148 + +#include <memory> +#include <wx/dcmemory.h> +#include <wx/dcmirror.h> +#include <wx/image.h> +#include <wx/icon.h> +#include <wx/app.h> + +namespace zen +{ +//functions supporting right-to-left GUI layout + +void drawBitmapRtlMirror(wxDC& dc, + const wxBitmap& image, + const wxRect& rect, + int alignment, + std::unique_ptr<wxBitmap>& buffer); //mirror image if layout is RTL + fix some strange wxDC::Blit bug on RTL + +void drawBitmapRtlNoMirror(wxDC& dc, //wxDC::DrawLabel does already NOT mirror by default (but does a crappy job at it, surprise) + const wxBitmap& image, + const wxRect& rect, + int alignment, + std::unique_ptr<wxBitmap>& buffer); + +void drawIconRtlNoMirror(wxDC& dc, + const wxIcon& icon, //wxDC::DrawIcon DOES mirror by default + const wxPoint& pt, + std::unique_ptr<wxBitmap>& buffer); + +wxBitmap mirrorIfRtl(const wxBitmap& bmp); + + + + + + + + + + + +//---------------------- implementation ------------------------ +namespace +{ +template <class DrawImageFun> +void drawRtlImpl(wxDC& dc, const wxRect& rect, std::unique_ptr<wxBitmap>& buffer, bool doMirror, DrawImageFun draw) +{ + if (dc.GetLayoutDirection() == wxLayout_RightToLeft) + { + if (!buffer || buffer->GetWidth() != rect.width || buffer->GetHeight() < rect.height) //[!] since we do a mirror, width needs to match exactly! + buffer.reset(new wxBitmap(rect.width, rect.height)); + + wxMemoryDC memDc(*buffer); + memDc.Blit(wxPoint(0, 0), rect.GetSize(), &dc, rect.GetTopLeft()); //blit in: background is mirrored due to memDc, dc having different layout direction! + + if (!doMirror) + { + *buffer = wxBitmap(buffer->ConvertToImage().Mirror()); + memDc.SelectObject(*buffer); + } + + draw(memDc, wxRect(0, 0, rect.width, rect.height)); + //note: we cannot simply use memDc.SetLayoutDirection(wxLayout_RightToLeft) due to some strange 1 pixel bug! so it's a quadruple mirror! :> + + if (!doMirror) + { + *buffer = wxBitmap(buffer->ConvertToImage().Mirror()); + memDc.SelectObject(*buffer); + } + + dc.Blit(rect.GetTopLeft(), rect.GetSize(), &memDc, wxPoint(0, 0)); //blit out: mirror once again + } + else + draw(dc, rect); +} +} + + +inline +void drawBitmapRtlMirror(wxDC& dc, const wxBitmap& image, const wxRect& rect, int alignment, std::unique_ptr<wxBitmap>& buffer) +{ + return drawRtlImpl(dc, rect, buffer, true, [&](wxDC& dc2, const wxRect& rect2) { dc2.DrawLabel(wxString(), image, rect2, alignment); }); +} + +inline +void drawBitmapRtlNoMirror(wxDC& dc, const wxBitmap& image, const wxRect& rect, int alignment, std::unique_ptr<wxBitmap>& buffer) +{ + if (dc.GetLayoutDirection() == wxLayout_RightToLeft) + if ((alignment & wxALIGN_CENTER_HORIZONTAL) == 0) //we still *do* want to mirror alignment! + alignment ^= wxALIGN_RIGHT; + static_assert(wxALIGN_LEFT == 0, "doh"); + return drawRtlImpl(dc, rect, buffer, false, [&](wxDC& dc2, const wxRect& rect2) { dc2.DrawLabel(wxString(), image, rect2, alignment); }); +} + +inline +void drawIconRtlNoMirror(wxDC& dc, const wxIcon& icon, const wxPoint& pt, std::unique_ptr<wxBitmap>& buffer) +{ + wxRect rect(pt.x, pt.y, icon.GetWidth(), icon.GetHeight()); + return drawRtlImpl(dc, rect, buffer, false, [&](wxDC& dc2, const wxRect& rect2) { dc2.DrawIcon(icon, rect2.GetTopLeft()); }); +} + + +inline +wxBitmap mirrorIfRtl(const wxBitmap& bmp) +{ + if (wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft) + return bmp.ConvertToImage().Mirror(); + else + return bmp; +} +} + +#endif //RTL_H_0183487180058718273432148 |