You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Editor/Plugins/EditorCommon/DockTitleBarWidget.cpp

234 lines
6.8 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include "DockTitleBarWidget.h"
#include <QStyle>
#include <QStyleOptionToolButton>
#include <AzCore/Casting/numeric_cast.h>
namespace DockTitleBarInterpolate
{
static QColor Interpolate(const QColor& a, const QColor& b, float k)
{
float mk = 1.0f - k;
return QColor(aznumeric_cast<int>(a.red() * mk + b.red() * k),
aznumeric_cast<int>(a.green() * mk + b.green() * k),
aznumeric_cast<int>(a.blue() * mk + b.blue() * k),
aznumeric_cast<int>(a.alpha() * mk + b.alpha() * k));
}
}
class CDockWidgetTitleButton
: public QAbstractButton
{
public:
CDockWidgetTitleButton(QWidget* parent);
QSize sizeHint() const override;
QSize minimumSizeHint() const override { return sizeHint(); }
protected:
void enterEvent(QEvent* ev) override;
void leaveEvent(QEvent* ev) override;
void paintEvent(QPaintEvent* ev) override;
};
class CTitleBarText
: public QWidget
{
public:
CTitleBarText(QWidget* parent, QDockWidget* dockWidget)
: QWidget(parent)
, m_dockWidget(dockWidget)
{
QFont font;
font.setBold(true);
setFont(font);
}
void paintEvent([[maybe_unused]] QPaintEvent* ev) override
{
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing, true);
QRect r = rect().adjusted(2, 2, -3, -3);
p.translate(0.5f, 0.5f);
QColor color = DockTitleBarInterpolate::Interpolate(palette().color(QPalette::Window), palette().color(QPalette::Shadow), 0.2f);
p.setBrush(QBrush(color));
p.setPen(Qt::NoPen);
p.drawRoundedRect(r, 4, 4, Qt::AbsoluteSize);
p.setPen(QPen(palette().color(QPalette::WindowText)));
QTextOption textOption(Qt::AlignLeft | Qt::AlignVCenter);
textOption.setWrapMode(QTextOption::NoWrap);
p.drawText(r.adjusted(4, 0, 0, 0), m_dockWidget->windowTitle(), textOption);
}
private:
QDockWidget* m_dockWidget;
};
// ---------------------------------------------------------------------------
CDockWidgetTitleButton::CDockWidgetTitleButton(QWidget* parent)
: QAbstractButton(parent)
{
setFocusPolicy(Qt::NoFocus);
}
QSize CDockWidgetTitleButton::sizeHint() const
{
ensurePolished();
int size = 2 * style()->pixelMetric(QStyle::PM_DockWidgetTitleBarButtonMargin, nullptr, this);
if (!icon().isNull())
{
int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, this);
QSize sz = icon().actualSize(QSize(iconSize, iconSize));
size += qMax(sz.width(), sz.height());
}
return QSize(size, size);
}
void CDockWidgetTitleButton::enterEvent(QEvent* ev)
{
if (isEnabled())
{
update();
}
QAbstractButton::enterEvent(ev);
}
void CDockWidgetTitleButton::leaveEvent(QEvent* ev)
{
if (isEnabled())
{
update();
}
QAbstractButton::leaveEvent(ev);
}
void CDockWidgetTitleButton::paintEvent([[maybe_unused]] QPaintEvent* ev)
{
QPainter painter(this);
QStyleOptionToolButton opt;
opt.state = QStyle::State_AutoRaise;
opt.init(this);
opt.state |= QStyle::State_AutoRaise;
if (isEnabled() && underMouse() && !isChecked() && !isDown())
{
opt.state |= QStyle::State_Raised;
}
if (isChecked())
{
opt.state |= QStyle::State_On;
}
if (isDown())
{
opt.state |= QStyle::State_Sunken;
}
if (opt.state & (QStyle::State_Raised | QStyle::State_Sunken))
{
style()->drawPrimitive(QStyle::PE_PanelButtonTool, &opt, &painter, this);
}
opt.icon = icon();
opt.subControls = QStyle::SubControls();
opt.activeSubControls = QStyle::SubControls();
opt.features = QStyleOptionToolButton::None;
opt.arrowType = Qt::NoArrow;
int size = style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, this);
opt.iconSize = QSize(size, size);
style()->drawComplexControl(QStyle::CC_ToolButton, &opt, &painter, this);
}
// ---------------------------------------------------------------------------
CDockTitleBarWidget::CDockTitleBarWidget(QDockWidget* dockWidget)
: m_dockWidget(dockWidget)
{
CTitleBarText* textWidget = new CTitleBarText(this, dockWidget);
m_layout = new QBoxLayout(QBoxLayout::LeftToRight);
m_layout->setContentsMargins(0, 0, 0, 0);
m_layout->setSpacing(0);
m_layout->addWidget(textWidget, 1);
QStyleOptionDockWidget opt;
opt.initFrom(dockWidget);
opt.closable = dockWidget->features() & QDockWidget::DockWidgetClosable;
opt.movable = dockWidget->features() & QDockWidget::DockWidgetMovable;
opt.floatable = dockWidget->features() & QDockWidget::DockWidgetFloatable;
m_buttonLayout = new QBoxLayout(QBoxLayout::LeftToRight);
m_buttonLayout->setContentsMargins(0, 0, 0, 0);
m_buttonLayout->setSpacing(0);
m_layout->addLayout(m_buttonLayout, 0);
m_floatButton = new CDockWidgetTitleButton(dockWidget);
m_floatButton->setIcon(QIcon("Icons/float.png"));
m_floatButton->setVisible(opt.floatable);
m_floatButton->setToolTip("Toggle Floating");
connect(m_floatButton, SIGNAL(clicked()), SLOT(OnFloatButtonPressed()));
m_layout->addWidget(m_floatButton, 0);
m_closeButton = new CDockWidgetTitleButton(dockWidget);
// close.png is a standard icon that looks similar to one in Fusion theme but
// uses alpha so it can be used on dark theme as well.
// style()->standardIcon(QStyle::SP_TitleBarCloseButton, &opt, dockWidget)
QIcon closeIcon("Icons/close.png");
m_closeButton->setIcon(closeIcon);
m_closeButton->setVisible(opt.closable);
m_closeButton->setToolTip("Close");
connect(m_closeButton, SIGNAL(clicked()), SLOT(OnCloseButtonPressed()));
m_layout->addWidget(m_closeButton, 0);
setLayout(m_layout);
}
void CDockTitleBarWidget::AddCustomButton(const QIcon& icon, const char* tooltip, int id)
{
SCustomButton slot;
slot.button = new CDockWidgetTitleButton(m_dockWidget);
slot.button->setIcon(icon);
slot.button->setToolTip(tooltip);
connect(slot.button, SIGNAL(clicked()), SLOT(OnCustomButtonPressed()));
slot.id = id;
m_buttonLayout->addWidget(slot.button, 0);
m_customButtons.push_back(slot);
}
void CDockTitleBarWidget::OnFloatButtonPressed()
{
m_dockWidget->setFloating(!m_dockWidget->isFloating());
}
void CDockTitleBarWidget::OnCloseButtonPressed()
{
m_dockWidget->close();
}
void CDockTitleBarWidget::OnCustomButtonPressed()
{
QObject* button = sender();
for (size_t i = 0; i < m_customButtons.size(); ++i)
{
if (button == m_customButtons[i].button)
{
SignalCustomButtonPressed(m_customButtons[i].id);
break;
}
}
}
#include <moc_DockTitleBarWidget.cpp>