Merge branch 'aui-tabart-high-dpi-fix'

Improve AUI tabs appearance in high DPI: scale the bitmaps to have
correct physical size for the current resolution.

See https://github.com/wxWidgets/wxWidgets/pull/1602
This commit is contained in:
Vadim Zeitlin
2019-10-25 00:31:16 +02:00
3 changed files with 101 additions and 75 deletions

View File

@@ -634,7 +634,7 @@ wxSize wxAuiGenericToolBarArt::GetToolSize(
// and add some extra space in front of the drop down button
if (item.HasDropDown())
{
int dropdownWidth = wnd->FromDIP(GetElementSize(wxAUI_TBART_DROPDOWN_SIZE));
int dropdownWidth = GetElementSize(wxAUI_TBART_DROPDOWN_SIZE);
width += dropdownWidth + wnd->FromDIP(4);
}

View File

@@ -55,6 +55,7 @@
#endif
#endif
#include <math.h>
// -- wxAuiDefaultDockArt class implementation --
@@ -88,6 +89,25 @@ wxBitmap wxAuiBitmapFromBits(const unsigned char bits[], int w, int h,
return wxBitmap(img);
}
// A utility function to scales a bitmap in place for use at the given scale
// factor.
void wxAuiScaleBitmap(wxBitmap& bmp, double scale)
{
#if wxUSE_IMAGE && !defined(__WXGTK3__) && !defined(__WXMAC__)
// scale to a close round number to improve quality
scale = floor(scale + 0.25);
if (scale > 1.0 && !(bmp.GetScaleFactor() > 1.0))
{
wxImage img = bmp.ConvertToImage();
img.Rescale(bmp.GetWidth()*scale, bmp.GetHeight()*scale,
wxIMAGE_QUALITY_BOX_AVERAGE);
bmp = wxBitmap(img);
}
#else
wxUnusedVar(bmp);
wxUnusedVar(scale);
#endif // wxUSE_IMAGE
}
static void DrawGradientRectangle(wxDC& dc,
const wxRect& rect,
@@ -748,6 +768,7 @@ void wxAuiDefaultDockArt::DrawPaneButton(wxDC& dc,
break;
}
wxAuiScaleBitmap(bmp, window->GetContentScaleFactor());
wxRect rect = _rect;
@@ -774,10 +795,11 @@ void wxAuiDefaultDockArt::DrawPaneButton(wxDC& dc,
}
// draw the background behind the button
dc.DrawRectangle(rect.x, rect.y, 16-window->FromDIP(1), 16-window->FromDIP(1));
dc.DrawRectangle(rect.x, rect.y,
bmp.GetScaledWidth() - window->FromDIP(1),
bmp.GetScaledHeight() - window->FromDIP(1));
}
// draw the button itself
dc.DrawBitmap(bmp, rect.x, rect.y, true);
}

View File

