Allow different styles for box layers.

This commit is contained in:
John Preston 2020-11-29 21:26:20 +03:00
parent 41bae1eba6
commit 7287e235e0
13 changed files with 205 additions and 31 deletions

View file

@ -555,6 +555,7 @@ callHangupRipple: #c04646; // phone call popup hangup button ripple effect
callMuteRipple: #ffffff12; // phone call popup mute mic and camera ripple effect callMuteRipple: #ffffff12; // phone call popup mute mic and camera ripple effect
groupCallBg: #131417; // group call popup background groupCallBg: #131417; // group call popup background
groupCallActiveFg: #4db8ff; // group call active controls text
groupCallMembersBg: #1a1c1f; // group call members list background groupCallMembersBg: #1a1c1f; // group call members list background
groupCallMembersFg: #ffffff; // group call member name text groupCallMembersFg: #ffffff; // group call member name text
groupCallMembersRipple: #22252a; // group call member row ripple effect groupCallMembersRipple: #22252a; // group call member row ripple effect
@ -569,6 +570,8 @@ groupCallLive1: #0dcc39; // group call live button color1
groupCallLive2: #0bb6bd; // group call live button color2 groupCallLive2: #0bb6bd; // group call live button color2
groupCallMuted1: #0992ef; // group call muted button color1 groupCallMuted1: #0992ef; // group call muted button color1
groupCallMuted2: #16ccfb; // group call muted button color2 groupCallMuted2: #16ccfb; // group call muted button color2
groupCallBoxButtonBgOver: #1d2a39; // group call button in box with mouse over
groupCallBoxButtonBgRipple: #223143; // group call button in box ripple effect
callBarBg: dialogsBgActive; // active phone call bar background callBarBg: dialogsBgActive; // active phone call bar background
callBarMuteRipple: dialogsRippleBgActive; // active phone call bar mute and hangup button ripple effect callBarMuteRipple: dialogsRippleBgActive; // active phone call bar mute and hangup button ripple effect

View file

