Allow different custom window title styles.

This commit is contained in:
John Preston 2019-10-14 14:34:51 +04:00
parent c0ce14bb68
commit 40d7581c36
11 changed files with 173 additions and 95 deletions

View file

@ -12,6 +12,10 @@
#include <QtCore/QRect> #include <QtCore/QRect>
#include <QtCore/QPoint> #include <QtCore/QPoint>
namespace style {
struct WindowTitle;
} // namespace style
namespace Ui { namespace Ui {
class PlainShadow; class PlainShadow;
@ -23,6 +27,7 @@ public:
TitleWidget(not_null<RpWidget*> parent, int height); TitleWidget(not_null<RpWidget*> parent, int height);
void setText(const QString &text); void setText(const QString &text);
void setStyle(const style::WindowTitle &st);
[[nodiscard]] QString text() const; [[nodiscard]] QString text() const;
protected: protected:
@ -35,6 +40,7 @@ private:
void init(int height); void init(int height);
not_null<const style::WindowTitle*> _st;
object_ptr<Ui::PlainShadow> _shadow; object_ptr<Ui::PlainShadow> _shadow;
QString _text; QString _text;
QFont _font; QFont _font;

View file

@ -21,6 +21,7 @@ namespace Platform {
TitleWidget::TitleWidget(not_null<RpWidget*> parent, int height) TitleWidget::TitleWidget(not_null<RpWidget*> parent, int height)
: RpWidget(parent) : RpWidget(parent)
, _st(&st::defaultWindowTitle)
, _shadow(this, st::titleShadow) { , _shadow(this, st::titleShadow) {
init(height); init(height);
} }
@ -32,6 +33,11 @@ void TitleWidget::setText(const QString &text) {
} }
} }
void TitleWidget::setStyle(const style::WindowTitle &st) {
_st = &st;
update();
}
QString TitleWidget::text() const { QString TitleWidget::text() const {
return _text; return _text;
} }
@ -45,7 +51,7 @@ void TitleWidget::init(int height) {
window()->widthValue( window()->widthValue(
) | rpl::start_with_next([=](int width) { ) | rpl::start_with_next([=](int width) {
setGeometry(0, 0, width, st::titleHeight); setGeometry(0, 0, width, height);
}, lifetime()); }, lifetime());
const auto families = QStringList{ const auto families = QStringList{
@ -70,10 +76,10 @@ void TitleWidget::paintEvent(QPaintEvent *e) {
QPainter p(this); QPainter p(this);
const auto active = isActiveWindow(); const auto active = isActiveWindow();
p.fillRect(rect(), active ? st::titleBgActive : st::titleBg); p.fillRect(rect(), active ? _st->bgActive : _st->bg);
p.setFont(_font); p.setFont(_font);
p.setPen(active ? st::titleFgActive : st::titleFg); p.setPen(active ? _st->fgActive : _st->fg);
p.drawText(rect(), _text, style::al_center); p.drawText(rect(), _text, style::al_center);
} }

View file

@ -6,6 +6,10 @@
// //
#pragma once #pragma once
namespace style {
struct WindowTitle;
} // namespace style
namespace Ui { namespace Ui {
class RpWidget; class RpWidget;
@ -16,6 +20,7 @@ class BasicWindowHelper {
public: public:
[[nodiscard]] virtual not_null<RpWidget*> body() = 0; [[nodiscard]] virtual not_null<RpWidget*> body() = 0;
virtual void setTitle(const QString &title) = 0; virtual void setTitle(const QString &title) = 0;
virtual void setTitleStyle(const style::WindowTitle &st) = 0;
virtual void setMinimumSize(QSize size) = 0; virtual void setMinimumSize(QSize size) = 0;
virtual void setFixedSize(QSize size) = 0; virtual void setFixedSize(QSize size) = 0;
virtual void setGeometry(QRect rect) = 0; virtual void setGeometry(QRect rect) = 0;

View file

@ -545,7 +545,7 @@ LRESULT WindowShadow::windowCallback(
case WM_NCHITTEST: { case WM_NCHITTEST: {
if (!_resizeEnabled) { if (!_resizeEnabled) {
return HTTRANSPARENT; return HTNOWHERE;
} }
const auto xPos = GET_X_LPARAM(lParam); const auto xPos = GET_X_LPARAM(lParam);
const auto yPos = GET_Y_LPARAM(lParam); const auto yPos = GET_Y_LPARAM(lParam);

View file

@ -21,9 +21,10 @@ namespace Platform {
TitleWidget::TitleWidget(not_null<RpWidget*> parent) TitleWidget::TitleWidget(not_null<RpWidget*> parent)
: RpWidget(parent) : RpWidget(parent)
, _minimize(this, st::titleButtonMinimize) , _st(&st::defaultWindowTitle)
, _maximizeRestore(this, st::titleButtonMaximize) , _minimize(this, _st->minimize)
, _close(this, st::titleButtonClose) , _maximizeRestore(this, _st->maximize)
, _close(this, _st->close)
, _shadow(this, st::titleShadow) , _shadow(this, st::titleShadow)
, _maximizedState(parent->windowState() & Qt::WindowMaximized) , _maximizedState(parent->windowState() & Qt::WindowMaximized)
, _activeState(parent->isActiveWindow()) { , _activeState(parent->isActiveWindow()) {
@ -34,6 +35,13 @@ void TitleWidget::setText(const QString &text) {
window()->setWindowTitle(text); window()->setWindowTitle(text);
} }
void TitleWidget::setStyle(const style::WindowTitle &st) {
_st = &st;
setGeometry(0, 0, window()->width(), _st->height);
updateButtonsState();
update();
}
not_null<RpWidget*> TitleWidget::window() const { not_null<RpWidget*> TitleWidget::window() const {
return static_cast<RpWidget*>(parentWidget()); return static_cast<RpWidget*>(parentWidget());
} }
@ -66,7 +74,7 @@ void TitleWidget::init() {
window()->widthValue( window()->widthValue(
) | rpl::start_with_next([=](int width) { ) | rpl::start_with_next([=](int width) {
setGeometry(0, 0, width, st::titleHeight); setGeometry(0, 0, width, _st->height);
}, lifetime()); }, lifetime());
window()->createWinId(); window()->createWinId();
@ -84,7 +92,7 @@ void TitleWidget::paintEvent(QPaintEvent *e) {
_activeState = active; _activeState = active;
updateButtonsState(); updateButtonsState();
} }
QPainter(this).fillRect(e->rect(), active ? st::titleBgActive : st::titleBg); QPainter(this).fillRect(e->rect(), active ? _st->bgActive : _st->bg);
} }
void TitleWidget::updateControlsPosition() { void TitleWidget::updateControlsPosition() {
@ -120,35 +128,35 @@ void TitleWidget::handleWindowStateChanged(Qt::WindowState state) {
void TitleWidget::updateButtonsState() { void TitleWidget::updateButtonsState() {
const auto minimize = _activeState const auto minimize = _activeState
? &st::titleButtonMinimizeIconActive ? &_st->minimizeIconActive
: nullptr; : &_st->minimize.icon;
const auto minimizeOver = _activeState const auto minimizeOver = _activeState
? &st::titleButtonMinimizeIconActiveOver ? &_st->minimizeIconActiveOver
: nullptr; : &_st->minimize.iconOver;
_minimize->setIconOverride(minimize, minimizeOver); _minimize->setIconOverride(minimize, minimizeOver);
if (_maximizedState) { if (_maximizedState) {
const auto restore = _activeState const auto restore = _activeState
? &st::titleButtonRestoreIconActive ? &_st->restoreIconActive
: &st::titleButtonRestoreIcon; : &_st->restoreIcon;
const auto restoreOver = _activeState const auto restoreOver = _activeState
? &st::titleButtonRestoreIconActiveOver ? &_st->restoreIconActiveOver
: &st::titleButtonRestoreIconOver; : &_st->restoreIconOver;
_maximizeRestore->setIconOverride(restore, restoreOver); _maximizeRestore->setIconOverride(restore, restoreOver);
} else { } else {
const auto maximize = _activeState const auto maximize = _activeState
? &st::titleButtonMaximizeIconActive ? &_st->maximizeIconActive
: nullptr; : &_st->maximize.icon;
const auto maximizeOver = _activeState const auto maximizeOver = _activeState
? &st::titleButtonMaximizeIconActiveOver ? &_st->maximizeIconActiveOver
: nullptr; : &_st->maximize.iconOver;
_maximizeRestore->setIconOverride(maximize, maximizeOver); _maximizeRestore->setIconOverride(maximize, maximizeOver);
} }
const auto close = _activeState const auto close = _activeState
? &st::titleButtonCloseIconActive ? &_st->closeIconActive
: nullptr; : &_st->close.icon;
const auto closeOver = _activeState const auto closeOver = _activeState
? &st::titleButtonCloseIconActiveOver ? &_st->closeIconActiveOver
: nullptr; : &_st->close.iconOver;
_close->setIconOverride(close, closeOver); _close->setIconOverride(close, closeOver);
} }

View file

@ -12,6 +12,10 @@
#include <QtCore/QRect> #include <QtCore/QRect>
#include <QtCore/QPoint> #include <QtCore/QPoint>
namespace style {
struct WindowTitle;
} // namespace style
namespace Ui { namespace Ui {
class IconButton; class IconButton;
@ -39,6 +43,7 @@ public:
explicit TitleWidget(not_null<RpWidget*> parent); explicit TitleWidget(not_null<RpWidget*> parent);
void setText(const QString &text); void setText(const QString &text);
void setStyle(const style::WindowTitle &st);
[[nodiscard]] HitTestResult hitTest(QPoint point) const; [[nodiscard]] HitTestResult hitTest(QPoint point) const;
void setResizeEnabled(bool enabled); void setResizeEnabled(bool enabled);
@ -55,6 +60,8 @@ private:
void updateButtonsState(); void updateButtonsState();
void updateControlsPosition(); void updateControlsPosition();
not_null<const style::WindowTitle*> _st;
object_ptr<Ui::IconButton> _minimize; object_ptr<Ui::IconButton> _minimize;
object_ptr<Ui::IconButton> _maximizeRestore; object_ptr<Ui::IconButton> _maximizeRestore;
object_ptr<Ui::IconButton> _close; object_ptr<Ui::IconButton> _close;

View file

@ -99,6 +99,10 @@ void WindowHelper::setTitle(const QString &title) {
_window->setWindowTitle(title); _window->setWindowTitle(title);
} }
void WindowHelper::setTitleStyle(const style::WindowTitle &st) {
_title->setStyle(st);
}
void WindowHelper::setMinimumSize(QSize size) { void WindowHelper::setMinimumSize(QSize size) {
_window->setMinimumSize(size.width(), _title->height() + size.height()); _window->setMinimumSize(size.width(), _title->height() + size.height());
} }

View file

@ -23,6 +23,7 @@ public:
not_null<RpWidget*> body() override; not_null<RpWidget*> body() override;
void setTitle(const QString &title) override; void setTitle(const QString &title) override;
void setTitleStyle(const style::WindowTitle &st) override;
void setMinimumSize(QSize size) override; void setMinimumSize(QSize size) override;
void setFixedSize(QSize size) override; void setFixedSize(QSize size) override;
void setGeometry(QRect rect) override; void setGeometry(QRect rect) override;

View file

@ -523,6 +523,27 @@ PassportScanRow {
restore: RoundButton; restore: RoundButton;
} }
WindowTitle {
height: pixels;
bg: color;
bgActive: color;
fg: color;
fgActive: color;
minimize: IconButton;
minimizeIconActive: icon;
minimizeIconActiveOver: icon;
maximize: IconButton;
maximizeIconActive: icon;
maximizeIconActiveOver: icon;
restoreIcon: icon;
restoreIconOver: icon;
restoreIconActive: icon;
restoreIconActiveOver: icon;
close: IconButton;
closeIconActive: icon;
closeIconActiveOver: icon;
}
defaultLabelSimple: LabelSimple { defaultLabelSimple: LabelSimple {
font: normalFont; font: normalFont;
maxWidth: 0px; maxWidth: 0px;
@ -1164,11 +1185,22 @@ backButton: IconButton(defaultIconButton) {
// Windows specific title // Windows specific title
titleHeight: 21px; windowTitleButton: IconButton {
titleButtonMinimize: IconButton {
width: 24px; width: 24px;
height: 21px; height: 21px;
iconPosition: point(0px, 0px);
}
windowTitleButtonClose: IconButton(windowTitleButton) {
width: 25px;
}
defaultWindowTitle: WindowTitle {
height: 21px;
bg: titleBg;
bgActive: titleBgActive;
fg: titleFg;
fgActive: titleFgActive;
minimize: IconButton(windowTitleButton) {
icon: icon { icon: icon {
{ size(24px, 21px), titleButtonBg }, { size(24px, 21px), titleButtonBg },
{ "title_button_minimize", titleButtonFg, point(4px, 4px) }, { "title_button_minimize", titleButtonFg, point(4px, 4px) },
@ -1177,17 +1209,16 @@ titleButtonMinimize: IconButton {
{ size(24px, 21px), titleButtonBgOver }, { size(24px, 21px), titleButtonBgOver },
{ "title_button_minimize", titleButtonFgOver, point(4px, 4px) }, { "title_button_minimize", titleButtonFgOver, point(4px, 4px) },
}; };
iconPosition: point(0px, 0px);
} }
titleButtonMinimizeIconActive: icon { minimizeIconActive: icon {
{ size(24px, 21px), titleButtonBgActive }, { size(24px, 21px), titleButtonBgActive },
{ "title_button_minimize", titleButtonFgActive, point(4px, 4px) }, { "title_button_minimize", titleButtonFgActive, point(4px, 4px) },
}; };
titleButtonMinimizeIconActiveOver: icon { minimizeIconActiveOver: icon {
{ size(24px, 21px), titleButtonBgActiveOver }, { size(24px, 21px), titleButtonBgActiveOver },
{ "title_button_minimize", titleButtonFgActiveOver, point(4px, 4px) }, { "title_button_minimize", titleButtonFgActiveOver, point(4px, 4px) },
}; };
titleButtonMaximize: IconButton(titleButtonMinimize) { maximize: IconButton(windowTitleButton) {
icon: icon { icon: icon {
{ size(24px, 21px), titleButtonBg }, { size(24px, 21px), titleButtonBg },
{ "title_button_maximize", titleButtonFg, point(4px, 4px) }, { "title_button_maximize", titleButtonFg, point(4px, 4px) },
@ -1197,33 +1228,31 @@ titleButtonMaximize: IconButton(titleButtonMinimize) {
{ "title_button_maximize", titleButtonFgOver, point(4px, 4px) }, { "title_button_maximize", titleButtonFgOver, point(4px, 4px) },
}; };
} }
titleButtonMaximizeIconActive: icon { maximizeIconActive: icon {
{ size(24px, 21px), titleButtonBgActive }, { size(24px, 21px), titleButtonBgActive },
{ "title_button_maximize", titleButtonFgActive, point(4px, 4px) }, { "title_button_maximize", titleButtonFgActive, point(4px, 4px) },
}; };
titleButtonMaximizeIconActiveOver: icon { maximizeIconActiveOver: icon {
{ size(24px, 21px), titleButtonBgActiveOver }, { size(24px, 21px), titleButtonBgActiveOver },
{ "title_button_maximize", titleButtonFgActiveOver, point(4px, 4px) }, { "title_button_maximize", titleButtonFgActiveOver, point(4px, 4px) },
}; };
titleButtonRestoreIcon: icon { restoreIcon: icon {
{ size(24px, 21px), titleButtonBg }, { size(24px, 21px), titleButtonBg },
{ "title_button_restore", titleButtonFg, point(4px, 4px) }, { "title_button_restore", titleButtonFg, point(4px, 4px) },
}; };
titleButtonRestoreIconOver: icon { restoreIconOver: icon {
{ size(24px, 21px), titleButtonBgOver }, { size(24px, 21px), titleButtonBgOver },
{ "title_button_restore", titleButtonFgOver, point(4px, 4px) }, { "title_button_restore", titleButtonFgOver, point(4px, 4px) },
}; };
titleButtonRestoreIconActive: icon { restoreIconActive: icon {
{ size(24px, 21px), titleButtonBgActive }, { size(24px, 21px), titleButtonBgActive },
{ "title_button_restore", titleButtonFgActive, point(4px, 4px) }, { "title_button_restore", titleButtonFgActive, point(4px, 4px) },
}; };
titleButtonRestoreIconActiveOver: icon { restoreIconActiveOver: icon {
{ size(24px, 21px), titleButtonBgActiveOver }, { size(24px, 21px), titleButtonBgActiveOver },
{ "title_button_restore", titleButtonFgActiveOver, point(4px, 4px) }, { "title_button_restore", titleButtonFgActiveOver, point(4px, 4px) },
}; };
titleButtonClose: IconButton(titleButtonMinimize) { close: IconButton(windowTitleButtonClose) {
width: 25px;
icon: icon { icon: icon {
{ size(25px, 21px), titleButtonCloseBg }, { size(25px, 21px), titleButtonCloseBg },
{ "title_button_close", titleButtonCloseFg, point(5px, 4px) }, { "title_button_close", titleButtonCloseFg, point(5px, 4px) },
@ -1233,14 +1262,15 @@ titleButtonClose: IconButton(titleButtonMinimize) {
{ "title_button_close", titleButtonCloseFgOver, point(5px, 4px) }, { "title_button_close", titleButtonCloseFgOver, point(5px, 4px) },
}; };
} }
titleButtonCloseIconActive: icon { closeIconActive: icon {
{ size(25px, 21px), titleButtonCloseBgActive }, { size(25px, 21px), titleButtonCloseBgActive },
{ "title_button_close", titleButtonCloseFgActive, point(5px, 4px) }, { "title_button_close", titleButtonCloseFgActive, point(5px, 4px) },
}; };
titleButtonCloseIconActiveOver: icon { closeIconActiveOver: icon {
{ size(25px, 21px), titleButtonCloseBgActiveOver }, { size(25px, 21px), titleButtonCloseBgActiveOver },
{ "title_button_close", titleButtonCloseFgActiveOver, point(5px, 4px) }, { "title_button_close", titleButtonCloseFgActiveOver, point(5px, 4px) },
}; };
}
windowShadow: icon {{ "window_shadow", windowShadowFg }}; windowShadow: icon {{ "window_shadow", windowShadowFg }};
windowShadowShift: 1px; windowShadowShift: 1px;

View file

@ -34,6 +34,12 @@ void Window::setTitle(const QString &title) {
} }
} }
void Window::setTitleStyle(const style::WindowTitle &st) {
if (_helper) {
_helper->setTitleStyle(st);
}
}
void Window::setMinimumSize(QSize size) { void Window::setMinimumSize(QSize size) {
if (_helper) { if (_helper) {
_helper->setMinimumSize(size); _helper->setMinimumSize(size);

View file

@ -8,6 +8,10 @@
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
namespace style {
struct WindowTitle;
} // namespace style
namespace Ui { namespace Ui {
namespace Platform { namespace Platform {
class BasicWindowHelper; class BasicWindowHelper;
@ -22,6 +26,7 @@ public:
[[nodiscard]] not_null<const RpWidget*> body() const; [[nodiscard]] not_null<const RpWidget*> body() const;
void setTitle(const QString &title); void setTitle(const QString &title);
void setTitleStyle(const style::WindowTitle &st);
void setMinimumSize(QSize size); void setMinimumSize(QSize size);
void setFixedSize(QSize size); void setFixedSize(QSize size);
void setGeometry(QRect rect); void setGeometry(QRect rect);