Merge branch 'art-scalefactor'
Fix confusion between different kinds of coordinates in wxAUI code, restoring correct behaviour in high DPI on all platforms. See #2620. Closes #19331.
This commit is contained in:
@@ -167,15 +167,19 @@ Currently the following symbols exist:
|
||||
have an efficient (CPU-specific) implementation. Notice that the functions
|
||||
themselves are always available but can be prohibitively slow to use when
|
||||
implemented in a generic way, using a critical section.}
|
||||
@itemdef{wxHAS_BITMAP_SCALE_FACTOR, Defined in @c wx/bitmap.h if bitmaps
|
||||
actually use scale factor under the current platform, see
|
||||
wxBitmap::SetScaleFactor().}
|
||||
@itemdef{wxHAS_BITMAPTOGGLEBUTTON, Defined in @c wx/tglbtn.h if
|
||||
wxBitmapToggleButton class is available in addition to wxToggleButton.}
|
||||
@itemdef{wxHAS_CONFIG_TEMPLATE_RW, Defined if the currently used compiler
|
||||
supports template Read() and Write() methods in wxConfig.}
|
||||
@itemdef{wxHAS_DEPRECATED_ATTR, Defined if C++14 @c [[deprecated]] attribute is
|
||||
supported (this symbol only exists in wxWidgets 3.1.6 or later).}
|
||||
@itemdef{wxHAS_DPI_INDEPENDENT_PIXELS, Defined if pixel coordinates on the
|
||||
current platform scale with DPI, i.e. if the given length in pixels has the
|
||||
same apparent size on the display independently of the DPI (this symbol
|
||||
only exists in wxWidgets 3.1.6 or later). Note that it should rarely, if
|
||||
ever, be necessary to use this symbol directly, functions such as
|
||||
wxWindow::FromDIP() and wxBitmap::GetScaledSize() exist to hide the
|
||||
differences between the platforms with and without DPI-independent pixels.}
|
||||
@itemdef{wxHAS_MEMBER_DEFAULT, Defined if the currently used compiler supports
|
||||
C++11 @c =default.}
|
||||
@itemdef{wxHAS_LARGE_FILES, Defined if wxFile supports files more than 4GB in
|
||||
|
||||
@@ -234,14 +234,11 @@ protected:
|
||||
return wxNullBitmap;
|
||||
}
|
||||
|
||||
// Derived classes must override CreateBitmapBundle if they provide
|
||||
// a bundle that cannot be represented through an ordinary bitmap.
|
||||
// Default implementation creates a wxBitmapBundle which returns the
|
||||
// specified art resource in whichever size it is being asked for.
|
||||
virtual wxBitmapBundle CreateBitmapBundle(const wxArtID& id,
|
||||
const wxArtClient& client,
|
||||
const wxSize& size)
|
||||
{
|
||||
return wxBitmapBundle(CreateBitmap(id, client, size));
|
||||
}
|
||||
const wxSize& size);
|
||||
|
||||
virtual wxIconBundle CreateIconBundle(const wxArtID& WXUNUSED(id),
|
||||
const wxArtClient& WXUNUSED(client))
|
||||
|
||||
@@ -186,12 +186,22 @@ public:
|
||||
wxSize GetSize() const
|
||||
{ return wxSize(GetWidth(), GetHeight()); }
|
||||
|
||||
// support for scaled bitmaps
|
||||
// Store or return the scale factor, which determines the ratio between the
|
||||
// bitmap physical size and its DIP size (on all platforms). By default
|
||||
// it's just 1.
|
||||
virtual void SetScaleFactor(double scale);
|
||||
virtual double GetScaleFactor() const;
|
||||
virtual double GetScaledWidth() const;
|
||||
virtual double GetScaledHeight() const;
|
||||
virtual wxSize GetScaledSize() const;
|
||||
|
||||
// This function returns the size divided by the scale factor, so that a
|
||||
// 64x64 bitmap with a scale factor of 2 has DIP size of 32x32 everywhere.
|
||||
wxSize GetDIPSize() const;
|
||||
|
||||
// These functions return the corresponding metrics divided by the scale
|
||||
// factor on platforms with DPI-independent pixels (e.g. GTK, Mac) and just
|
||||
// the same thing as the non-scaled accessors elsewhere (e.g. MSW).
|
||||
double GetScaledWidth() const;
|
||||
double GetScaledHeight() const;
|
||||
wxSize GetScaledSize() const;
|
||||
|
||||
#if wxUSE_IMAGE
|
||||
virtual wxImage ConvertToImage() const = 0;
|
||||
|
||||
@@ -111,5 +111,20 @@
|
||||
// compiler, so this symbol exists purely for compatibility.
|
||||
#define wxHAS_EVENT_BIND
|
||||
|
||||
|
||||
/*
|
||||
Some platforms use DPI-independent pixels, i.e. pixels actually scale with
|
||||
DPI and a 100px-wide window has the same apparent size on the display in
|
||||
normal and high (i.e. 2x, or 200% scaling) DPI, while others always use
|
||||
physical pixels and a window must be 200px wide to have the same apparent
|
||||
size in high DPI as in normal DPI.
|
||||
*/
|
||||
#if defined(__WXGTK3__) || defined(__WXMAC__)
|
||||
#define wxHAS_DPI_INDEPENDENT_PIXELS
|
||||
|
||||
// This is an older synonym kept only for compatibility
|
||||
#define wxHAVE_DPI_INDEPENDENT_PIXELS
|
||||
#endif
|
||||
|
||||
#endif /* _WX_FEATURES_H_ */
|
||||
|
||||
|
||||
@@ -17,10 +17,6 @@ typedef struct _GdkPixbuf GdkPixbuf;
|
||||
class WXDLLIMPEXP_FWD_CORE wxPixelDataBase;
|
||||
class WXDLLIMPEXP_FWD_CORE wxCursor;
|
||||
|
||||
#ifdef __WXGTK3__
|
||||
#define wxHAS_BITMAP_SCALE_FACTOR
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxMask
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -89,7 +85,7 @@ public:
|
||||
{ return Create(sz.GetWidth(), sz.GetHeight(), depth); }
|
||||
bool Create(int width, int height, const wxDC& WXUNUSED(dc))
|
||||
{ return Create(width,height); }
|
||||
#ifdef wxHAS_BITMAP_SCALE_FACTOR
|
||||
#ifdef __WXGTK3__
|
||||
virtual bool CreateScaled(int w, int h, int depth, double scale) wxOVERRIDE;
|
||||
virtual void SetScaleFactor(double scale) wxOVERRIDE;
|
||||
virtual double GetScaleFactor() const wxOVERRIDE;
|
||||
|
||||
@@ -184,12 +184,18 @@ public:
|
||||
void UseAlpha(bool use = true);
|
||||
void ResetAlpha() { UseAlpha(false); }
|
||||
|
||||
// provide stabs of scaled bitmaps functions, they are trivial here
|
||||
// allow setting and storing the scale factor
|
||||
virtual void SetScaleFactor(double scale);
|
||||
virtual double GetScaleFactor() const;
|
||||
virtual double GetScaledWidth() const;
|
||||
virtual double GetScaledHeight() const;
|
||||
virtual wxSize GetScaledSize() const;
|
||||
|
||||
// return the size divided by scale factor
|
||||
wxSize GetDIPSize() const;
|
||||
|
||||
// but scaled metrics accessors return the same thing as non-scaled ones,
|
||||
// just as in all the other ports without wxHAS_DPI_INDEPENDENT_PIXELS.
|
||||
double GetScaledWidth() const;
|
||||
double GetScaledHeight() const;
|
||||
wxSize GetScaledSize() const;
|
||||
|
||||
// implementation only from now on
|
||||
// -------------------------------
|
||||
|
||||
@@ -36,6 +36,8 @@ public:
|
||||
{
|
||||
m_width = m_height = m_depth = 0;
|
||||
|
||||
m_scaleFactor = 1.0;
|
||||
|
||||
m_handle = NULL;
|
||||
}
|
||||
|
||||
@@ -45,6 +47,8 @@ public:
|
||||
m_height = data.m_height;
|
||||
m_depth = data.m_depth;
|
||||
|
||||
m_scaleFactor = data.m_scaleFactor;
|
||||
|
||||
// can't copy handles like this, derived class copy ctor must do it!
|
||||
m_handle = NULL;
|
||||
}
|
||||
@@ -65,6 +69,9 @@ public:
|
||||
// the depth of the image
|
||||
int m_depth;
|
||||
|
||||
// scale factor of the image
|
||||
double m_scaleFactor;
|
||||
|
||||
// the handle to it
|
||||
union
|
||||
{
|
||||
@@ -111,6 +118,10 @@ public:
|
||||
int GetWidth() const { return IsNull() ? 0 : GetGDIImageData()->m_width; }
|
||||
int GetHeight() const { return IsNull() ? 0 : GetGDIImageData()->m_height; }
|
||||
int GetDepth() const { return IsNull() ? 0 : GetGDIImageData()->m_depth; }
|
||||
double GetScaleFactor() const
|
||||
{
|
||||
return IsNull() ? 1.0 : GetGDIImageData()->m_scaleFactor;
|
||||
}
|
||||
|
||||
wxSize GetSize() const
|
||||
{
|
||||
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
#endif // WXWIN_COMPATIBILITY_3_0
|
||||
|
||||
WXHICON GetHICON() const { return (WXHICON)GetHandle(); }
|
||||
bool InitFromHICON(WXHICON icon, int width, int height);
|
||||
bool InitFromHICON(WXHICON icon, int width, int height, double scale = 1.0);
|
||||
|
||||
// create from bitmap (which should have a mask unless it's monochrome):
|
||||
// there shouldn't be any implicit bitmap -> icon conversion (i.e. no
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
|
||||
#include "wx/palette.h"
|
||||
|
||||
#define wxHAS_BITMAP_SCALE_FACTOR
|
||||
|
||||
// Bitmap
|
||||
class WXDLLIMPEXP_FWD_CORE wxBitmap;
|
||||
class wxBitmapRefData ;
|
||||
|
||||
@@ -49,10 +49,6 @@
|
||||
#define wxUSE_MENUS_NATIVE wxUSE_MENUS
|
||||
#endif // __WXUNIVERSAL__/!__WXUNIVERSAL__
|
||||
|
||||
#if defined(__WXGTK3__) || defined(__WXMAC__)
|
||||
#define wxHAVE_DPI_INDEPENDENT_PIXELS
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// forward declarations
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -542,7 +538,7 @@ public:
|
||||
|
||||
// Return the magnification of the content of this window for the platforms
|
||||
// using logical pixels different from physical ones, i.e. those for which
|
||||
// wxHAVE_DPI_INDEPENDENT_PIXELS is defined. For the other ones, always
|
||||
// wxHAS_DPI_INDEPENDENT_PIXELS is defined. For the other ones, always
|
||||
// returns 1, regardless of DPI scale factor returned by the function below.
|
||||
virtual double GetContentScaleFactor() const;
|
||||
|
||||
@@ -997,14 +993,14 @@ public:
|
||||
// horizontal and vertical directions, but this could, in principle,
|
||||
// change too, so prefer using the overloads taking wxPoint or wxSize.
|
||||
|
||||
#ifdef wxHAVE_DPI_INDEPENDENT_PIXELS
|
||||
#ifdef wxHAS_DPI_INDEPENDENT_PIXELS
|
||||
static wxSize FromDIP(const wxSize& sz, const wxWindowBase* WXUNUSED(w))
|
||||
{
|
||||
return sz;
|
||||
}
|
||||
#else
|
||||
static wxSize FromDIP(const wxSize& sz, const wxWindowBase* w);
|
||||
#endif // wxHAVE_DPI_INDEPENDENT_PIXELS
|
||||
#endif // wxHAS_DPI_INDEPENDENT_PIXELS
|
||||
static wxPoint FromDIP(const wxPoint& pt, const wxWindowBase* w)
|
||||
{
|
||||
const wxSize sz = FromDIP(wxSize(pt.x, pt.y), w);
|
||||
@@ -1019,14 +1015,14 @@ public:
|
||||
wxPoint FromDIP(const wxPoint& pt) const { return FromDIP(pt, this); }
|
||||
int FromDIP(int d) const { return FromDIP(d, this); }
|
||||
|
||||
#ifdef wxHAVE_DPI_INDEPENDENT_PIXELS
|
||||
#ifdef wxHAS_DPI_INDEPENDENT_PIXELS
|
||||
static wxSize ToDIP(const wxSize& sz, const wxWindowBase* WXUNUSED(w))
|
||||
{
|
||||
return sz;
|
||||
}
|
||||
#else
|
||||
static wxSize ToDIP(const wxSize& sz, const wxWindowBase* w);
|
||||
#endif // wxHAVE_DPI_INDEPENDENT_PIXELS
|
||||
#endif // wxHAS_DPI_INDEPENDENT_PIXELS
|
||||
static wxPoint ToDIP(const wxPoint& pt, const wxWindowBase* w)
|
||||
{
|
||||
const wxSize sz = ToDIP(wxSize(pt.x, pt.y), w);
|
||||
|
||||
@@ -307,7 +307,9 @@ public:
|
||||
@param client
|
||||
wxArtClient identifier of the client (i.e. who is asking for the bitmap).
|
||||
@param size
|
||||
Default size for the returned bundle.
|
||||
Default size for the returned bundle, i.e. the size of the bitmap
|
||||
in normal DPI (this implies that wxWindow::FromDIP() must @e not be
|
||||
used with it).
|
||||
|
||||
@return If any of the registered providers recognizes the ID in its
|
||||
CreateBitmapBundle(), this bundle is returned. Otherwise, if any of
|
||||
|
||||
@@ -541,6 +541,22 @@ public:
|
||||
*/
|
||||
virtual int GetDepth() const;
|
||||
|
||||
/**
|
||||
Returns the size of bitmap in DPI-independent units.
|
||||
|
||||
This assumes that the bitmap was created using the value of scale
|
||||
factor corresponding to the current DPI (see CreateScaled() and
|
||||
SetScaleFactor()) and returns its physical size divided by this scale
|
||||
factor.
|
||||
|
||||
Unlike GetScaledSize(), this function returns the same value under all
|
||||
platforms and so its result should @e not be used as window or device
|
||||
context coordinates.
|
||||
|
||||
@since 3.1.6
|
||||
*/
|
||||
wxSize GetDIPSize() const;
|
||||
|
||||
/**
|
||||
Returns the static list of bitmap format handlers.
|
||||
|
||||
@@ -604,23 +620,29 @@ public:
|
||||
|
||||
@since 2.9.5
|
||||
*/
|
||||
virtual double GetScaledHeight() const;
|
||||
double GetScaledHeight() const;
|
||||
|
||||
/**
|
||||
Returns the scaled size of the bitmap.
|
||||
|
||||
The scaled size of the bitmap is its size in pixels, as returned by
|
||||
For the platforms using DPI-independent pixels, i.e. those where @c
|
||||
wxHAS_DPI_INDEPENDENT_PIXELS is defined, such as wxOSX or wxGTK 3,
|
||||
this function returns the physical size of the bitmap, as returned by
|
||||
GetSize(), divided by its scale factor, as returned by
|
||||
GetScaleFactor(), and so is the same as the normal size for bitmaps
|
||||
with the default scale factor of 1 and always less than the physical
|
||||
size for the higher resolution bitmaps supposed to be used on high DPI
|
||||
screens.
|
||||
GetScaleFactor(), while for the other platforms, it simply returns the
|
||||
same thing as GetSize().
|
||||
|
||||
This ensures that the result of this function is always expressed in
|
||||
the pixel coordinates appropriate for the current platform, i.e. its
|
||||
return value is always in logical pixels, used for window and wxDC
|
||||
coordinates, whether these pixels are the same as physical pixels,
|
||||
which are returned by GetSize(), or not.
|
||||
|
||||
@see GetScaledWidth(), GetScaledHeight(), GetSize()
|
||||
|
||||
@since 2.9.5
|
||||
*/
|
||||
virtual wxSize GetScaledSize() const;
|
||||
wxSize GetScaledSize() const;
|
||||
|
||||
/**
|
||||
Returns the scaled width of the bitmap.
|
||||
@@ -631,7 +653,7 @@ public:
|
||||
|
||||
@since 2.9.5
|
||||
*/
|
||||
virtual double GetScaledWidth() const;
|
||||
double GetScaledWidth() const;
|
||||
|
||||
/**
|
||||
Returns the size of the bitmap in pixels.
|
||||
@@ -810,21 +832,6 @@ public:
|
||||
When creating a new bitmap, CreateScaled() can be used to specify the
|
||||
correct scale factor from the beginning.
|
||||
|
||||
Note that this method exists in all ports, but simply does nothing in
|
||||
those of them that don't use logical pixel scaling. The preprocessor
|
||||
symbol @c wxHAS_BITMAP_SCALE_FACTOR can be tested to determine whether
|
||||
the scale factor is really supported, e.g.
|
||||
|
||||
@code
|
||||
bitmap.SetScaleFactor(2);
|
||||
|
||||
// In the other ports scale factor is always 1, so the assert would
|
||||
// fail there.
|
||||
#ifdef wxHAS_BITMAP_SCALE_FACTOR
|
||||
wxASSERT( bitmap.GetScaleFactor() == 2 );
|
||||
#endif
|
||||
@endcode
|
||||
|
||||
@since 3.1.6
|
||||
*/
|
||||
virtual void SetScaleFactor(double scale);
|
||||
|
||||
@@ -1416,7 +1416,7 @@ public:
|
||||
For the platforms not doing any pixel mapping, i.e. where logical and
|
||||
physical pixels are one and the same, this function always returns 1.0
|
||||
and so using it is, in principle, unnecessary and could be avoided by
|
||||
using preprocessor check for @c wxHAVE_DPI_INDEPENDENT_PIXELS @e not
|
||||
using preprocessor check for @c wxHAS_DPI_INDEPENDENT_PIXELS @e not
|
||||
being defined, however using this function unconditionally under all
|
||||
platforms is usually simpler and so preferable.
|
||||
|
||||
@@ -1424,7 +1424,7 @@ public:
|
||||
3.0, but different from its behaviour in versions 3.1.0 to 3.1.3,
|
||||
where it returned the same value as GetDPIScaleFactor(). Please use
|
||||
the other function if you need to use a scaling factor greater than
|
||||
1.0 even for the platforms without @c wxHAVE_DPI_INDEPENDENT_PIXELS,
|
||||
1.0 even for the platforms without @c wxHAS_DPI_INDEPENDENT_PIXELS,
|
||||
such as wxMSW.
|
||||
|
||||
@since 2.9.5
|
||||
|
||||
@@ -781,22 +781,20 @@ MyFrame::MyFrame(wxWindow* parent,
|
||||
// create some toolbars
|
||||
wxAuiToolBar* tb1 = new wxAuiToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
||||
wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_OVERFLOW);
|
||||
tb1->SetToolBitmapSize(FromDIP(wxSize(48,48)));
|
||||
tb1->AddTool(ID_SampleItem+1, "Test", wxArtProvider::GetBitmap(wxART_ERROR));
|
||||
tb1->AddTool(ID_SampleItem+1, "Test", wxArtProvider::GetBitmapBundle(wxART_ERROR));
|
||||
tb1->AddSeparator();
|
||||
tb1->AddTool(ID_SampleItem+2, "Test", wxArtProvider::GetBitmap(wxART_QUESTION));
|
||||
tb1->AddTool(ID_SampleItem+3, "Test", wxArtProvider::GetBitmap(wxART_INFORMATION));
|
||||
tb1->AddTool(ID_SampleItem+4, "Test", wxArtProvider::GetBitmap(wxART_WARNING));
|
||||
tb1->AddTool(ID_SampleItem+5, "Test", wxArtProvider::GetBitmap(wxART_MISSING_IMAGE));
|
||||
tb1->AddTool(ID_SampleItem+2, "Test", wxArtProvider::GetBitmapBundle(wxART_QUESTION));
|
||||
tb1->AddTool(ID_SampleItem+3, "Test", wxArtProvider::GetBitmapBundle(wxART_INFORMATION));
|
||||
tb1->AddTool(ID_SampleItem+4, "Test", wxArtProvider::GetBitmapBundle(wxART_WARNING));
|
||||
tb1->AddTool(ID_SampleItem+5, "Test", wxArtProvider::GetBitmapBundle(wxART_MISSING_IMAGE));
|
||||
tb1->SetCustomOverflowItems(prepend_items, append_items);
|
||||
tb1->Realize();
|
||||
|
||||
|
||||
wxAuiToolBar* tb2 = new wxAuiToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
||||
wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_OVERFLOW | wxAUI_TB_HORIZONTAL);
|
||||
tb2->SetToolBitmapSize(FromDIP(wxSize(16,16)));
|
||||
|
||||
wxBitmap tb2_bmp1 = wxArtProvider::GetBitmap(wxART_QUESTION, wxART_OTHER, FromDIP(wxSize(16,16)));
|
||||
wxBitmapBundle tb2_bmp1 = wxArtProvider::GetBitmapBundle(wxART_QUESTION, wxART_OTHER, wxSize(16,16));
|
||||
tb2->AddTool(ID_SampleItem+6, "Disabled", tb2_bmp1);
|
||||
tb2->AddTool(ID_SampleItem+7, "Test", tb2_bmp1);
|
||||
tb2->AddTool(ID_SampleItem+8, "Test", tb2_bmp1);
|
||||
@@ -816,8 +814,7 @@ MyFrame::MyFrame(wxWindow* parent,
|
||||
|
||||
wxAuiToolBar* tb3 = new wxAuiToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
||||
wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_OVERFLOW);
|
||||
tb3->SetToolBitmapSize(FromDIP(wxSize(16,16)));
|
||||
wxBitmap tb3_bmp1 = wxArtProvider::GetBitmap(wxART_FOLDER, wxART_OTHER, FromDIP(wxSize(16,16)));
|
||||
wxBitmapBundle tb3_bmp1 = wxArtProvider::GetBitmapBundle(wxART_FOLDER, wxART_OTHER, wxSize(16,16));
|
||||
tb3->AddTool(ID_SampleItem+16, "Check 1", tb3_bmp1, "Check 1", wxITEM_CHECK);
|
||||
tb3->AddTool(ID_SampleItem+17, "Check 2", tb3_bmp1, "Check 2", wxITEM_CHECK);
|
||||
tb3->AddTool(ID_SampleItem+18, "Check 3", tb3_bmp1, "Check 3", wxITEM_CHECK);
|
||||
@@ -839,8 +836,7 @@ MyFrame::MyFrame(wxWindow* parent,
|
||||
wxAUI_TB_OVERFLOW |
|
||||
wxAUI_TB_TEXT |
|
||||
wxAUI_TB_HORZ_TEXT);
|
||||
tb4->SetToolBitmapSize(FromDIP(wxSize(16,16)));
|
||||
wxBitmap tb4_bmp1 = wxArtProvider::GetBitmap(wxART_NORMAL_FILE, wxART_OTHER, FromDIP(wxSize(16,16)));
|
||||
wxBitmapBundle tb4_bmp1 = wxArtProvider::GetBitmapBundle(wxART_NORMAL_FILE, wxART_OTHER, wxSize(16,16));
|
||||
tb4->AddTool(ID_DropDownToolbarItem, "Item 1", tb4_bmp1);
|
||||
tb4->AddTool(ID_SampleItem+23, "Item 2", tb4_bmp1);
|
||||
tb4->SetToolSticky(ID_SampleItem+23, true);
|
||||
@@ -863,13 +859,12 @@ MyFrame::MyFrame(wxWindow* parent,
|
||||
|
||||
wxAuiToolBar* tb5 = new wxAuiToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
||||
wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_OVERFLOW | wxAUI_TB_VERTICAL);
|
||||
tb5->SetToolBitmapSize(FromDIP(wxSize(48,48)));
|
||||
tb5->AddTool(ID_SampleItem+30, "Test", wxArtProvider::GetBitmap(wxART_ERROR));
|
||||
tb5->AddTool(ID_SampleItem+30, "Test", wxArtProvider::GetBitmapBundle(wxART_ERROR));
|
||||
tb5->AddSeparator();
|
||||
tb5->AddTool(ID_SampleItem+31, "Test", wxArtProvider::GetBitmap(wxART_QUESTION));
|
||||
tb5->AddTool(ID_SampleItem+32, "Test", wxArtProvider::GetBitmap(wxART_INFORMATION));
|
||||
tb5->AddTool(ID_SampleItem+33, "Test", wxArtProvider::GetBitmap(wxART_WARNING));
|
||||
tb5->AddTool(ID_SampleItem+34, "Test", wxArtProvider::GetBitmap(wxART_MISSING_IMAGE));
|
||||
tb5->AddTool(ID_SampleItem+31, "Test", wxArtProvider::GetBitmapBundle(wxART_QUESTION));
|
||||
tb5->AddTool(ID_SampleItem+32, "Test", wxArtProvider::GetBitmapBundle(wxART_INFORMATION));
|
||||
tb5->AddTool(ID_SampleItem+33, "Test", wxArtProvider::GetBitmapBundle(wxART_WARNING));
|
||||
tb5->AddTool(ID_SampleItem+34, "Test", wxArtProvider::GetBitmapBundle(wxART_MISSING_IMAGE));
|
||||
tb5->SetCustomOverflowItems(prepend_items, append_items);
|
||||
tb5->Realize();
|
||||
|
||||
@@ -928,9 +923,9 @@ MyFrame::MyFrame(wxWindow* parent,
|
||||
m_mgr.AddPane(wnd10, wxAuiPaneInfo().
|
||||
Name("test10").Caption("Text Pane with Hide Prompt").
|
||||
Bottom().Layer(1).Position(1).
|
||||
Icon(wxArtProvider::GetBitmap(wxART_WARNING,
|
||||
wxART_OTHER,
|
||||
wxSize(iconSize, iconSize))));
|
||||
Icon(wxArtProvider::GetBitmapBundle(wxART_WARNING,
|
||||
wxART_OTHER,
|
||||
wxSize(iconSize, iconSize))));
|
||||
|
||||
m_mgr.AddPane(CreateSizeReportCtrl(), wxAuiPaneInfo().
|
||||
Name("test11").Caption("Fixed Pane").
|
||||
@@ -1489,6 +1484,7 @@ void MyFrame::OnDropDownToolbarItem(wxAuiToolBarEvent& evt)
|
||||
// create the popup menu
|
||||
wxMenu menuPopup;
|
||||
|
||||
// TODO: Use GetBitmapBundle() when wxMenuItem is updated to use it too.
|
||||
wxBitmap bmp = wxArtProvider::GetBitmap(wxART_QUESTION, wxART_OTHER, FromDIP(wxSize(16,16)));
|
||||
|
||||
wxMenuItem* m1 = new wxMenuItem(&menuPopup, 10001, _("Drop Down Item 1"));
|
||||
@@ -1589,11 +1585,11 @@ wxTreeCtrl* MyFrame::CreateTreeCtrl()
|
||||
FromDIP(wxSize(160,250)),
|
||||
wxTR_DEFAULT_STYLE | wxNO_BORDER);
|
||||
|
||||
wxSize size = FromDIP(wxSize(16, 16));
|
||||
wxImageList* imglist = new wxImageList(size.x, size.y, true, 2);
|
||||
imglist->Add(wxArtProvider::GetBitmap(wxART_FOLDER, wxART_OTHER, size));
|
||||
imglist->Add(wxArtProvider::GetBitmap(wxART_NORMAL_FILE, wxART_OTHER, size));
|
||||
tree->AssignImageList(imglist);
|
||||
wxSize size(16, 16);
|
||||
wxVector<wxBitmapBundle> images;
|
||||
images.push_back(wxArtProvider::GetBitmapBundle(wxART_FOLDER, wxART_OTHER, size));
|
||||
images.push_back(wxArtProvider::GetBitmapBundle(wxART_NORMAL_FILE, wxART_OTHER, size));
|
||||
tree->SetImages(images);
|
||||
|
||||
wxTreeItemId root = tree->AddRoot("wxAUI Project", 0);
|
||||
wxArrayTreeItemIds items;
|
||||
@@ -1655,7 +1651,7 @@ wxAuiNotebook* MyFrame::CreateNotebook()
|
||||
m_notebook_style);
|
||||
ctrl->Freeze();
|
||||
|
||||
wxBitmap page_bmp = wxArtProvider::GetBitmap(wxART_NORMAL_FILE, wxART_OTHER, FromDIP(wxSize(16,16)));
|
||||
wxBitmapBundle page_bmp = wxArtProvider::GetBitmapBundle(wxART_NORMAL_FILE, wxART_OTHER, wxSize(16,16));
|
||||
|
||||
ctrl->AddPage(CreateHTMLCtrl(ctrl), "Welcome to wxAUI" , false, page_bmp);
|
||||
ctrl->SetPageToolTip(0, "Welcome to wxAUI (this is a page tooltip)");
|
||||
|
||||
@@ -684,9 +684,16 @@ wxAuiDefaultDockArt::DrawIcon(wxDC& dc, wxWindow *window, const wxRect& rect, wx
|
||||
wxCHECK_RET( window, "must have some window" );
|
||||
}
|
||||
|
||||
// Ensure the icon fits into the title bar.
|
||||
wxSize iconSize = pane.icon.GetPreferredSizeFor(window);
|
||||
if (iconSize.y > rect.height)
|
||||
{
|
||||
iconSize *= static_cast<double>(rect.height) / iconSize.y;
|
||||
}
|
||||
|
||||
// Draw the icon centered vertically
|
||||
int xOffset = window->FromDIP(2);
|
||||
const wxBitmap& icon = pane.icon.GetBitmapFor(window);
|
||||
const wxBitmap& icon = pane.icon.GetBitmap(iconSize);
|
||||
dc.DrawBitmap(icon,
|
||||
rect.x+xOffset, rect.y+(rect.height-icon.GetScaledHeight())/2,
|
||||
true);
|
||||
|
||||
@@ -245,12 +245,12 @@ void wxAuiGenericTabArt::SetSizingInfo(const wxSize& tab_ctrl_size,
|
||||
|
||||
m_fixedTabWidth = wnd->FromDIP(100);
|
||||
|
||||
int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - wxWindow::FromDIP(4, NULL);
|
||||
int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - wnd->FromDIP(4);
|
||||
|
||||
if (m_flags & wxAUI_NB_CLOSE_BUTTON)
|
||||
tot_width -= m_activeCloseBmp.GetPreferredSizeFor(wnd).x;
|
||||
tot_width -= m_activeCloseBmp.GetPreferredSizeFor(wnd).x / wnd->GetContentScaleFactor();
|
||||
if (m_flags & wxAUI_NB_WINDOWLIST_BUTTON)
|
||||
tot_width -= m_activeWindowListBmp.GetPreferredSizeFor(wnd).x;
|
||||
tot_width -= m_activeWindowListBmp.GetPreferredSizeFor(wnd).x / wnd->GetContentScaleFactor();
|
||||
|
||||
if (tab_count > 0)
|
||||
{
|
||||
@@ -258,12 +258,12 @@ void wxAuiGenericTabArt::SetSizingInfo(const wxSize& tab_ctrl_size,
|
||||
}
|
||||
|
||||
|
||||
m_fixedTabWidth = wxMax(m_fixedTabWidth, wxWindow::FromDIP(100, NULL));
|
||||
m_fixedTabWidth = wxMax(m_fixedTabWidth, wnd->FromDIP(100));
|
||||
|
||||
if (m_fixedTabWidth > tot_width/2)
|
||||
m_fixedTabWidth = tot_width/2;
|
||||
|
||||
m_fixedTabWidth = wxMin(m_fixedTabWidth, wxWindow::FromDIP(220, NULL));
|
||||
m_fixedTabWidth = wxMin(m_fixedTabWidth, wnd->FromDIP(220));
|
||||
|
||||
m_tabCtrlHeight = tab_ctrl_size.y;
|
||||
}
|
||||
@@ -703,7 +703,9 @@ wxSize wxAuiGenericTabArt::GetTabSize(wxDC& dc,
|
||||
// if there's a bitmap, add space for it
|
||||
if (bitmap.IsOk())
|
||||
{
|
||||
const wxSize bitmapSize = bitmap.GetPreferredSizeFor(wnd);
|
||||
// we need the correct size of the bitmap to be used on this window in
|
||||
// logical dimensions for drawing
|
||||
const wxSize bitmapSize = bitmap.GetPreferredSizeFor(wnd) / wnd->GetContentScaleFactor();
|
||||
|
||||
// increase by bitmap plus right side bitmap padding
|
||||
tab_width += bitmapSize.x + wnd->FromDIP(3);
|
||||
@@ -976,7 +978,7 @@ void wxAuiSimpleTabArt::SetSizingInfo(const wxSize& tab_ctrl_size,
|
||||
|
||||
m_fixedTabWidth = wnd->FromDIP(100);
|
||||
|
||||
int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - wxWindow::FromDIP(4, NULL);
|
||||
int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - wnd->FromDIP(4);
|
||||
|
||||
if (m_flags & wxAUI_NB_CLOSE_BUTTON)
|
||||
tot_width -= m_activeCloseBmp.GetBitmapFor(wnd).GetScaledWidth();
|
||||
@@ -989,12 +991,12 @@ void wxAuiSimpleTabArt::SetSizingInfo(const wxSize& tab_ctrl_size,
|
||||
}
|
||||
|
||||
|
||||
m_fixedTabWidth = wxMax(m_fixedTabWidth, wxWindow::FromDIP(100, NULL));
|
||||
m_fixedTabWidth = wxMax(m_fixedTabWidth, wnd->FromDIP(100));
|
||||
|
||||
if (m_fixedTabWidth > tot_width/2)
|
||||
m_fixedTabWidth = tot_width/2;
|
||||
|
||||
m_fixedTabWidth = wxMin(m_fixedTabWidth, wxWindow::FromDIP(220, NULL));
|
||||
m_fixedTabWidth = wxMin(m_fixedTabWidth, wnd->FromDIP(220));
|
||||
}
|
||||
|
||||
void wxAuiSimpleTabArt::SetColour(const wxColour& colour)
|
||||
|
||||
@@ -138,6 +138,77 @@ wxArtProviderCache::ConstructHashID(const wxArtID& id,
|
||||
wxString::Format(wxT("%d-%d"), size.x, size.y);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxBitmapBundleImplArt: uses art provider to get the bitmaps
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class wxBitmapBundleImplArt : public wxBitmapBundleImpl
|
||||
{
|
||||
public:
|
||||
wxBitmapBundleImplArt(const wxArtID& id,
|
||||
const wxArtClient& client,
|
||||
const wxSize& size)
|
||||
: m_artId(id),
|
||||
m_artClient(client),
|
||||
m_sizeDefault(GetValidSize(id, client, size))
|
||||
{
|
||||
}
|
||||
|
||||
virtual wxSize GetDefaultSize() const wxOVERRIDE
|
||||
{
|
||||
return m_sizeDefault;
|
||||
}
|
||||
|
||||
virtual wxSize GetPreferredSizeAtScale(double scale) const wxOVERRIDE
|
||||
{
|
||||
// We have no preferred sizes.
|
||||
return m_sizeDefault*scale;
|
||||
}
|
||||
|
||||
virtual wxBitmap GetBitmap(const wxSize& size) wxOVERRIDE
|
||||
{
|
||||
return wxArtProvider::GetBitmap(m_artId, m_artClient, size);
|
||||
}
|
||||
|
||||
private:
|
||||
static wxSize GetValidSize(const wxArtID& id,
|
||||
const wxArtClient& client,
|
||||
const wxSize& size)
|
||||
{
|
||||
// If valid size is provided, just use it.
|
||||
if ( size != wxDefaultSize )
|
||||
return size;
|
||||
|
||||
// Otherwise, try to get the size we'd use without creating a bitmap
|
||||
// immediately.
|
||||
const wxSize sizeHint = wxArtProvider::GetSizeHint(client);
|
||||
if ( sizeHint != wxDefaultSize )
|
||||
return sizeHint;
|
||||
|
||||
// If we really have to, do create a bitmap just to get its size. Note
|
||||
// we need the size in logical pixels here, it will be scaled later if
|
||||
// necessary, so use GetScaledSize() and not GetSize().
|
||||
const wxBitmap bitmap = wxArtProvider::GetBitmap(id, client);
|
||||
if ( bitmap.IsOk() )
|
||||
return bitmap.GetDIPSize();
|
||||
|
||||
// We really need some default size, so just return this hardcoded
|
||||
// value if all else fails -- what else can we do.
|
||||
return wxSize(16, 16);
|
||||
}
|
||||
|
||||
const wxArtID m_artId;
|
||||
const wxArtClient m_artClient;
|
||||
const wxSize m_sizeDefault;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxBitmapBundleImplArt);
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// ============================================================================
|
||||
// wxArtProvider class
|
||||
// ============================================================================
|
||||
@@ -305,7 +376,7 @@ wxBitmapBundle wxArtProvider::GetBitmapBundle(const wxArtID& id,
|
||||
|
||||
wxCHECK_MSG( sm_providers, wxNullBitmap, wxT("no wxArtProvider exists") );
|
||||
|
||||
wxString hashId = wxArtProviderCache::ConstructHashID(id, client);
|
||||
wxString hashId = wxArtProviderCache::ConstructHashID(id, client, size);
|
||||
|
||||
wxBitmapBundle bitmapbundle; // (DoGetIconBundle(id, client));
|
||||
|
||||
@@ -325,6 +396,12 @@ wxBitmapBundle wxArtProvider::GetBitmapBundle(const wxArtID& id,
|
||||
return bitmapbundle;
|
||||
}
|
||||
|
||||
wxBitmapBundle wxArtProvider::CreateBitmapBundle(const wxArtID& id,
|
||||
const wxArtClient& client,
|
||||
const wxSize& size)
|
||||
{
|
||||
return wxBitmapBundle::FromImpl(new wxBitmapBundleImplArt(id, client, size));
|
||||
}
|
||||
|
||||
/*static*/
|
||||
wxIconBundle wxArtProvider::GetIconBundle(const wxArtID& id, const wxArtClient& client)
|
||||
|
||||
@@ -220,6 +220,13 @@ double wxBitmapBase::GetScaleFactor() const
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
wxSize wxBitmapBase::GetDIPSize() const
|
||||
{
|
||||
return GetSize() / GetScaleFactor();
|
||||
}
|
||||
|
||||
#ifdef wxHAS_DPI_INDEPENDENT_PIXELS
|
||||
|
||||
double wxBitmapBase::GetScaledWidth() const
|
||||
{
|
||||
return GetWidth() / GetScaleFactor();
|
||||
@@ -235,6 +242,25 @@ wxSize wxBitmapBase::GetScaledSize() const
|
||||
return wxSize(wxRound(GetScaledWidth()), wxRound(GetScaledHeight()));
|
||||
}
|
||||
|
||||
#else // !wxHAS_DPI_INDEPENDENT_PIXELS
|
||||
|
||||
double wxBitmapBase::GetScaledWidth() const
|
||||
{
|
||||
return GetWidth();
|
||||
}
|
||||
|
||||
double wxBitmapBase::GetScaledHeight() const
|
||||
{
|
||||
return GetHeight();
|
||||
}
|
||||
|
||||
wxSize wxBitmapBase::GetScaledSize() const
|
||||
{
|
||||
return GetSize();
|
||||
}
|
||||
|
||||
#endif // wxHAS_DPI_INDEPENDENT_PIXELS/!wxHAS_DPI_INDEPENDENT_PIXELS
|
||||
|
||||
#endif // wxUSE_BITMAP_BASE
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -361,7 +361,7 @@ void SetScaledScreenDCFont(wxScreenDC& sDC, const wxFont& font)
|
||||
{
|
||||
// When using DPI-independent pixels, the results of GetTextExtent() and
|
||||
// similar don't depend on DPI anyhow.
|
||||
#ifndef wxHAVE_DPI_INDEPENDENT_PIXELS
|
||||
#ifndef wxHAS_DPI_INDEPENDENT_PIXELS
|
||||
static const int SVG_DPI = 96;
|
||||
|
||||
const double screenDPI = sDC.GetPPI().y;
|
||||
@@ -380,7 +380,7 @@ void SetScaledScreenDCFont(wxScreenDC& sDC, const wxFont& font)
|
||||
sDC.SetFont(scaledFont);
|
||||
}
|
||||
else
|
||||
#endif // !wxHAVE_DPI_INDEPENDENT_PIXELS
|
||||
#endif // !wxHAS_DPI_INDEPENDENT_PIXELS
|
||||
{
|
||||
sDC.SetFont(font);
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ wxSize wxStaticBitmapBase::DoGetBestSize() const
|
||||
//
|
||||
// Note that we can use content scale factor rather than DPI scale
|
||||
// because the scaled size is the same as normal size on platforms
|
||||
// without wxHAVE_DPI_INDEPENDENT_PIXELS (e.g. wxMSW) anyhow.
|
||||
// without wxHAS_DPI_INDEPENDENT_PIXELS (e.g. wxMSW) anyhow.
|
||||
const wxSize size = m_bitmapBundle.GetPreferredSizeFor(this);
|
||||
const double scale = GetContentScaleFactor();
|
||||
|
||||
|
||||
@@ -2867,7 +2867,7 @@ wxSize wxWindowBase::GetDPI() const
|
||||
return wxDisplay(static_cast<const wxWindow*>(this)).GetPPI();
|
||||
}
|
||||
|
||||
#ifndef wxHAVE_DPI_INDEPENDENT_PIXELS
|
||||
#ifndef wxHAS_DPI_INDEPENDENT_PIXELS
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -2910,7 +2910,7 @@ wxWindowBase::ToDIP(const wxSize& sz, const wxWindowBase* w)
|
||||
return wxRescaleCoord(sz).From(dpi).To(baseline);
|
||||
}
|
||||
|
||||
#endif // !wxHAVE_DPI_INDEPENDENT_PIXELS
|
||||
#endif // !wxHAS_DPI_INDEPENDENT_PIXELS
|
||||
|
||||
// Windows' computes dialog units using average character width over upper-
|
||||
// and lower-case ASCII alphabet and not using the average character width
|
||||
|
||||
@@ -489,7 +489,7 @@ bool wxHtmlWindow::DoSetPage(const wxString& source)
|
||||
SetBackgroundImage(wxNullBitmap);
|
||||
|
||||
double pixelScale = 1.0;
|
||||
#ifndef wxHAVE_DPI_INDEPENDENT_PIXELS
|
||||
#ifndef wxHAS_DPI_INDEPENDENT_PIXELS
|
||||
pixelScale = GetDPIScaleFactor();
|
||||
#endif
|
||||
|
||||
|
||||
@@ -499,6 +499,8 @@ bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon,
|
||||
int w = icon.GetWidth(),
|
||||
h = icon.GetHeight();
|
||||
|
||||
refData->m_scaleFactor = icon.GetScaleFactor();
|
||||
|
||||
if ( iconInfo.hbmColor )
|
||||
{
|
||||
refData->m_width = w;
|
||||
@@ -1366,18 +1368,26 @@ bool wxBitmap::InitFromHBITMAP(WXHBITMAP bmp, int width, int height, int depth)
|
||||
// scale factor-related functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Note: currently we don't use scale factor at all and don't even store it
|
||||
// because this seems useless, but we define these functions out of line here
|
||||
// and not inline in the header to make it possible to change this later
|
||||
// without breaking ABI if necessary.
|
||||
// wxMSW doesn't really use scale factor, but we must still store it to use the
|
||||
// correct sizes in the code which uses it to decide on the bitmap size to use.
|
||||
|
||||
void wxBitmap::SetScaleFactor(double WXUNUSED(scale))
|
||||
void wxBitmap::SetScaleFactor(double scale)
|
||||
{
|
||||
wxCHECK_RET( IsOk(), wxT("invalid bitmap") );
|
||||
|
||||
GetBitmapData()->m_scaleFactor = scale;
|
||||
}
|
||||
|
||||
double wxBitmap::GetScaleFactor() const
|
||||
{
|
||||
return 1.0;
|
||||
wxCHECK_MSG( IsOk(), -1, wxT("invalid bitmap") );
|
||||
|
||||
return GetBitmapData()->m_scaleFactor;
|
||||
}
|
||||
|
||||
wxSize wxBitmap::GetDIPSize() const
|
||||
{
|
||||
return GetSize() / GetScaleFactor();
|
||||
}
|
||||
|
||||
double wxBitmap::GetScaledWidth() const
|
||||
|
||||
@@ -586,7 +586,26 @@ bool wxICOResourceHandler::LoadIcon(wxIcon *icon,
|
||||
}
|
||||
}
|
||||
|
||||
return icon->CreateFromHICON((WXHICON)hicon);
|
||||
if ( !hicon )
|
||||
return false;
|
||||
|
||||
wxSize size;
|
||||
double scale = 1.0;
|
||||
if ( hasSize )
|
||||
{
|
||||
size.x = desiredWidth;
|
||||
size.y = desiredHeight;
|
||||
}
|
||||
else // We loaded an icon of default size.
|
||||
{
|
||||
// LoadIcon() returns icons of scaled size, so we must use the correct
|
||||
// scaling factor of them.
|
||||
size = wxGetHiconSize(hicon);
|
||||
if ( const wxWindow* win = wxApp::GetMainTopWindow() )
|
||||
scale = win->GetDPIScaleFactor();
|
||||
}
|
||||
|
||||
return icon->InitFromHICON((WXHICON)hicon, size.x, size.y, scale);
|
||||
}
|
||||
|
||||
#if wxUSE_PNG_RESOURCE_HANDLER
|
||||
|
||||
@@ -154,7 +154,7 @@ bool wxIcon::CreateFromHICON(WXHICON icon)
|
||||
return InitFromHICON(icon, size.GetWidth(), size.GetHeight());
|
||||
}
|
||||
|
||||
bool wxIcon::InitFromHICON(WXHICON icon, int width, int height)
|
||||
bool wxIcon::InitFromHICON(WXHICON icon, int width, int height, double scale)
|
||||
{
|
||||
#if wxDEBUG_LEVEL >= 2
|
||||
if ( icon != NULL )
|
||||
@@ -170,6 +170,7 @@ bool wxIcon::InitFromHICON(WXHICON icon, int width, int height)
|
||||
GetGDIImageData()->m_handle = (WXHANDLE)icon;
|
||||
GetGDIImageData()->m_width = width;
|
||||
GetGDIImageData()->m_height = height;
|
||||
GetGDIImageData()->m_scaleFactor = scale;
|
||||
|
||||
return IsOk();
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ TEST_CASE("BitmapBundle::GetPreferredSize", "[bmpbundle]")
|
||||
CHECK( b.GetPreferredSizeAtScale(3 ) == 3*normal );
|
||||
}
|
||||
|
||||
#ifdef wxHAS_BITMAP_SCALE_FACTOR
|
||||
#ifdef wxHAS_DPI_INDEPENDENT_PIXELS
|
||||
|
||||
TEST_CASE("BitmapBundle::Scaled", "[bmpbundle]")
|
||||
{
|
||||
@@ -105,7 +105,7 @@ TEST_CASE("BitmapBundle::Scaled", "[bmpbundle]")
|
||||
CHECK( b.GetDefaultSize() == wxSize(32, 32) );
|
||||
}
|
||||
|
||||
#endif // wxHAS_BITMAP_SCALE_FACTOR
|
||||
#endif // wxHAS_DPI_INDEPENDENT_PIXELS
|
||||
|
||||
#ifdef wxHAS_SVG
|
||||
|
||||
|
||||
Reference in New Issue
Block a user