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
groupCallBg: #131417; // group call popup background
groupCallActiveFg: #4db8ff; // group call active controls text
groupCallMembersBg: #1a1c1f; // group call members list background
groupCallMembersFg: #ffffff; // group call member name text
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
groupCallMuted1: #0992ef; // group call muted button color1
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
callBarMuteRipple: dialogsRippleBgActive; // active phone call bar mute and hangup button ripple effect

View file

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

View file

@ -45,6 +45,7 @@ class BoxContentDelegate {
public:
virtual void setLayerType(bool layerType) = 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 setAdditionalTitle(rpl::producer<QString> additional) = 0;
virtual void setCloseByOutsideClick(bool close) = 0;

View file

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

View file

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

View file

@ -11,6 +11,16 @@ namespace Ui {
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) {
_hideByBackgroundClick = hide;
if (_layer) {
@ -55,6 +65,7 @@ void LayerManager::ensureLayerCreated() {
}
_layer.emplace(_widget);
_layer->setHideByBackgroundClick(_hideByBackgroundClick);
_layer->setStyleOverrides(_boxSt, _layerSt);
_layer->hideFinishEvents(
) | rpl::filter([=] {

View file

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

View file

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

View file

@ -16,6 +16,10 @@ class SectionMemento;
struct SectionShow;
} // namespace Window
namespace style {
struct Box;
} // namespace style
namespace Ui {
class BoxContent;
@ -93,6 +97,16 @@ public:
void finishAnimating();
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(
object_ptr<BoxContent> box,
LayerOptions options,
@ -201,6 +215,9 @@ private:
class BackgroundWidget;
object_ptr<BackgroundWidget> _background;
const style::Box *_boxSt = nullptr;
const style::Box *_layerSt = nullptr;
bool _hideByBackgroundClick = true;
rpl::event_stream<> _hideFinishStream;

View file

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

View file

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

View file

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

View file

@ -495,6 +495,7 @@ SettingsButton {
textBgOver: color;
font: font;
rightLabel: FlatLabel;
height: pixels;
padding: margins;
@ -780,6 +781,7 @@ defaultToggle: Toggle {
}
defaultCheckbox: Checkbox {
textFg: windowFg;
textFgActive: windowFg;
width: -44px;
margin: margins(8px, 8px, 8px, 8px);
@ -821,12 +823,76 @@ defaultMultiSelectItem: MultiSelectItem {
minScale: 0.3;
}
widgetSlideDuration: 200;
widgetFadeDuration: 200;
defaultMultiSelectSearchField: InputField(defaultInputField) {
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) }};
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 {
height: pixels;
barTop: pixels;
@ -1125,6 +1191,7 @@ PeerListItem {
button: OutlineButton;
checkbox: RoundImageCheckbox;
disabledCheckFg: color;
statusFg: color;
statusFgOver: color;
statusFgActive: color;
@ -1132,6 +1199,8 @@ PeerListItem {
PeerList {
padding: margins;
bg: color;
about: FlatLabel;
item: PeerListItem;
}
@ -1163,13 +1232,31 @@ defaultPeerListItem: PeerListItem {
photoSize: 46px;
button: defaultPeerListButton;
checkbox: defaultPeerListCheckbox;
disabledCheckFg: menuIconFg;
statusFg: windowSubTextFg;
statusFgOver: windowSubTextFgOver;
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 {
padding: margins(0px, 0px, 0px, 0px);
bg: contactsBg;
about: defaultPeerListAbout;
item: defaultPeerListItem;
}
@ -1256,6 +1343,11 @@ defaultSettingsToggle: Toggle(defaultToggle) {
defaultSettingsToggleOver: Toggle(defaultSettingsToggle) {
untoggledFg: menuIconFgOver;
}
defaultSettingsRightLabel: FlatLabel(defaultFlatLabel) {
textFg: windowActiveTextFg;
style: boxTextStyle;
maxHeight: 20px;
}
defaultSettingsButton: SettingsButton {
textFg: windowBoldFg;
textFgOver: windowBoldFgOver;
@ -1263,6 +1355,7 @@ defaultSettingsButton: SettingsButton {
textBgOver: windowBgOver;
font: boxTextFont;
rightLabel: defaultSettingsRightLabel;
height: 20px;
padding: margins(22px, 10px, 22px, 8px);