@ -29,7 +29,7 @@ QPointer<RoundButton> BoxContent::addButton(
return addButton( return addButton(
std::move(text), std::move(text),
std::move(clickCallback), std::move(clickCallback),
st::defaultBoxButton); getDelegate()->style().button);
} }
QPointer<RoundButton> BoxContent::addLeftButton( QPointer<RoundButton> BoxContent::addLeftButton(
@ -38,7 +38,7 @@ QPointer<RoundButton> BoxContent::addLeftButton(
return getDelegate()->addLeftButton( return getDelegate()->addLeftButton(
std::move(text), std::move(text),
std::move(clickCallback), std::move(clickCallback),
st::defaultBoxButton); getDelegate()->style().button);
} }
void BoxContent::setInner(object_ptr<TWidget> inner) { void BoxContent::setInner(object_ptr<TWidget> inner) {
@ -245,8 +245,9 @@ void BoxContent::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
if (testAttribute(Qt::WA_OpaquePaintEvent)) { if (testAttribute(Qt::WA_OpaquePaintEvent)) {
const auto &color = getDelegate()->style().bg;
for (const auto rect : e->region()) { for (const auto rect : e->region()) {
p.fillRect(rect, st::boxBg); p.fillRect(rect, color);
} }
} }
} }

View file

@ -45,6 +45,7 @@ class BoxContentDelegate {
public: public:
virtual void setLayerType(bool layerType) = 0; virtual void setLayerType(bool layerType) = 0;
virtual void setStyle(const style::Box &st) = 0; virtual void setStyle(const style::Box &st) = 0;
virtual const style::Box &style() = 0;
virtual void setTitle(rpl::producer<TextWithEntities> title) = 0; virtual void setTitle(rpl::producer<TextWithEntities> title) = 0;
virtual void setAdditionalTitle(rpl::producer<QString> additional) = 0; virtual void setAdditionalTitle(rpl::producer<QString> additional) = 0;
virtual void setCloseByOutsideClick(bool close) = 0; virtual void setCloseByOutsideClick(bool close) = 0;

View file

@ -42,7 +42,7 @@ BoxLayerWidget::BoxLayerWidget(
: LayerWidget(layer) : LayerWidget(layer)
, _layer(layer) , _layer(layer)
, _content(std::move(content)) , _content(std::move(content))
, _roundRect(ImageRoundRadius::Small, st::boxBg) { , _roundRect(ImageRoundRadius::Small, st().bg) {
_content->setParent(this); _content->setParent(this);
_content->setDelegate(this); _content->setDelegate(this);
@ -74,12 +74,21 @@ const style::Box &BoxLayerWidget::st() const {
return _st return _st
? *_st ? *_st
: _layerType : _layerType
? st::layerBox ? (_layer->boxStyleOverrideLayer()
: st::defaultBox; ? *_layer->boxStyleOverrideLayer()
: st::layerBox)
: (_layer->boxStyleOverride()
? *_layer->boxStyleOverride()
: st::defaultBox);
} }
void BoxLayerWidget::setStyle(const style::Box &st) { void BoxLayerWidget::setStyle(const style::Box &st) {
_st = &st; _st = &st;
_roundRect.setColor(st.bg);
}
const style::Box &BoxLayerWidget::style() {
return st();
} }
int BoxLayerWidget::buttonsHeight() const { int BoxLayerWidget::buttonsHeight() const {
@ -118,7 +127,7 @@ void BoxLayerWidget::paintEvent(QPaintEvent *e) {
auto other = e->region().intersected(QRect(0, st::boxRadius, width(), height() - 2 * st::boxRadius)); auto other = e->region().intersected(QRect(0, st::boxRadius, width(), height() - 2 * st::boxRadius));
if (!other.isEmpty()) { if (!other.isEmpty()) {
for (const auto rect : other) { for (const auto rect : other) {
p.fillRect(rect, st::boxBg); p.fillRect(rect, st().bg);
} }
} }
if (!_additionalTitle.current().isEmpty() if (!_additionalTitle.current().isEmpty()
@ -137,21 +146,29 @@ void BoxLayerWidget::paintEvent(QPaintEvent *e) {
void BoxLayerWidget::paintAdditionalTitle(Painter &p) { void BoxLayerWidget::paintAdditionalTitle(Painter &p) {
p.setFont(st::boxTitleAdditionalFont); p.setFont(st::boxTitleAdditionalFont);
p.setPen(st::boxTitleAdditionalFg); p.setPen(st().titleAdditionalFg);
p.drawTextLeft(_titleLeft + (_title ? _title->width() : 0) + st::boxTitleAdditionalSkip, _titleTop + st::boxTitleFont->ascent - st::boxTitleAdditionalFont->ascent, width(), _additionalTitle.current()); p.drawTextLeft(
_titleLeft + (_title ? _title->width() : 0) + st::boxTitleAdditionalSkip,
_titleTop + st::boxTitleFont->ascent - st::boxTitleAdditionalFont->ascent,
width(),
_additionalTitle.current());
} }
void BoxLayerWidget::parentResized() { void BoxLayerWidget::parentResized() {
auto newHeight = countRealHeight(); auto newHeight = countRealHeight();
auto parentSize = parentWidget()->size(); auto parentSize = parentWidget()->size();
setGeometry((parentSize.width() - width()) / 2, (parentSize.height() - newHeight) / 2, width(), newHeight); setGeometry(
(parentSize.width() - width()) / 2,
(parentSize.height() - newHeight) / 2,
width(),
newHeight);
update(); update();
} }
void BoxLayerWidget::setTitle(rpl::producer<TextWithEntities> title) { void BoxLayerWidget::setTitle(rpl::producer<TextWithEntities> title) {
const auto wasTitle = hasTitle(); const auto wasTitle = hasTitle();
if (title) { if (title) {
_title.create(this, rpl::duplicate(title), st::boxTitle); _title.create(this, rpl::duplicate(title), st().title);
_title->show(); _title->show();
std::move( std::move(
title title
@ -323,9 +340,10 @@ void BoxLayerWidget::setDimensions(int newWidth, int maxHeight, bool forceCenter
resize(newWidth, countRealHeight()); resize(newWidth, countRealHeight());
auto newGeometry = geometry(); auto newGeometry = geometry();
auto parentHeight = parentWidget()->height(); auto parentHeight = parentWidget()->height();
if (newGeometry.top() + newGeometry.height() + st::boxVerticalMargin > parentHeight const auto bottomMargin = st().margin.bottom();
if (newGeometry.top() + newGeometry.height() + bottomMargin > parentHeight
|| forceCenterPosition) { || forceCenterPosition) {
const auto top1 = parentHeight - int(st::boxVerticalMargin) - newGeometry.height(); const auto top1 = parentHeight - bottomMargin - newGeometry.height();
const auto top2 = (parentHeight - newGeometry.height()) / 2; const auto top2 = (parentHeight - newGeometry.height()) / 2;
const auto newTop = forceCenterPosition const auto newTop = forceCenterPosition
? std::min(top1, top2) ? std::min(top1, top2)
@ -343,7 +361,10 @@ void BoxLayerWidget::setDimensions(int newWidth, int maxHeight, bool forceCenter
} }
int BoxLayerWidget::countRealHeight() const { int BoxLayerWidget::countRealHeight() const {
return qMin(_fullHeight, parentWidget()->height() - 2 * st::boxVerticalMargin); const auto &margin = st().margin;
return std::min(
_fullHeight,
parentWidget()->height() - margin.top() - margin.bottom());
} }
int BoxLayerWidget::countFullHeight() const { int BoxLayerWidget::countFullHeight() const {

View file

@ -45,6 +45,7 @@ public:
void setLayerType(bool layerType) override; void setLayerType(bool layerType) override;
void setStyle(const style::Box &st) override; void setStyle(const style::Box &st) override;
const style::Box &style() override;
void setTitle(rpl::producer<TextWithEntities> title) override; void setTitle(rpl::producer<TextWithEntities> title) override;
void setAdditionalTitle(rpl::producer<QString> additional) override; void setAdditionalTitle(rpl::producer<QString> additional) override;
void showBox( void showBox(

View file

@ -11,6 +11,16 @@ namespace Ui {
LayerManager::LayerManager(not_null<RpWidget*> widget) : _widget(widget) { LayerManager::LayerManager(not_null<RpWidget*> widget) : _widget(widget) {
} }
void LayerManager::setStyleOverrides(
const style::Box *boxSt,
const style::Box *layerSt) {
_boxSt = boxSt;
_layerSt = layerSt;
if (_layer) {
_layer->setStyleOverrides(_boxSt, _layerSt);
}
}
void LayerManager::setHideByBackgroundClick(bool hide) { void LayerManager::setHideByBackgroundClick(bool hide) {
_hideByBackgroundClick = hide; _hideByBackgroundClick = hide;
if (_layer) { if (_layer) {
@ -55,6 +65,7 @@ void LayerManager::ensureLayerCreated() {
} }
_layer.emplace(_widget); _layer.emplace(_widget);
_layer->setHideByBackgroundClick(_hideByBackgroundClick); _layer->setHideByBackgroundClick(_hideByBackgroundClick);
_layer->setStyleOverrides(_boxSt, _layerSt);
_layer->hideFinishEvents( _layer->hideFinishEvents(
) | rpl::filter([=] { ) | rpl::filter([=] {

View file

@ -10,6 +10,10 @@
#include <QtCore/QMargins> #include <QtCore/QMargins>
namespace style {
struct Box;
} // namespace style
namespace Ui { namespace Ui {
class BoxContent; class BoxContent;
@ -19,6 +23,10 @@ class LayerManager final {
public: public:
explicit LayerManager(not_null<RpWidget*> widget); explicit LayerManager(not_null<RpWidget*> widget);
void setStyleOverrides(
const style::Box *boxSt,
const style::Box *layerSt);
void setHideByBackgroundClick(bool hide); void setHideByBackgroundClick(bool hide);
void showBox( void showBox(
object_ptr<BoxContent> box, object_ptr<BoxContent> box,
@ -34,6 +42,9 @@ private:
const not_null<RpWidget*> _widget; const not_null<RpWidget*> _widget;
base::unique_qptr<LayerStackWidget> _layer; base::unique_qptr<LayerStackWidget> _layer;
const style::Box *_boxSt = nullptr;
const style::Box *_layerSt = nullptr;
bool _hideByBackgroundClick = false; bool _hideByBackgroundClick = false;
}; };

View file

@ -458,6 +458,13 @@ bool LayerStackWidget::layerShown() const {
return _specialLayer || currentLayer() || _mainMenu; return _specialLayer || currentLayer() || _mainMenu;
} }
void LayerStackWidget::setStyleOverrides(
const style::Box *boxSt,
const style::Box *layerSt) {
_boxSt = boxSt;
_layerSt = layerSt;
}
void LayerStackWidget::setCacheImages() { void LayerStackWidget::setCacheImages() {
auto bodyCache = QPixmap(), mainMenuCache = QPixmap(); auto bodyCache = QPixmap(), mainMenuCache = QPixmap();
auto specialLayerCache = QPixmap(); auto specialLayerCache = QPixmap();

View file

@ -16,6 +16,10 @@ class SectionMemento;
struct SectionShow; struct SectionShow;
} // namespace Window } // namespace Window
namespace style {
struct Box;
} // namespace style
namespace Ui { namespace Ui {
class BoxContent; class BoxContent;
@ -93,6 +97,16 @@ public:
void finishAnimating(); void finishAnimating();
rpl::producer<> hideFinishEvents() const; rpl::producer<> hideFinishEvents() const;
void setStyleOverrides(
const style::Box *boxSt,
const style::Box *layerSt);
[[nodiscard]] const style::Box *boxStyleOverrideLayer() const {
return _layerSt;
}
[[nodiscard]] const style::Box *boxStyleOverride() const {
return _boxSt;
}
void showBox( void showBox(
object_ptr<BoxContent> box, object_ptr<BoxContent> box,
LayerOptions options, LayerOptions options,
@ -201,6 +215,9 @@ private:
class BackgroundWidget; class BackgroundWidget;
object_ptr<BackgroundWidget> _background; object_ptr<BackgroundWidget> _background;
const style::Box *_boxSt = nullptr;
const style::Box *_layerSt = nullptr;
bool _hideByBackgroundClick = true; bool _hideByBackgroundClick = true;
rpl::event_stream<> _hideFinishStream; rpl::event_stream<> _hideFinishStream;

View file

@ -24,6 +24,11 @@ ServiceCheck {
Box { Box {
buttonPadding: margins; buttonPadding: margins;
buttonHeight: pixels; buttonHeight: pixels;
button: RoundButton;
margin: margins;
title: FlatLabel;
bg: color;
titleAdditionalFg: color;
} }
boxDuration: 200; boxDuration: 200;
@ -36,12 +41,6 @@ defaultBoxButton: RoundButton(defaultLightButton) {
font: boxButtonFont; font: boxButtonFont;
} }
boxTextStyle: TextStyle(defaultTextStyle) {
font: font(boxFontSize);
linkFont: font(boxFontSize);
linkFontOver: font(boxFontSize underline);
}
boxLabelStyle: TextStyle(boxTextStyle) { boxLabelStyle: TextStyle(boxTextStyle) {
lineHeight: 22px; lineHeight: 22px;
} }
@ -118,7 +117,6 @@ boxOptionListPadding: margins(0px, 0px, 0px, 0px);
boxOptionListSkip: 20px; boxOptionListSkip: 20px;
boxOptionInputSkip: 6px; boxOptionInputSkip: 6px;
boxVerticalMargin: 10px;
boxWidth: 320px; boxWidth: 320px;
boxWideWidth: 364px; boxWideWidth: 364px;
boxPadding: margins(22px, 30px, 22px, 8px); boxPadding: margins(22px, 30px, 22px, 8px);
@ -129,6 +127,11 @@ boxMediumSkip: 20px;
defaultBox: Box { defaultBox: Box {
buttonPadding: margins(8px, 12px, 13px, 12px); buttonPadding: margins(8px, 12px, 13px, 12px);
buttonHeight: 36px; buttonHeight: 36px;
button: defaultBoxButton;
margin: margins(0px, 10px, 0px, 10px);
bg: boxBg;
title: boxTitle;
titleAdditionalFg: boxTitleAdditionalFg;
} }
layerBox: Box(defaultBox) { layerBox: Box(defaultBox) {
buttonPadding: margins(8px, 8px, 8px, 8px); buttonPadding: margins(8px, 8px, 8px, 8px);

View file

@ -67,22 +67,25 @@ RoundRect::RoundRect(
ImageRoundRadius radius, ImageRoundRadius radius,
const style::color &color) const style::color &color)
: _color(color) : _color(color)
, _corners(Images::PrepareCorners(radius, color)) { , _refresh([=] { _corners = Images::PrepareCorners(radius, _color); }) {
_refresh();
style::PaletteChanged( style::PaletteChanged(
) | rpl::start_with_next([=] { ) | rpl::start_with_next(_refresh, _lifetime);
_corners = Images::PrepareCorners(radius, _color);
}, _lifetime);
} }
RoundRect::RoundRect( RoundRect::RoundRect(
int radius, int radius,
const style::color &color) const style::color &color)
: _color(color) : _color(color)
, _corners(Images::PrepareCorners(radius, color)) { , _refresh([=] { _corners = Images::PrepareCorners(radius, _color); }) {
_refresh();
style::PaletteChanged( style::PaletteChanged(
) | rpl::start_with_next([=] { ) | rpl::start_with_next(_refresh, _lifetime);
_corners = Images::PrepareCorners(radius, _color); }
}, _lifetime);
void RoundRect::setColor(const style::color &color) {
_color = color;
_refresh();
} }
const style::color &RoundRect::color() const { const style::color &RoundRect::color() const {

View file

@ -27,6 +27,7 @@ public:
RoundRect(int radius, const style::color &color); RoundRect(int radius, const style::color &color);
[[nodiscard]] const style::color &color() const; [[nodiscard]] const style::color &color() const;
void setColor(const style::color &color);
void paint( void paint(
QPainter &p, QPainter &p,
const QRect &rect, const QRect &rect,
@ -39,6 +40,7 @@ public:
private: private:
style::color _color; style::color _color;
std::array<QImage, 4> _corners; std::array<QImage, 4> _corners;
Fn<void()> _refresh;
rpl::lifetime _lifetime; rpl::lifetime _lifetime;

View file

@ -495,6 +495,7 @@ SettingsButton {
textBgOver: color; textBgOver: color;
font: font; font: font;
rightLabel: FlatLabel;
height: pixels; height: pixels;
padding: margins; padding: margins;
@ -780,6 +781,7 @@ defaultToggle: Toggle {
} }
defaultCheckbox: Checkbox { defaultCheckbox: Checkbox {
textFg: windowFg; textFg: windowFg;
textFgActive: windowFg;
width: -44px; width: -44px;
margin: margins(8px, 8px, 8px, 8px); margin: margins(8px, 8px, 8px, 8px);
@ -821,12 +823,76 @@ defaultMultiSelectItem: MultiSelectItem {
minScale: 0.3; minScale: 0.3;
} }
widgetSlideDuration: 200; defaultMultiSelectSearchField: InputField(defaultInputField) {
widgetFadeDuration: 200; textBg: transparent;
textMargins: margins(2px, 7px, 2px, 0px);
placeholderFg: placeholderFg;
placeholderFgActive: placeholderFgActive;
placeholderFgError: placeholderFgActive;
placeholderMargins: margins(2px, 0px, 2px, 0px);
placeholderScale: 0.;
placeholderFont: normalFont;
border: 0px;
borderActive: 0px;
heightMin: 32px;
font: normalFont;
}
fieldSearchIcon: icon {{ "box_search", menuIconFg, point(9px, 8px) }}; fieldSearchIcon: icon {{ "box_search", menuIconFg, point(9px, 8px) }};
boxFieldSearchIcon: icon {{ "box_search", menuIconFg, point(10px, 9px) }}; boxFieldSearchIcon: icon {{ "box_search", menuIconFg, point(10px, 9px) }};
defaultMultiSelectSearchCancel: CrossButton {
width: 44px;
height: 44px;
cross: CrossAnimation {
size: 36px;
skip: 12px;
stroke: 2px;
minScale: 0.3;
}
crossFg: boxTitleCloseFg;
crossFgOver: boxTitleCloseFgOver;
crossPosition: point(4px, 4px);
duration: 150;
loadingPeriod: 1000;
ripple: RippleAnimation(defaultRippleAnimation) {
color: windowBgOver;
}
}
defaultMultiSelect: MultiSelect {
bg: boxSearchBg;
padding: margins(8px, 6px, 8px, 6px);
maxHeight: 104px;
scroll: ScrollArea(defaultSolidScroll) {
deltat: 3px;
deltab: 3px;
round: 1px;
width: 8px;
deltax: 3px;
hiding: 1000;
}
item: defaultMultiSelectItem;
itemSkip: 8px;
field: defaultMultiSelectSearchField;
fieldMinWidth: 42px;
fieldIcon: boxFieldSearchIcon;
fieldIconSkip: 36px;
fieldCancel: defaultMultiSelectSearchCancel;
fieldCancelSkip: 40px;
}
widgetSlideDuration: 200;
widgetFadeDuration: 200;
SettingsSlider { SettingsSlider {
height: pixels; height: pixels;
barTop: pixels; barTop: pixels;
@ -1125,6 +1191,7 @@ PeerListItem {
button: OutlineButton; button: OutlineButton;
checkbox: RoundImageCheckbox; checkbox: RoundImageCheckbox;
disabledCheckFg: color;
statusFg: color; statusFg: color;
statusFgOver: color; statusFgOver: color;
statusFgActive: color; statusFgActive: color;
@ -1132,6 +1199,8 @@ PeerListItem {
PeerList { PeerList {
padding: margins; padding: margins;
bg: color;
about: FlatLabel;
item: PeerListItem; item: PeerListItem;
} }
@ -1163,13 +1232,31 @@ defaultPeerListItem: PeerListItem {
photoSize: 46px; photoSize: 46px;
button: defaultPeerListButton; button: defaultPeerListButton;
checkbox: defaultPeerListCheckbox; checkbox: defaultPeerListCheckbox;
disabledCheckFg: menuIconFg;
statusFg: windowSubTextFg; statusFg: windowSubTextFg;
statusFgOver: windowSubTextFgOver; statusFgOver: windowSubTextFgOver;
statusFgActive: windowActiveTextFg; statusFgActive: windowActiveTextFg;
} }
boxTextStyle: TextStyle(defaultTextStyle) {
font: font(boxFontSize);
linkFont: font(boxFontSize);
linkFontOver: font(boxFontSize underline);
}
defaultPeerListAbout: FlatLabel(defaultFlatLabel) {
minWidth: 240px;
textFg: membersAboutLimitFg;
align: align(top);
style: TextStyle(boxTextStyle) {
lineHeight: 22px;
}
}
defaultPeerList: PeerList { defaultPeerList: PeerList {
padding: margins(0px, 0px, 0px, 0px); padding: margins(0px, 0px, 0px, 0px);
bg: contactsBg;
about: defaultPeerListAbout;
item: defaultPeerListItem; item: defaultPeerListItem;
} }
@ -1256,6 +1343,11 @@ defaultSettingsToggle: Toggle(defaultToggle) {
defaultSettingsToggleOver: Toggle(defaultSettingsToggle) { defaultSettingsToggleOver: Toggle(defaultSettingsToggle) {
untoggledFg: menuIconFgOver; untoggledFg: menuIconFgOver;
} }
defaultSettingsRightLabel: FlatLabel(defaultFlatLabel) {
textFg: windowActiveTextFg;
style: boxTextStyle;
maxHeight: 20px;
}
defaultSettingsButton: SettingsButton { defaultSettingsButton: SettingsButton {
textFg: windowBoldFg; textFg: windowBoldFg;
textFgOver: windowBoldFgOver; textFgOver: windowBoldFgOver;
@ -1263,6 +1355,7 @@ defaultSettingsButton: SettingsButton {
textBgOver: windowBgOver; textBgOver: windowBgOver;
font: boxTextFont; font: boxTextFont;
rightLabel: defaultSettingsRightLabel;
height: 20px; height: 20px;
padding: margins(22px, 10px, 22px, 8px); padding: margins(22px, 10px, 22px, 8px);