@@ -72,6 +72,9 @@ private:
wxBitmap wxAuiBitmapFromBits(const unsigned char bits[], int w, int h,
const wxColour& color);
// This function is defined in dockart.cpp.
void wxAuiScaleBitmap(wxBitmap& bmp, double scale);
wxString wxAuiChopText(wxDC& dc, const wxString& text, int max_size);
static void DrawButtons(wxDC& dc,
@@ -96,7 +99,7 @@ static void DrawButtons(wxDC& dc,
dc.SetPen(wxPen(bkcolour.ChangeLightness(75)));
// draw the background behind the button
dc.DrawRectangle(rect.x, rect.y, 16-offset.x, 16-offset.y);
dc.DrawRectangle(rect.x, rect.y, bmp.GetScaledWidth()-offset.x, bmp.GetScaledHeight()-offset.y);
}
// draw the button itself
@@ -221,7 +224,7 @@ void wxAuiGenericTabArt::SetSizingInfo(const wxSize& tab_ctrl_size,
{
m_fixedTabWidth = wxWindow::FromDIP(100, NULL);
int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - 4;
int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - wxWindow::FromDIP(4, NULL);
if (m_flags & wxAUI_NB_CLOSE_BUTTON)
tot_width -= m_activeCloseBmp.GetScaledWidth();
@@ -528,16 +531,10 @@ void wxAuiGenericTabArt::DrawTab(wxDC& dc,
int text_offset;
int close_button_width = 0;
if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
{
close_button_width = m_activeCloseBmp.GetScaledWidth();
}
int bitmap_offset = 0;
if (page.bitmap.IsOk())
{
bitmap_offset = tab_x + 8;
bitmap_offset = tab_x + wnd->FromDIP(8);
// draw bitmap
dc.DrawBitmap(page.bitmap,
@@ -546,14 +543,42 @@ void wxAuiGenericTabArt::DrawTab(wxDC& dc,
true);
text_offset = bitmap_offset + page.bitmap.GetScaledWidth();
text_offset += 3; // bitmap padding
text_offset += wnd->FromDIP(3); // bitmap padding
}
else
{
text_offset = tab_x + 8;
text_offset = tab_x + wnd->FromDIP(8);
}
// draw close button if necessary
int close_button_width = 0;
if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
{
wxBitmap bmp = m_disabledCloseBmp;
if (close_button_state == wxAUI_BUTTON_STATE_HOVER ||
close_button_state == wxAUI_BUTTON_STATE_PRESSED)
{
bmp = m_activeCloseBmp;
}
wxAuiScaleBitmap(bmp, wnd->GetContentScaleFactor());
int offsetY = tab_y-1;
if (m_flags & wxAUI_NB_BOTTOM)
offsetY = 1;
wxRect rect(tab_x + tab_width - bmp.GetScaledWidth() - wnd->FromDIP(1),
offsetY + (tab_height/2) - (bmp.GetScaledHeight()/2),
bmp.GetScaledWidth(),
tab_height);
IndentPressedBitmap(wnd->FromDIP(wxSize(1, 1)), &rect, close_button_state);
dc.DrawBitmap(bmp, rect.x, rect.y, true);
*out_button_rect = rect;
close_button_width = bmp.GetScaledWidth();
}
wxString draw_text = wxAuiChopText(dc,
caption,
@@ -599,32 +624,6 @@ void wxAuiGenericTabArt::DrawTab(wxDC& dc,
wxRendererNative::Get().DrawFocusRect(wnd, dc, focusRect, 0);
}
// draw close button if necessary
if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
{
wxBitmap bmp = m_disabledCloseBmp;
if (close_button_state == wxAUI_BUTTON_STATE_HOVER ||
close_button_state == wxAUI_BUTTON_STATE_PRESSED)
{
bmp = m_activeCloseBmp;
}
int offsetY = tab_y-1;
if (m_flags & wxAUI_NB_BOTTOM)
offsetY = 1;
wxRect rect(tab_x + tab_width - close_button_width - 1,
offsetY + (tab_height/2) - (bmp.GetScaledHeight()/2),
close_button_width,
tab_height);
IndentPressedBitmap(wnd->FromDIP(wxSize(1, 1)), &rect, close_button_state);
dc.DrawBitmap(bmp, rect.x, rect.y, true);
*out_button_rect = rect;
}
*out_tab_rect = wxRect(tab_x, tab_y, tab_width, tab_height);
dc.DestroyClippingRegion();
@@ -640,7 +639,7 @@ int wxAuiGenericTabArt::GetBorderWidth(wxWindow* wnd)
wxAuiManager* mgr = wxAuiManager::GetManager(wnd);
if (mgr)
{
wxAuiDockArt* art = mgr->GetArtProvider();
wxAuiDockArt* art = mgr->GetArtProvider();
if (art)
return art->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE);
}
@@ -673,13 +672,16 @@ wxSize wxAuiGenericTabArt::GetTabSize(wxDC& dc,
// if the close button is showing, add space for it
if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
tab_width += m_activeCloseBmp.GetScaledWidth() + 3;
{
// increase by button size plus the padding
tab_width += m_activeCloseBmp.GetScaledWidth() + wnd->FromDIP(3);
}
// if there's a bitmap, add space for it
if (bitmap.IsOk())
{
tab_width += bitmap.GetScaledWidth();
tab_width += 3; // right side bitmap padding
// increase by bitmap plus right side bitmap padding
tab_width += bitmap.GetScaledWidth() + wnd->FromDIP(3);
tab_height = wxMax(tab_height, bitmap.GetScaledHeight());
}
@@ -742,6 +744,8 @@ void wxAuiGenericTabArt::DrawButton(wxDC& dc,
if (!bmp.IsOk())
return;
wxAuiScaleBitmap(bmp, wnd->GetContentScaleFactor());
rect = in_rect;
if (orientation == wxLEFT)
@@ -937,7 +941,7 @@ void wxAuiSimpleTabArt::SetSizingInfo(const wxSize& tab_ctrl_size,
{
m_fixedTabWidth = wxWindow::FromDIP(100, NULL);
int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - 4;
int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - wxWindow::FromDIP(4, NULL);
if (m_flags & wxAUI_NB_CLOSE_BUTTON)
tot_width -= m_activeCloseBmp.GetScaledWidth();
@@ -1097,16 +1101,30 @@ void wxAuiSimpleTabArt::DrawTab(wxDC& dc,
int text_offset;
int close_button_width = 0;
// draw close button if necessary
if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
{
close_button_width = m_activeCloseBmp.GetScaledWidth();
text_offset = tab_x + (tab_height/2) + ((tab_width-close_button_width)/2) - (textx/2);
}
else
{
text_offset = tab_x + (tab_height/3) + (tab_width/2) - (textx/2);
wxBitmap bmp;
if (page.active)
bmp = m_activeCloseBmp;
else
bmp = m_disabledCloseBmp;
wxAuiScaleBitmap(bmp, wnd->GetContentScaleFactor());
wxRect rect(tab_x + tab_width - bmp.GetScaledWidth() - 1,
tab_y + (tab_height/2) - (bmp.GetScaledHeight()/2) + 1,
bmp.GetScaledWidth(),
tab_height - 1);
DrawButtons(dc, wnd->FromDIP(wxSize(1, 1)), rect, bmp, *wxWHITE, close_button_state);
*out_button_rect = rect;
close_button_width = bmp.GetScaledWidth();
}
text_offset = tab_x + (tab_height/2) + ((tab_width-close_button_width)/2) - (textx/2);
// set minimum text offset
if (text_offset < tab_x + tab_height)
text_offset = tab_x + tab_height;
@@ -1133,25 +1151,6 @@ void wxAuiSimpleTabArt::DrawTab(wxDC& dc,
wxRendererNative::Get().DrawFocusRect(wnd, dc, focusRect, 0);
}
// draw close button if necessary
if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
{
wxBitmap bmp;
if (page.active)
bmp = m_activeCloseBmp;
else
bmp = m_disabledCloseBmp;
wxRect rect(tab_x + tab_width - close_button_width - 1,
tab_y + (tab_height/2) - (bmp.GetScaledHeight()/2) + 1,
close_button_width,
tab_height - 1);
DrawButtons(dc, wnd->FromDIP(wxSize(1, 1)), rect, bmp, *wxWHITE, close_button_state);
*out_button_rect = rect;
}
*out_tab_rect = wxRect(tab_x, tab_y, tab_width, tab_height);
dc.DestroyClippingRegion();
@@ -1180,7 +1179,7 @@ int wxAuiSimpleTabArt::GetAdditionalBorderSpace(wxWindow* WXUNUSED(wnd))
}
wxSize wxAuiSimpleTabArt::GetTabSize(wxDC& dc,
wxWindow* WXUNUSED(wnd),
wxWindow* wnd,
const wxString& caption,
const wxBitmap& WXUNUSED(bitmap),
bool WXUNUSED(active),
@@ -1192,11 +1191,14 @@ wxSize wxAuiSimpleTabArt::GetTabSize(wxDC& dc,
dc.SetFont(m_measuringFont);
dc.GetTextExtent(caption, &measured_textx, &measured_texty);
wxCoord tab_height = measured_texty + 4;
wxCoord tab_width = measured_textx + tab_height + 5;
wxCoord tab_height = measured_texty + wnd->FromDIP(4);
wxCoord tab_width = measured_textx + tab_height + wnd->FromDIP(5);
if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
tab_width += m_activeCloseBmp.GetScaledWidth();
{
// increase by button size plus the padding
tab_width += m_activeCloseBmp.GetScaledWidth() + wnd->FromDIP(3);
}
if (m_flags & wxAUI_NB_TAB_FIXED_WIDTH)
{
@@ -1251,6 +1253,8 @@ void wxAuiSimpleTabArt::DrawButton(wxDC& dc,
if (!bmp.IsOk())
return;
wxAuiScaleBitmap(bmp, wnd->GetContentScaleFactor());
rect = in_rect;
if (orientation == wxLEFT)