DockTitleBarWidget.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "DockTitleBarWidget.h"
  9. #include <QStyle>
  10. #include <QStyleOptionToolButton>
  11. #include <AzCore/Casting/numeric_cast.h>
  12. namespace DockTitleBarInterpolate
  13. {
  14. static QColor Interpolate(const QColor& a, const QColor& b, float k)
  15. {
  16. float mk = 1.0f - k;
  17. return QColor(aznumeric_cast<int>(a.red() * mk + b.red() * k),
  18. aznumeric_cast<int>(a.green() * mk + b.green() * k),
  19. aznumeric_cast<int>(a.blue() * mk + b.blue() * k),
  20. aznumeric_cast<int>(a.alpha() * mk + b.alpha() * k));
  21. }
  22. }
  23. class CDockWidgetTitleButton
  24. : public QAbstractButton
  25. {
  26. public:
  27. CDockWidgetTitleButton(QWidget* parent);
  28. QSize sizeHint() const override;
  29. QSize minimumSizeHint() const override { return sizeHint(); }
  30. protected:
  31. void enterEvent(QEvent* ev) override;
  32. void leaveEvent(QEvent* ev) override;
  33. void paintEvent(QPaintEvent* ev) override;
  34. };
  35. class CTitleBarText
  36. : public QWidget
  37. {
  38. public:
  39. CTitleBarText(QWidget* parent, QDockWidget* dockWidget)
  40. : QWidget(parent)
  41. , m_dockWidget(dockWidget)
  42. {
  43. QFont font;
  44. font.setBold(true);
  45. setFont(font);
  46. }
  47. void paintEvent([[maybe_unused]] QPaintEvent* ev) override
  48. {
  49. QPainter p(this);
  50. p.setRenderHint(QPainter::Antialiasing, true);
  51. QRect r = rect().adjusted(2, 2, -3, -3);
  52. p.translate(0.5f, 0.5f);
  53. QColor color = DockTitleBarInterpolate::Interpolate(palette().color(QPalette::Window), palette().color(QPalette::Shadow), 0.2f);
  54. p.setBrush(QBrush(color));
  55. p.setPen(Qt::NoPen);
  56. p.drawRoundedRect(r, 4, 4, Qt::AbsoluteSize);
  57. p.setPen(QPen(palette().color(QPalette::WindowText)));
  58. QTextOption textOption(Qt::AlignLeft | Qt::AlignVCenter);
  59. textOption.setWrapMode(QTextOption::NoWrap);
  60. p.drawText(r.adjusted(4, 0, 0, 0), m_dockWidget->windowTitle(), textOption);
  61. }
  62. private:
  63. QDockWidget* m_dockWidget;
  64. };
  65. // ---------------------------------------------------------------------------
  66. CDockWidgetTitleButton::CDockWidgetTitleButton(QWidget* parent)
  67. : QAbstractButton(parent)
  68. {
  69. setFocusPolicy(Qt::NoFocus);
  70. }
  71. QSize CDockWidgetTitleButton::sizeHint() const
  72. {
  73. ensurePolished();
  74. int size = 2 * style()->pixelMetric(QStyle::PM_DockWidgetTitleBarButtonMargin, nullptr, this);
  75. if (!icon().isNull())
  76. {
  77. int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, this);
  78. QSize sz = icon().actualSize(QSize(iconSize, iconSize));
  79. size += qMax(sz.width(), sz.height());
  80. }
  81. return QSize(size, size);
  82. }
  83. void CDockWidgetTitleButton::enterEvent(QEvent* ev)
  84. {
  85. if (isEnabled())
  86. {
  87. update();
  88. }
  89. QAbstractButton::enterEvent(ev);
  90. }
  91. void CDockWidgetTitleButton::leaveEvent(QEvent* ev)
  92. {
  93. if (isEnabled())
  94. {
  95. update();
  96. }
  97. QAbstractButton::leaveEvent(ev);
  98. }
  99. void CDockWidgetTitleButton::paintEvent([[maybe_unused]] QPaintEvent* ev)
  100. {
  101. QPainter painter(this);
  102. QStyleOptionToolButton opt;
  103. opt.state = QStyle::State_AutoRaise;
  104. opt.init(this);
  105. opt.state |= QStyle::State_AutoRaise;
  106. if (isEnabled() && underMouse() && !isChecked() && !isDown())
  107. {
  108. opt.state |= QStyle::State_Raised;
  109. }
  110. if (isChecked())
  111. {
  112. opt.state |= QStyle::State_On;
  113. }
  114. if (isDown())
  115. {
  116. opt.state |= QStyle::State_Sunken;
  117. }
  118. if (opt.state & (QStyle::State_Raised | QStyle::State_Sunken))
  119. {
  120. style()->drawPrimitive(QStyle::PE_PanelButtonTool, &opt, &painter, this);
  121. }
  122. opt.icon = icon();
  123. opt.subControls = QStyle::SubControls();
  124. opt.activeSubControls = QStyle::SubControls();
  125. opt.features = QStyleOptionToolButton::None;
  126. opt.arrowType = Qt::NoArrow;
  127. int size = style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, this);
  128. opt.iconSize = QSize(size, size);
  129. style()->drawComplexControl(QStyle::CC_ToolButton, &opt, &painter, this);
  130. }
  131. // ---------------------------------------------------------------------------
  132. CDockTitleBarWidget::CDockTitleBarWidget(QDockWidget* dockWidget)
  133. : m_dockWidget(dockWidget)
  134. {
  135. CTitleBarText* textWidget = new CTitleBarText(this, dockWidget);
  136. m_layout = new QBoxLayout(QBoxLayout::LeftToRight);
  137. m_layout->setContentsMargins(0, 0, 0, 0);
  138. m_layout->setSpacing(0);
  139. m_layout->addWidget(textWidget, 1);
  140. QStyleOptionDockWidget opt;
  141. opt.initFrom(dockWidget);
  142. opt.closable = dockWidget->features() & QDockWidget::DockWidgetClosable;
  143. opt.movable = dockWidget->features() & QDockWidget::DockWidgetMovable;
  144. opt.floatable = dockWidget->features() & QDockWidget::DockWidgetFloatable;
  145. m_buttonLayout = new QBoxLayout(QBoxLayout::LeftToRight);
  146. m_buttonLayout->setContentsMargins(0, 0, 0, 0);
  147. m_buttonLayout->setSpacing(0);
  148. m_layout->addLayout(m_buttonLayout, 0);
  149. m_floatButton = new CDockWidgetTitleButton(dockWidget);
  150. m_floatButton->setIcon(QIcon("Icons/float.png"));
  151. m_floatButton->setVisible(opt.floatable);
  152. m_floatButton->setToolTip("Toggle Floating");
  153. connect(m_floatButton, SIGNAL(clicked()), SLOT(OnFloatButtonPressed()));
  154. m_layout->addWidget(m_floatButton, 0);
  155. m_closeButton = new CDockWidgetTitleButton(dockWidget);
  156. // close.png is a standard icon that looks similar to one in Fusion theme but
  157. // uses alpha so it can be used on dark theme as well.
  158. // style()->standardIcon(QStyle::SP_TitleBarCloseButton, &opt, dockWidget)
  159. QIcon closeIcon("Icons/close.png");
  160. m_closeButton->setIcon(closeIcon);
  161. m_closeButton->setVisible(opt.closable);
  162. m_closeButton->setToolTip("Close");
  163. connect(m_closeButton, SIGNAL(clicked()), SLOT(OnCloseButtonPressed()));
  164. m_layout->addWidget(m_closeButton, 0);
  165. setLayout(m_layout);
  166. }
  167. void CDockTitleBarWidget::AddCustomButton(const QIcon& icon, const char* tooltip, int id)
  168. {
  169. SCustomButton slot;
  170. slot.button = new CDockWidgetTitleButton(m_dockWidget);
  171. slot.button->setIcon(icon);
  172. slot.button->setToolTip(tooltip);
  173. connect(slot.button, SIGNAL(clicked()), SLOT(OnCustomButtonPressed()));
  174. slot.id = id;
  175. m_buttonLayout->addWidget(slot.button, 0);
  176. m_customButtons.push_back(slot);
  177. }
  178. void CDockTitleBarWidget::OnFloatButtonPressed()
  179. {
  180. m_dockWidget->setFloating(!m_dockWidget->isFloating());
  181. }
  182. void CDockTitleBarWidget::OnCloseButtonPressed()
  183. {
  184. m_dockWidget->close();
  185. }
  186. void CDockTitleBarWidget::OnCustomButtonPressed()
  187. {
  188. QObject* button = sender();
  189. for (size_t i = 0; i < m_customButtons.size(); ++i)
  190. {
  191. if (button == m_customButtons[i].button)
  192. {
  193. SignalCustomButtonPressed(m_customButtons[i].id);
  194. break;
  195. }
  196. }
  197. }
  198. #include <moc_DockTitleBarWidget.cpp>