Add wxRendererNative implementation for wxQt

Closes #24223.
This commit is contained in:
ali kettab 2024-01-17 14:07:27 +01:00 committed by Vadim Zeitlin
parent 1b4dfc292a
commit 9e61385878
7 changed files with 848 additions and 5 deletions

View file

@ -5551,7 +5551,8 @@ COND_TOOLKIT_QT___GUI_SRC_OBJECTS = \
monodll_paletteg.o \ monodll_paletteg.o \
monodll_qt_datectrl.o \ monodll_qt_datectrl.o \
monodll_qt_timectrl.o \ monodll_qt_timectrl.o \
monodll_qt_overlay.o monodll_qt_overlay.o \
monodll_qt_renderer.o
@COND_TOOLKIT_QT@__GUI_SRC_OBJECTS = $(COND_TOOLKIT_QT___GUI_SRC_OBJECTS) @COND_TOOLKIT_QT@__GUI_SRC_OBJECTS = $(COND_TOOLKIT_QT___GUI_SRC_OBJECTS)
@COND_PLATFORM_UNIX_1@__QT_PLATFORM_SRC_OBJECTS = \ @COND_PLATFORM_UNIX_1@__QT_PLATFORM_SRC_OBJECTS = \
@COND_PLATFORM_UNIX_1@ monodll_unix_dialup.o monodll_unix_joystick.o \ @COND_PLATFORM_UNIX_1@ monodll_unix_dialup.o monodll_unix_joystick.o \
@ -7317,7 +7318,8 @@ COND_TOOLKIT_QT___GUI_SRC_OBJECTS_1 = \
monolib_paletteg.o \ monolib_paletteg.o \
monolib_qt_datectrl.o \ monolib_qt_datectrl.o \
monolib_qt_timectrl.o \ monolib_qt_timectrl.o \
monolib_qt_overlay.o monolib_qt_overlay.o \
monolib_qt_renderer.o
@COND_TOOLKIT_QT@__GUI_SRC_OBJECTS_1 = $(COND_TOOLKIT_QT___GUI_SRC_OBJECTS_1) @COND_TOOLKIT_QT@__GUI_SRC_OBJECTS_1 = $(COND_TOOLKIT_QT___GUI_SRC_OBJECTS_1)
@COND_PLATFORM_UNIX_1@__QT_PLATFORM_SRC_OBJECTS_1 = \ @COND_PLATFORM_UNIX_1@__QT_PLATFORM_SRC_OBJECTS_1 = \
@COND_PLATFORM_UNIX_1@ monolib_unix_dialup.o monolib_unix_joystick.o \ @COND_PLATFORM_UNIX_1@ monolib_unix_dialup.o monolib_unix_joystick.o \
@ -9234,7 +9236,8 @@ COND_TOOLKIT_QT___GUI_SRC_OBJECTS_2 = \
coredll_paletteg.o \ coredll_paletteg.o \
coredll_qt_datectrl.o \ coredll_qt_datectrl.o \
coredll_qt_timectrl.o \ coredll_qt_timectrl.o \
coredll_qt_overlay.o coredll_qt_overlay.o \
coredll_qt_renderer.o
@COND_TOOLKIT_QT@__GUI_SRC_OBJECTS_2 = $(COND_TOOLKIT_QT___GUI_SRC_OBJECTS_2) @COND_TOOLKIT_QT@__GUI_SRC_OBJECTS_2 = $(COND_TOOLKIT_QT___GUI_SRC_OBJECTS_2)
@COND_PLATFORM_UNIX_1@__QT_PLATFORM_SRC_OBJECTS_2 = \ @COND_PLATFORM_UNIX_1@__QT_PLATFORM_SRC_OBJECTS_2 = \
@COND_PLATFORM_UNIX_1@ coredll_unix_dialup.o coredll_unix_joystick.o \ @COND_PLATFORM_UNIX_1@ coredll_unix_dialup.o coredll_unix_joystick.o \
@ -10726,7 +10729,8 @@ COND_TOOLKIT_QT___GUI_SRC_OBJECTS_3 = \
corelib_paletteg.o \ corelib_paletteg.o \
corelib_qt_datectrl.o \ corelib_qt_datectrl.o \
corelib_qt_timectrl.o \ corelib_qt_timectrl.o \
corelib_qt_overlay.o corelib_qt_overlay.o \
corelib_qt_renderer.o
@COND_TOOLKIT_QT@__GUI_SRC_OBJECTS_3 = $(COND_TOOLKIT_QT___GUI_SRC_OBJECTS_3) @COND_TOOLKIT_QT@__GUI_SRC_OBJECTS_3 = $(COND_TOOLKIT_QT___GUI_SRC_OBJECTS_3)
@COND_PLATFORM_UNIX_1@__QT_PLATFORM_SRC_OBJECTS_3 = \ @COND_PLATFORM_UNIX_1@__QT_PLATFORM_SRC_OBJECTS_3 = \
@COND_PLATFORM_UNIX_1@ corelib_unix_dialup.o corelib_unix_joystick.o \ @COND_PLATFORM_UNIX_1@ corelib_unix_dialup.o corelib_unix_joystick.o \
@ -15833,6 +15837,9 @@ monodll_qt_timectrl.o: $(srcdir)/src/qt/timectrl.cpp $(MONODLL_ODEP)
monodll_qt_overlay.o: $(srcdir)/src/qt/overlay.cpp $(MONODLL_ODEP) monodll_qt_overlay.o: $(srcdir)/src/qt/overlay.cpp $(MONODLL_ODEP)
$(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/qt/overlay.cpp $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/qt/overlay.cpp
monodll_qt_renderer.o: $(srcdir)/src/qt/renderer.cpp $(MONODLL_ODEP)
$(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/qt/renderer.cpp
monodll_mdig.o: $(srcdir)/src/generic/mdig.cpp $(MONODLL_ODEP) monodll_mdig.o: $(srcdir)/src/generic/mdig.cpp $(MONODLL_ODEP)
$(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/generic/mdig.cpp $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/generic/mdig.cpp
@ -20588,6 +20595,9 @@ monolib_qt_timectrl.o: $(srcdir)/src/qt/timectrl.cpp $(MONOLIB_ODEP)
monolib_qt_overlay.o: $(srcdir)/src/qt/overlay.cpp $(MONOLIB_ODEP) monolib_qt_overlay.o: $(srcdir)/src/qt/overlay.cpp $(MONOLIB_ODEP)
$(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/qt/overlay.cpp $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/qt/overlay.cpp
monolib_qt_renderer.o: $(srcdir)/src/qt/renderer.cpp $(MONOLIB_ODEP)
$(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/qt/renderer.cpp
monolib_mdig.o: $(srcdir)/src/generic/mdig.cpp $(MONOLIB_ODEP) monolib_mdig.o: $(srcdir)/src/generic/mdig.cpp $(MONOLIB_ODEP)
$(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/generic/mdig.cpp $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/generic/mdig.cpp
@ -26024,6 +26034,9 @@ coredll_qt_timectrl.o: $(srcdir)/src/qt/timectrl.cpp $(COREDLL_ODEP)
coredll_qt_overlay.o: $(srcdir)/src/qt/overlay.cpp $(COREDLL_ODEP) coredll_qt_overlay.o: $(srcdir)/src/qt/overlay.cpp $(COREDLL_ODEP)
$(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/qt/overlay.cpp $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/qt/overlay.cpp
coredll_qt_renderer.o: $(srcdir)/src/qt/renderer.cpp $(COREDLL_ODEP)
$(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/qt/renderer.cpp
coredll_mdig.o: $(srcdir)/src/generic/mdig.cpp $(COREDLL_ODEP) coredll_mdig.o: $(srcdir)/src/generic/mdig.cpp $(COREDLL_ODEP)
$(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/generic/mdig.cpp $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/generic/mdig.cpp
@ -29744,6 +29757,9 @@ corelib_qt_timectrl.o: $(srcdir)/src/qt/timectrl.cpp $(CORELIB_ODEP)
corelib_qt_overlay.o: $(srcdir)/src/qt/overlay.cpp $(CORELIB_ODEP) corelib_qt_overlay.o: $(srcdir)/src/qt/overlay.cpp $(CORELIB_ODEP)
$(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/qt/overlay.cpp $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/qt/overlay.cpp
corelib_qt_renderer.o: $(srcdir)/src/qt/renderer.cpp $(CORELIB_ODEP)
$(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/qt/renderer.cpp
corelib_mdig.o: $(srcdir)/src/generic/mdig.cpp $(CORELIB_ODEP) corelib_mdig.o: $(srcdir)/src/generic/mdig.cpp $(CORELIB_ODEP)
$(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/generic/mdig.cpp $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/generic/mdig.cpp

View file

@ -478,6 +478,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
src/qt/datectrl.cpp src/qt/datectrl.cpp
src/qt/timectrl.cpp src/qt/timectrl.cpp
src/qt/overlay.cpp src/qt/overlay.cpp
src/qt/renderer.cpp
</set> </set>
<set var="MEDIA_QT_SRC" hints="files"> <set var="MEDIA_QT_SRC" hints="files">

View file

@ -391,6 +391,7 @@ set(QT_SRC
src/qt/datectrl.cpp src/qt/datectrl.cpp
src/qt/timectrl.cpp src/qt/timectrl.cpp
src/qt/overlay.cpp src/qt/overlay.cpp
src/qt/renderer.cpp
) )
set(MEDIA_QT_SRC set(MEDIA_QT_SRC

View file

@ -387,6 +387,7 @@ QT_SRC=
src/qt/radiobox.cpp src/qt/radiobox.cpp
src/qt/radiobut.cpp src/qt/radiobut.cpp
src/qt/region.cpp src/qt/region.cpp
src/qt/renderer.cpp
src/qt/scrolbar.cpp src/qt/scrolbar.cpp
src/qt/settings.cpp src/qt/settings.cpp
src/qt/slider.cpp src/qt/slider.cpp

View file

@ -33,7 +33,8 @@ class WXDLLIMPEXP_FWD_CORE wxWindow;
#include "wx/string.h" #include "wx/string.h"
// some platforms have their own renderers, others use the generic one // some platforms have their own renderers, others use the generic one
#if defined(__WXMSW__) || ( defined(__WXMAC__) && wxOSX_USE_COCOA_OR_CARBON ) || defined(__WXGTK__) #if defined(__WXMSW__) || ( defined(__WXMAC__) && wxOSX_USE_COCOA_OR_CARBON ) || \
defined(__WXGTK__) || defined(__WXQT__)
#define wxHAS_NATIVE_RENDERER #define wxHAS_NATIVE_RENDERER
#else #else
#undef wxHAS_NATIVE_RENDERER #undef wxHAS_NATIVE_RENDERER

View file

@ -383,6 +383,12 @@ private:
else else
renderer.DrawChoice(this, dc, renderer.DrawChoice(this, dc,
wxRect(x2, y, width, GetCharHeight() * 3 / 2), m_flags); wxRect(x2, y, width, GetCharHeight() * 3 / 2), m_flags);
y += lineHeight + heightGauge;
dc.DrawText("DrawTextCtrl()", x1, y);
renderer.DrawTextCtrl(this, dc,
wxRect(x2, y, width, GetCharHeight() * 3 / 2), m_flags);
} }
int m_flags; int m_flags;

817
src/qt/renderer.cpp Normal file
View file

@ -0,0 +1,817 @@
///////////////////////////////////////////////////////////////////////////////
// Name: src/qt/renderer.cpp
// Purpose: implementation of wxRendererNative for wxQt
// Author: Kettab Ali
// Created: 2024-01-08
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// for compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#include "wx/renderer.h"
#ifndef WX_PRECOMP
#include "wx/window.h"
#include "wx/dcclient.h"
#endif
#include "wx/headerctrl.h" // for wxHD_BITMAP_ON_RIGHT
#include "wx/qt/private/converter.h"
#include <QtGui/QPainter>
#include <QtWidgets/QStyle>
#include <QtWidgets/QStyleOptionButton>
#include <QtWidgets/QStyleOptionFrame>
#include <QtWidgets/QStyleOptionHeader>
namespace
{
bool wxIsKDEDesktop()
{
wxString de = wxGetenv(wxS("XDG_CURRENT_DESKTOP"));
if ( !de.empty() )
{
// Can be a colon separated list according to
// https://wiki.archlinux.org/title/Environment_variables#Examples
de = de.BeforeFirst(':');
}
de.MakeUpper();
return de.Contains(wxS("KDE"));
}
}
// ----------------------------------------------------------------------------
// wxRendererQt: our wxRendererNative implementation
// ----------------------------------------------------------------------------
class WXDLLEXPORT wxRendererQt : public wxDelegateRendererNative
{
public:
// draw the header control button (used by wxDataViewCtrl)
virtual int DrawHeaderButton(wxWindow *win,
wxDC& dc,
const wxRect& rect,
int flags = 0,
wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
wxHeaderButtonParams* params = nullptr) override;
virtual int GetHeaderButtonHeight(wxWindow *win) override;
virtual int GetHeaderButtonMargin(wxWindow *win) override;
// draw the expanded/collapsed icon for a tree control item
virtual void DrawTreeItemButton(wxWindow *win,
wxDC& dc,
const wxRect& rect,
int flags = 0) override;
virtual void DrawSplitterBorder(wxWindow *win,
wxDC& dc,
const wxRect& rect,
int flags = 0) override;
virtual void DrawSplitterSash(wxWindow *win,
wxDC& dc,
const wxSize& size,
wxCoord position,
wxOrientation orient,
int flags = 0) override;
virtual void DrawCheckBox(wxWindow *win,
wxDC& dc,
const wxRect& rect,
int flags = 0) override;
virtual void DrawCheckMark(wxWindow *win,
wxDC& dc,
const wxRect& rect,
int flags = 0) override;
virtual wxSize GetCheckMarkSize(wxWindow *win) override;
virtual void DrawPushButton(wxWindow *win,
wxDC& dc,
const wxRect& rect,
int flags = 0) override;
virtual void DrawItemSelectionRect(wxWindow *win,
wxDC& dc,
const wxRect& rect,
int flags = 0) override;
virtual void DrawChoice(wxWindow* win,
wxDC& dc,
const wxRect& rect,
int flags = 0) override;
virtual void DrawComboBox(wxWindow* win,
wxDC& dc,
const wxRect& rect,
int flags = 0) override;
virtual void DrawGauge(wxWindow* win,
wxDC& dc,
const wxRect& rect,
int value,
int max,
int flags = 0);
virtual void DrawRadioBitmap(wxWindow* win,
wxDC& dc,
const wxRect& rect,
int flags = 0 ) override;
virtual void DrawTextCtrl(wxWindow* win,
wxDC& dc,
const wxRect& rect,
int flags = 0) override;
virtual void DrawFocusRect(wxWindow* win,
wxDC& dc,
const wxRect& rect,
int flags = 0) override;
virtual wxSize GetCheckBoxSize(wxWindow *win, int flags = 0) override;
virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win) override;
// Common code for DrawComboBox() and DrawChoice()
void DoDrawComboBox(wxWindow* win,
wxDC& dc,
const wxRect& rect,
int flags, bool editable = true);
};
// ============================================================================
// implementation
// ============================================================================
/* static */
wxRendererNative& wxRendererNative::GetDefault()
{
static wxRendererQt s_rendererQt;
return s_rendererQt;
}
static QPainter* wxGetQtPainter(const wxDC& dc)
{
return static_cast<QPainter*>(dc.GetHandle());
}
// ----------------------------------------------------------------------------
// list/tree controls drawing
// ----------------------------------------------------------------------------
int
wxRendererQt::DrawHeaderButton(wxWindow *win, wxDC& dc, const wxRect& rect, int flags,
wxHeaderSortIconType sortArrow, wxHeaderButtonParams* params)
{
auto painter = wxGetQtPainter(dc);
wxCHECK_MSG( painter, 0, "Invalid painter!" );
wxDCClipper clip(dc, rect);
auto qtWidget = win->GetHandle();
auto qtStyle = qtWidget->style();
int margin = qtStyle->pixelMetric(QStyle::PM_HeaderMargin, nullptr, qtWidget);
int bestWidth = qtStyle->pixelMetric(QStyle::PM_HeaderDefaultSectionSizeHorizontal, nullptr, qtWidget)
+ 2 * margin;
QStyleOptionHeader option;
option.initFrom(qtWidget);
option.rect = wxQtConvertRect(rect);
if ( flags & wxCONTROL_DISABLED )
{
option.palette.setCurrentColorGroup(QPalette::Disabled);
}
else
{
option.state = QStyle::State_Enabled;
if ( flags & wxCONTROL_CURRENT )
option.state |= QStyle::State_MouseOver;
if ( flags & wxCONTROL_SELECTED )
option.state |= QStyle::State_Sunken;
}
if ( params )
{
option.text = wxQtConvertString(params->m_labelText);
if ( params->m_labelColour.IsOk() )
{
option.palette.setColor(QPalette::WindowText,
wxQtConvertColour(params->m_labelColour));
}
if ( params->m_labelFont.IsOk() )
{
option.fontMetrics = QFontMetrics(params->m_labelFont.GetHandle());
}
switch ( params->m_labelAlignment )
{
default:
case wxALIGN_LEFT:
option.textAlignment = Qt::AlignLeft;
break;
case wxALIGN_CENTER:
option.textAlignment = Qt::AlignHCenter;
break;
case wxALIGN_RIGHT:
option.textAlignment = Qt::AlignRight;
break;
}
if ( params->m_labelBitmap.IsOk() )
{
option.icon = *params->m_labelBitmap.GetHandle();
option.iconAlignment = Qt::AlignVCenter;
if ( win->HasFlag(wxHD_BITMAP_ON_RIGHT) )
option.iconAlignment |= Qt::AlignRight;
bestWidth += qtStyle->pixelMetric(QStyle::PM_SmallIconSize, nullptr, qtWidget);
}
bestWidth = wxMax(bestWidth, option.fontMetrics.boundingRect(option.text).width());
}
#if 0
if ( sortArrow != wxHDR_SORT_ICON_NONE )
{
// May or may not be a bug, but this makes drawControl(QStyle::CE_Header, ...)
// below not draw anything at all under non-KDE desktops! So we'll draw the sort
// indicator ourselves later.
option.sortIndicator = (sortArrow == wxHDR_SORT_ICON_UP)
? QStyleOptionHeader::SortUp
: QStyleOptionHeader::SortDown;
}
#endif
qtStyle->drawControl(QStyle::CE_Header, &option, painter, qtWidget);
if ( sortArrow != wxHDR_SORT_ICON_NONE )
{
option.sortIndicator = (sortArrow == wxHDR_SORT_ICON_UP)
? QStyleOptionHeader::SortUp
: QStyleOptionHeader::SortDown;
const int markSize = qtStyle->pixelMetric(QStyle::PM_HeaderMarkSize, nullptr, qtWidget);
bestWidth += markSize;
// Adjust the rect for the arrow
option.rect.setSize(QSize(markSize, markSize));
option.rect.moveTo(rect.x + rect.width - markSize - margin,
(rect.height - markSize) / 2 );
qtStyle->drawPrimitive(QStyle::PE_IndicatorHeaderArrow, &option, painter, qtWidget);
}
return bestWidth;
}
int wxRendererQt::GetHeaderButtonHeight(wxWindow* win)
{
auto qtWidget = win->GetHandle();
auto qtStyle = qtWidget->style();
QStyleOptionHeader option;
option.initFrom(qtWidget);
const auto size =
qtStyle->sizeFromContents(QStyle::CT_HeaderSection, &option, QSize(), qtWidget);
return size.height();
}
int wxRendererQt::GetHeaderButtonMargin(wxWindow* win)
{
auto qtWidget = win->GetHandle();
auto qtStyle = qtWidget->style();
return qtStyle->pixelMetric(QStyle::PM_HeaderGripMargin, nullptr, qtWidget);
}
// draw a ">" or "v" button
void
wxRendererQt::DrawTreeItemButton(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
{
auto painter = wxGetQtPainter(dc);
wxCHECK_RET( painter, "Invalid painter!" );
wxDCClipper clip(dc, rect);
auto qtWidget = win->GetHandle();
auto qtStyle = qtWidget->style();
QStyleOption option;
option.initFrom(qtWidget);
option.rect = wxQtConvertRect(rect);
option.state = QStyle::State_Children;
if ( flags & wxCONTROL_EXPANDED )
option.state |= QStyle::State_Open;
qtStyle->drawPrimitive(QStyle::PE_IndicatorBranch, &option, painter, qtWidget);
}
// ----------------------------------------------------------------------------
// splitter sash drawing
// ----------------------------------------------------------------------------
wxSplitterRenderParams
wxRendererQt::GetSplitterParams(const wxWindow* win)
{
auto qtWidget = win->GetHandle();
auto qtStyle = qtWidget->style();
QStyleOption option;
option.initFrom(qtWidget);
// Narrow handles don't work well with wxSplitterWindow
const int handle_size =
wxMax(5, qtStyle->pixelMetric(QStyle::PM_SplitterWidth, &option, qtWidget));
// we don't draw any border, hence 0 for the second field
return wxSplitterRenderParams
(
handle_size,
0,
true // hot sensitive
);
}
void
wxRendererQt::DrawSplitterBorder(wxWindow * WXUNUSED(win),
wxDC& WXUNUSED(dc),
const wxRect& WXUNUSED(rect),
int WXUNUSED(flags))
{
// nothing to do
}
void
wxRendererQt::DrawSplitterSash(wxWindow* win, wxDC& dc, const wxSize& size,
wxCoord position, wxOrientation orient, int flags)
{
auto painter = wxGetQtPainter(dc);
wxCHECK_RET( painter, "Invalid painter!" );
auto qtWidget = win->GetHandle();
auto qtStyle = qtWidget->style();
const int handle_size = GetSplitterParams(win).widthSash;
wxRect rect;
if ( orient == wxVERTICAL )
{
rect.x = position;
rect.y = 0;
rect.width = handle_size;
rect.height = size.y;
}
else // horz
{
rect.x = 0;
rect.y = position;
rect.height = handle_size;
rect.width = size.x;
}
wxDCClipper clip(dc, rect);
QStyleOption option;
option.initFrom(qtWidget);
option.rect = wxQtConvertRect(rect);
if ( orient == wxVERTICAL )
option.state = QStyle::State_Horizontal;
else
option.state = QStyle::State_None;
option.state |= QStyle::State_Enabled;
if ( flags & wxCONTROL_CURRENT )
option.state |= QStyle::State_MouseOver;
else if ( flags & wxCONTROL_PRESSED )
option.state |= QStyle::State_Sunken;
qtStyle->drawControl(QStyle::CE_Splitter, &option, painter, qtWidget);
}
wxSize
wxRendererQt::GetCheckBoxSize(wxWindow* win, int WXUNUSED(flags))
{
auto qtWidget = win->GetHandle();
auto qtStyle = qtWidget->style();
QStyleOptionButton option;
option.initFrom(qtWidget);
const auto qtRect = qtStyle->subElementRect(QStyle::SE_CheckBoxIndicator, &option);
return wxQtConvertSize( qtRect.size() );
}
void
wxRendererQt::DrawCheckBox(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
{
auto painter = wxGetQtPainter(dc);
wxCHECK_RET( painter, "Invalid painter!" );
wxDCClipper clip(dc, rect);
auto qtWidget = win->GetHandle();
auto qtStyle = qtWidget->style();
QStyleOptionButton option;
option.initFrom(qtWidget);
option.rect = wxQtConvertRect(rect);
if ( flags & wxCONTROL_DISABLED )
{
option.state = QStyle::State_None;
option.palette.setCurrentColorGroup(QPalette::Disabled);
}
else
{
option.state = QStyle::State_Enabled;
if ( flags & wxCONTROL_CURRENT )
option.state |= QStyle::State_MouseOver;
if ( flags & wxCONTROL_FOCUSED )
option.state |= QStyle::State_HasFocus;
if ( flags & wxCONTROL_PRESSED )
option.state |= QStyle::State_Sunken;
else
option.state |= QStyle::State_Raised;
}
if ( flags & wxCONTROL_UNDETERMINED )
option.state |= QStyle::State_NoChange;
else if ( flags & wxCONTROL_CHECKED )
option.state |= QStyle::State_On;
else
option.state |= QStyle::State_Off;
qtStyle->drawControl(QStyle::CE_CheckBox, &option, painter, qtWidget);
}
wxSize
wxRendererQt::GetCheckMarkSize(wxWindow* win)
{
return wxSize(win->GetCharWidth(),
win->GetCharHeight());
}
void
wxRendererQt::DrawCheckMark(wxWindow *win, wxDC& dc, const wxRect& rect, int WXUNUSED(flags))
{
wxDCClipper clip(dc, rect);
wxDCFontChanger fontChanger(dc, win->GetFont());
// Draw the unicode character “✓” (U+2713)
const auto checkMark = wxString::FromUTF8("\xE2\x9C\x93");
dc.DrawText(checkMark, rect.GetPosition());
}
void
wxRendererQt::DrawPushButton(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
{
auto painter = wxGetQtPainter(dc);
wxCHECK_RET( painter, "Invalid painter!" );
wxDCClipper clip(dc, rect);
auto qtWidget = win->GetHandle();
auto qtStyle = qtWidget->style();
QStyleOptionButton option;
option.initFrom(qtWidget);
option.rect = wxQtConvertRect(rect);
if ( flags & wxCONTROL_DISABLED )
{
option.state = QStyle::State_None;
option.palette.setCurrentColorGroup(QPalette::Disabled);
}
else
{
option.state = QStyle::State_Enabled;
if ( flags & wxCONTROL_CURRENT )
option.state |= QStyle::State_MouseOver;
if ( flags & wxCONTROL_PRESSED )
option.state |= QStyle::State_Sunken;
else
option.state |= QStyle::State_Raised;
}
qtStyle->drawControl(QStyle::CE_PushButton, &option, painter, qtWidget);
}
void
wxRendererQt::DrawItemSelectionRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
{
auto painter = wxGetQtPainter(dc);
wxCHECK_RET( painter, "Invalid painter!" );
wxDCClipper clip(dc, rect);
auto qtWidget = win->GetHandle();
auto qtStyle = qtWidget->style();
QStyleOptionViewItem option;
option.initFrom(qtWidget);
option.rect = wxQtConvertRect(rect);
if ( flags & wxCONTROL_SELECTED )
{
option.state = QStyle::State_Selected;
option.showDecorationSelected = true;
}
qtStyle->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, qtWidget);
}
void
wxRendererQt::DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int WXUNUSED(flags))
{
auto painter = wxGetQtPainter(dc);
wxCHECK_RET( painter, "Invalid painter!" );
wxDCClipper clip(dc, rect);
auto qtWidget = win->GetHandle();
auto qtStyle = qtWidget->style();
QStyleOptionFocusRect option;
option.initFrom(qtWidget);
option.rect = wxQtConvertRect(rect);
option.backgroundColor = wxQtConvertColour(win->GetBackgroundColour());
option.state = QStyle::State_FocusAtBorder | QStyle::State_HasFocus;
qtStyle->drawPrimitive(QStyle::PE_FrameFocusRect, &option, painter, qtWidget);
}
void
wxRendererQt::DrawGauge(wxWindow* win, wxDC& dc, const wxRect& rect,
int value, int max, int flags)
{
auto painter = wxGetQtPainter(dc);
wxCHECK_RET( painter, "Invalid painter!" );
const bool isKDE = wxIsKDEDesktop();
wxDCClipper clip(dc, rect);
auto qtWidget = win->GetHandle();
auto qtStyle = qtWidget->style();
QStyleOptionProgressBar option;
option.initFrom(qtWidget);
option.rect = wxQtConvertRect(rect);
option.minimum = 0;
option.maximum = max;
option.progress = value;
if ( flags & wxCONTROL_DISABLED )
{
option.state = QStyle::State_None;
option.palette.setCurrentColorGroup(QPalette::Disabled);
}
else
{
option.state = QStyle::State_Enabled;
if ( flags & wxCONTROL_CURRENT )
option.state |= QStyle::State_MouseOver;
}
if ( flags & wxCONTROL_SPECIAL )
{
if ( isKDE )
option.orientation = Qt::Vertical;
}
else
{
option.state |= QStyle::State_Horizontal;
}
if ( isKDE )
{
qtStyle->drawControl(QStyle::CE_ProgressBar, &option, painter, qtWidget);
}
else
{
qtStyle->drawControl(QStyle::CE_ProgressBarGroove, &option, painter, qtWidget);
if ( !(flags & wxCONTROL_SPECIAL) )
{
qtStyle->drawControl(QStyle::CE_ProgressBarContents, &option, painter, qtWidget);
return;
}
option.rect = option.rect.transposed();
option.invertedAppearance = true;
const auto& r = option.rect;
painter->save();
auto m = painter->worldTransform();
painter->resetTransform();
painter->translate(option.rect.topLeft());
painter->rotate(90);
painter->translate(-r.topLeft() - QPoint(0, r.height()));
painter->setWorldTransform(m, true);
qtStyle->drawControl(QStyle::CE_ProgressBarContents, &option, painter, qtWidget);
painter->restore();
}
}
void
wxRendererQt::DoDrawComboBox(wxWindow* win, wxDC& dc, const wxRect& origRect,
int flags, bool editable)
{
auto painter = wxGetQtPainter(dc);
wxCHECK_RET( painter, "Invalid painter!" );
// Under Xfce and Ubuntu Budgie desktops, the control cannot be rendered
// outside a predefined rectangle positioned at (0, 0). So we need to reset
// the position of the rect here and reposition the control later.
wxRect rect = origRect;
rect.SetPosition(wxPoint(0, 0));
auto qtWidget = win->GetHandle();
auto qtStyle = qtWidget->style();
QStyleOptionComboBox option;
option.initFrom(qtWidget);
option.rect = wxQtConvertRect(rect);
option.editable = editable;
option.frame = true;
option.activeSubControls = QStyle::SC_ComboBoxEditField;
if ( flags & wxCONTROL_DISABLED )
{
option.state = QStyle::State_None;
option.palette.setCurrentColorGroup(QPalette::Disabled);
}
else
{
option.state = QStyle::State_Enabled;
if ( flags & wxCONTROL_CURRENT )
option.state |= QStyle::State_MouseOver;
if ( flags & wxCONTROL_FOCUSED )
option.state |= QStyle::State_HasFocus;
if ( flags & wxCONTROL_PRESSED )
option.state |= QStyle::State_Sunken;
}
painter->save();
painter->translate(wxQtConvertPoint(origRect.GetPosition()));
qtStyle->drawComplexControl(QStyle::CC_ComboBox, &option, painter, qtWidget);
painter->restore();
}
void wxRendererQt::DrawComboBox(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
{
DoDrawComboBox(win, dc, rect, flags);
}
void wxRendererQt::DrawChoice(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
{
DoDrawComboBox(win, dc, rect, flags, false);
}
void
wxRendererQt::DrawRadioBitmap(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
{
auto painter = wxGetQtPainter(dc);
wxCHECK_RET( painter, "Invalid painter!" );
wxDCClipper clip(dc, rect);
auto qtWidget = win->GetHandle();
auto qtStyle = qtWidget->style();
QStyleOptionButton option;
option.initFrom(qtWidget);
option.rect = wxQtConvertRect(rect);
if ( flags & wxCONTROL_DISABLED )
{
option.state = QStyle::State_None;
option.palette.setCurrentColorGroup(QPalette::Disabled);
}
else
{
option.state = QStyle::State_Enabled;
if ( flags & wxCONTROL_CURRENT )
option.state |= QStyle::State_MouseOver;
if ( flags & wxCONTROL_FOCUSED )
option.state |= QStyle::State_HasFocus;
if ( flags & wxCONTROL_PRESSED )
option.state |= QStyle::State_Sunken;
}
if ( flags & wxCONTROL_UNDETERMINED )
option.state |= QStyle::State_NoChange;
else if ( flags & wxCONTROL_CHECKED )
option.state |= QStyle::State_On;
else
option.state |= QStyle::State_Off;
qtStyle->drawControl(QStyle::CE_RadioButton, &option, painter, qtWidget);
}
void
wxRendererQt::DrawTextCtrl(wxWindow* win, wxDC& dc, const wxRect& origRect, int flags)
{
auto painter = wxGetQtPainter(dc);
wxCHECK_RET( painter, "Invalid painter!" );
auto qtWidget = win->GetHandle();
auto qtStyle = qtWidget->style();
const int frameWidth = qtStyle->pixelMetric(QStyle::PM_DefaultFrameWidth);
// Notice that KDE refuses to render the frame around the control if its
// height is less than _minHeight_ (this is also the case for the native
// QLineEdit)
const int minHeight = 2 * frameWidth + win->GetCharHeight() * 3 / 2;
wxRect rect = origRect;
if ( rect.GetHeight() < minHeight )
{
rect.SetHeight(minHeight);
}
wxDCClipper clip(dc, rect);
QStyleOptionFrame option;
option.initFrom(qtWidget);
option.rect = wxQtConvertRect(rect);
if ( flags & wxCONTROL_DISABLED )
{
option.state = QStyle::State_None;
option.palette.setCurrentColorGroup(QPalette::Disabled);
}
else
{
option.state = QStyle::State_Enabled | QStyle::State_Sunken;
if ( flags & wxCONTROL_CURRENT )
option.state |= QStyle::State_MouseOver;
if ( flags & wxCONTROL_FOCUSED )
option.state |= QStyle::State_HasFocus;
}
option.lineWidth = frameWidth;
option.midLineWidth = 0;
qtStyle->drawPrimitive(QStyle::PE_PanelLineEdit, &option, painter, qtWidget);
qtStyle->drawPrimitive(QStyle::PE_FrameLineEdit, &option, painter, qtWidget);
}