Files
cbh/ElaWidgetTools/DeveloperComponents/ElaMenuStyle.cpp
2025-09-19 22:40:52 +08:00

235 lines
9.5 KiB
C++

#include "ElaMenuStyle.h"
#include <QDebug>
#include <QPainter>
#include <QPainterPath>
#include <QStyleOption>
#include "ElaMenu.h"
#include "ElaTheme.h"
ElaMenuStyle::ElaMenuStyle(QStyle* style)
{
_pMenuItemHeight = 32;
_themeMode = eTheme->getThemeMode();
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) {
_themeMode = themeMode;
});
}
ElaMenuStyle::~ElaMenuStyle()
{
}
void ElaMenuStyle::drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
{
switch (element)
{
case QStyle::PE_PanelMenu:
{
// 高性能阴影
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
eTheme->drawEffectShadow(painter, option->rect, _shadowBorderWidth, 6);
// 背景绘制
QRect foregroundRect(_shadowBorderWidth, _shadowBorderWidth, option->rect.width() - 2 * _shadowBorderWidth, option->rect.height() - 2 * _shadowBorderWidth);
painter->setPen(ElaThemeColor(_themeMode, PopupBorder));
painter->setBrush(ElaThemeColor(_themeMode, PopupBase));
painter->drawRoundedRect(foregroundRect, 6, 6);
painter->restore();
return;
}
case QStyle::PE_FrameMenu:
{
return;
}
default:
{
break;
}
}
QProxyStyle::drawPrimitive(element, option, painter, widget);
}
void ElaMenuStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
{
switch (element)
{
case QStyle::CE_MenuItem:
{
//内容绘制 区分类型
if (const QStyleOptionMenuItem* mopt = qstyleoption_cast<const QStyleOptionMenuItem*>(option))
{
if (mopt->menuItemType == QStyleOptionMenuItem::Separator)
{
QRect separatorRect = mopt->rect;
painter->save();
painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
painter->setPen(Qt::NoPen);
painter->setBrush(ElaThemeColor(_themeMode, BasicBaseLine));
painter->drawRoundedRect(QRectF(separatorRect.x() + separatorRect.width() * 0.055, separatorRect.center().y(), separatorRect.width() - separatorRect.width() * 0.11, 1.5), 1, 1);
painter->restore();
return;
}
else
{
QRect menuRect = mopt->rect;
qreal contentPadding = menuRect.width() * 0.055;
qreal textLeftSpacing = 8;
painter->save();
painter->setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing | QPainter::TextAntialiasing);
//覆盖效果
if (mopt->state.testFlag(QStyle::State_Enabled) && (mopt->state.testFlag(QStyle::State_MouseOver) || mopt->state.testFlag(QStyle::State_Selected)))
{
QRect hoverRect = menuRect;
hoverRect.adjust(0, 2, 0, -2);
painter->setPen(Qt::NoPen);
painter->setBrush(ElaThemeColor(_themeMode, PopupHover));
painter->drawRoundedRect(hoverRect, 5, 5);
}
//Icon绘制
QIcon menuIcon = mopt->icon;
//check绘制
if (mopt->menuHasCheckableItems)
{
painter->save();
painter->setPen(!mopt->state.testFlag(QStyle::State_Enabled) ? Qt::gray : _themeMode == ElaThemeType::Light ? Qt::black
: Qt::white);
QFont iconFont = QFont("ElaAwesome");
iconFont.setPixelSize(_pMenuItemHeight * 0.57);
painter->setFont(iconFont);
painter->drawText(QRectF(menuRect.x() + contentPadding, menuRect.y(), _iconWidth, menuRect.height()), Qt::AlignCenter, mopt->checked ? QChar((unsigned short)ElaIconType::Check) : QChar((unsigned short)ElaIconType::None));
painter->restore();
}
else
{
QString iconText;
const ElaMenu* menu = dynamic_cast<const ElaMenu*>(widget);
if (menu)
{
QAction* action = menu->actionAt(menuRect.center());
if (action)
{
iconText = action->property("ElaIconType").toString();
}
}
if (!iconText.isEmpty())
{
painter->save();
painter->setPen(!mopt->state.testFlag(QStyle::State_Enabled) ? Qt::gray : _themeMode == ElaThemeType::Light ? Qt::black
: Qt::white);
QFont iconFont = QFont("ElaAwesome");
iconFont.setPixelSize(_pMenuItemHeight * 0.57);
painter->setFont(iconFont);
painter->drawText(QRectF(menuRect.x() + contentPadding, menuRect.y(), _iconWidth, menuRect.height()), Qt::AlignCenter, iconText);
painter->restore();
}
else
{
if (!menuIcon.isNull())
{
painter->drawPixmap(QRect(menuRect.x() + contentPadding, menuRect.center().y() - _iconWidth / 2, _iconWidth, _iconWidth), menuIcon.pixmap(_iconWidth, _iconWidth));
}
}
}
//文字和快捷键绘制
if (!mopt->text.isEmpty())
{
QStringList textList = mopt->text.split("\t");
painter->setPen(!mopt->state.testFlag(QStyle::State_Enabled) ? Qt::gray : _themeMode == ElaThemeType::Light ? Qt::black
: Qt::white);
painter->drawText(QRectF(menuRect.x() + (_isAnyoneItemHasIcon ? contentPadding + textLeftSpacing : 0) + _iconWidth, menuRect.y(), menuRect.width(), menuRect.height()), Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, textList[0]);
if (textList.count() > 1)
{
painter->drawText(QRectF(menuRect.x() + contentPadding + _iconWidth + textLeftSpacing, menuRect.y(), menuRect.width() - (contentPadding * 2 + _iconWidth + textLeftSpacing), menuRect.height()), Qt::AlignRight | Qt::AlignVCenter | Qt::TextSingleLine, textList[1]);
}
}
//展开图标
if (mopt->menuItemType == QStyleOptionMenuItem::SubMenu)
{
painter->save();
painter->setPen(!mopt->state.testFlag(QStyle::State_Enabled) ? Qt::gray : _themeMode == ElaThemeType::Light ? Qt::black
: Qt::white);
QFont iconFont = QFont("ElaAwesome");
iconFont.setPixelSize(18);
painter->setFont(iconFont);
painter->drawText(QRect(menuRect.right() - 25, menuRect.y(), 25, menuRect.height()), Qt::AlignVCenter, QChar((unsigned short)ElaIconType::AngleRight));
painter->restore();
}
painter->restore();
}
}
return;
}
case QStyle::CE_MenuEmptyArea:
{
return;
}
default:
{
break;
}
}
QProxyStyle::drawControl(element, option, painter, widget);
}
int ElaMenuStyle::pixelMetric(PixelMetric metric, const QStyleOption* option, const QWidget* widget) const
{
switch (metric)
{
case QStyle::PM_SmallIconSize:
{
//图标宽度
_iconWidth = _pMenuItemHeight * 0.7;
return _iconWidth;
}
case QStyle::PM_MenuPanelWidth:
{
//外围容器宽度
return _shadowBorderWidth * 1.5;
}
default:
{
break;
}
}
return QProxyStyle::pixelMetric(metric, option, widget);
}
QSize ElaMenuStyle::sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& size, const QWidget* widget) const
{
switch (type)
{
case QStyle::CT_MenuItem:
{
if (const QStyleOptionMenuItem* mopt = qstyleoption_cast<const QStyleOptionMenuItem*>(option))
{
if (mopt->menuItemType == QStyleOptionMenuItem::Separator)
{
break;
}
QSize menuItemSize = QProxyStyle::sizeFromContents(type, option, size, widget);
const ElaMenu* menu = dynamic_cast<const ElaMenu*>(widget);
if (menu->isHasIcon() || mopt->menuHasCheckableItems)
{
_isAnyoneItemHasIcon = true;
}
if (menu->isHasChildMenu())
{
return QSize(menuItemSize.width() + 20, _pMenuItemHeight);
}
else
{
return QSize(menuItemSize.width(), _pMenuItemHeight);
}
}
}
default:
{
break;
}
}
return QProxyStyle::sizeFromContents(type, option, size, widget);
}