mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-14 21:27:07 +02:00
Custom colors in history_view_service_message module.
This commit is contained in:
parent
1a4a9319f3
commit
2a2607d026
24 changed files with 520 additions and 367 deletions
|
@ -237,7 +237,10 @@ InnerWidget::InnerWidget(
|
|||
, _channel(channel)
|
||||
, _history(channel->owner().history(channel))
|
||||
, _api(&_channel->session().mtp())
|
||||
, _pathGradient(HistoryView::MakePathShiftGradient([=] { update(); }))
|
||||
, _pathGradient(
|
||||
HistoryView::MakePathShiftGradient(
|
||||
controller->chatStyle(),
|
||||
[=] { update(); }))
|
||||
, _scrollDateCheck([=] { scrollDateCheck(); })
|
||||
, _emptyText(
|
||||
st::historyAdminLogEmptyWidth
|
||||
|
@ -906,8 +909,14 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
|
|||
Painter p(this);
|
||||
|
||||
auto clip = e->rect();
|
||||
auto context = _controller->preparePaintContext({
|
||||
.theme = _theme.get(),
|
||||
.visibleAreaTop = _visibleTop,
|
||||
.visibleAreaTopGlobal = mapToGlobal(QPoint(0, _visibleTop)).y(),
|
||||
.clip = clip,
|
||||
});
|
||||
if (_items.empty() && _upLoaded && _downLoaded) {
|
||||
paintEmpty(p);
|
||||
paintEmpty(p, context.st);
|
||||
} else {
|
||||
_pathGradient->startFrame(
|
||||
0,
|
||||
|
@ -923,12 +932,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
|
|||
});
|
||||
if (from != end) {
|
||||
auto top = itemTop(from->get());
|
||||
auto context = _controller->preparePaintContext({
|
||||
.theme = _theme.get(),
|
||||
.visibleAreaTop = _visibleTop,
|
||||
.visibleAreaTopGlobal = mapToGlobal(QPoint(0, _visibleTop)).y(),
|
||||
.clip = clip,
|
||||
}).translated(0, -top);
|
||||
context.translate(0, -top);
|
||||
p.translate(0, top);
|
||||
for (auto i = from; i != to; ++i) {
|
||||
const auto view = i->get();
|
||||
|
@ -1000,10 +1004,11 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
|
|||
const auto chatWide =
|
||||
_controller->adaptive().isChatWide();
|
||||
if (const auto date = view->Get<HistoryView::DateBadge>()) {
|
||||
date->paint(p, dateY, width, chatWide);
|
||||
date->paint(p, context.st, dateY, width, chatWide);
|
||||
} else {
|
||||
HistoryView::ServiceMessagePainter::paintDate(
|
||||
HistoryView::ServiceMessagePainter::PaintDate(
|
||||
p,
|
||||
context.st,
|
||||
view->dateTime(),
|
||||
dateY,
|
||||
width,
|
||||
|
@ -1043,19 +1048,14 @@ auto InnerWidget::viewForItem(const HistoryItem *item) -> Element* {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void InnerWidget::paintEmpty(Painter &p) {
|
||||
void InnerWidget::paintEmpty(Painter &p, not_null<const Ui::ChatStyle*> st) {
|
||||
auto rectWidth = st::historyAdminLogEmptyWidth;
|
||||
auto innerWidth = rectWidth - st::historyAdminLogEmptyPadding.left() - st::historyAdminLogEmptyPadding.right();
|
||||
auto rectHeight = st::historyAdminLogEmptyPadding.top() + _emptyText.countHeight(innerWidth) + st::historyAdminLogEmptyPadding.bottom();
|
||||
auto rect = QRect((width() - rectWidth) / 2, (height() - rectHeight) / 3, rectWidth, rectHeight);
|
||||
HistoryView::ServiceMessagePainter::paintBubble(
|
||||
p,
|
||||
rect.x(),
|
||||
rect.y(),
|
||||
rect.width(),
|
||||
rect.height());
|
||||
HistoryView::ServiceMessagePainter::PaintBubble(p, st, rect);
|
||||
|
||||
p.setPen(st::msgServiceFg);
|
||||
p.setPen(st->msgServiceFg());
|
||||
_emptyText.draw(p, rect.x() + st::historyAdminLogEmptyPadding.left(), rect.y() + st::historyAdminLogEmptyPadding.top(), innerWidth, style::al_top);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ enum class PointState : char;
|
|||
|
||||
namespace Ui {
|
||||
class PopupMenu;
|
||||
class ChatStyle;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
|
@ -213,7 +214,7 @@ private:
|
|||
void updateSize();
|
||||
void updateMinMaxIds();
|
||||
void updateEmptyText();
|
||||
void paintEmpty(Painter &p);
|
||||
void paintEmpty(Painter &p, not_null<const Ui::ChatStyle*> st);
|
||||
void clearAfterFilterChange();
|
||||
void clearAndRequestLog();
|
||||
void addEvents(Direction direction, const QVector<MTPChannelAdminLogEvent> &events);
|
||||
|
|
|
@ -159,7 +159,10 @@ HistoryInner::HistoryInner(
|
|||
, _peer(history->peer)
|
||||
, _history(history)
|
||||
, _migrated(history->migrateFrom())
|
||||
, _pathGradient(HistoryView::MakePathShiftGradient([=] { update(); }))
|
||||
, _pathGradient(
|
||||
HistoryView::MakePathShiftGradient(
|
||||
controller->chatStyle(),
|
||||
[=] { update(); }))
|
||||
, _scrollDateCheck([this] { scrollDateCheck(); })
|
||||
, _scrollDateHideTimer([this] { scrollDateHideByTimer(); }) {
|
||||
Instance = this;
|
||||
|
@ -543,12 +546,16 @@ TextSelection HistoryInner::itemRenderSelection(
|
|||
return TextSelection();
|
||||
}
|
||||
|
||||
void HistoryInner::paintEmpty(Painter &p, int width, int height) {
|
||||
void HistoryInner::paintEmpty(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
int width,
|
||||
int height) {
|
||||
if (!_emptyPainter) {
|
||||
_emptyPainter = std::make_unique<HistoryView::EmptyPainter>(
|
||||
_history);
|
||||
}
|
||||
_emptyPainter->paint(p, width, height);
|
||||
_emptyPainter->paint(p, st, width, height);
|
||||
}
|
||||
|
||||
void HistoryInner::paintEvent(QPaintEvent *e) {
|
||||
|
@ -563,37 +570,47 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
|||
_userpicsCache.clear();
|
||||
});
|
||||
|
||||
Painter p(this);
|
||||
auto clip = e->rect();
|
||||
|
||||
const auto visibleAreaTopGlobal = mapToGlobal(
|
||||
QPoint(0, _visibleAreaTop)).y();
|
||||
auto context = _controller->preparePaintContext({
|
||||
.theme = _theme.get(),
|
||||
.visibleAreaTop = _visibleAreaTop,
|
||||
.visibleAreaTopGlobal = visibleAreaTopGlobal,
|
||||
.clip = clip,
|
||||
});
|
||||
_pathGradient->startFrame(
|
||||
0,
|
||||
width(),
|
||||
std::min(st::msgMaxWidth / 2, width() / 2));
|
||||
|
||||
Painter p(this);
|
||||
auto clip = e->rect();
|
||||
|
||||
const auto historyDisplayedEmpty = _history->isDisplayedEmpty()
|
||||
&& (!_migrated || _migrated->isDisplayedEmpty());
|
||||
bool noHistoryDisplayed = _firstLoading || historyDisplayedEmpty;
|
||||
if (!_firstLoading && _botAbout && !_botAbout->info->text.isEmpty() && _botAbout->height > 0) {
|
||||
const auto st = context.st;
|
||||
const auto stm = &st->messageStyle(false, false);
|
||||
if (clip.y() < _botAbout->rect.y() + _botAbout->rect.height() && clip.y() + clip.height() > _botAbout->rect.y()) {
|
||||
p.setTextPalette(st::inTextPalette);
|
||||
Ui::FillRoundRect(p, _botAbout->rect, st::msgInBg, Ui::MessageInCorners, &st::msgInShadow);
|
||||
p.setTextPalette(stm->textPalette);
|
||||
Ui::FillRoundRect(p, _botAbout->rect, stm->msgBg, stm->corners, &stm->msgShadow);
|
||||
|
||||
auto top = _botAbout->rect.top() + st::msgPadding.top();
|
||||
if (!_history->peer->isRepliesChat()) {
|
||||
p.setFont(st::msgNameFont);
|
||||
p.setPen(st::dialogsNameFg);
|
||||
p.setPen(st->dialogsNameFg());
|
||||
p.drawText(_botAbout->rect.left() + st::msgPadding.left(), top + st::msgNameFont->ascent, tr::lng_bot_description(tr::now));
|
||||
top += +st::msgNameFont->height + st::botDescSkip;
|
||||
}
|
||||
|
||||
p.setPen(st::historyTextInFg);
|
||||
p.setPen(stm->historyTextFg);
|
||||
_botAbout->info->text.draw(p, _botAbout->rect.left() + st::msgPadding.left(), top, _botAbout->width);
|
||||
|
||||
p.restoreTextPalette();
|
||||
}
|
||||
} else if (historyDisplayedEmpty) {
|
||||
paintEmpty(p, width(), height());
|
||||
paintEmpty(p, context.st, width(), height());
|
||||
} else {
|
||||
_emptyPainter = nullptr;
|
||||
}
|
||||
|
@ -611,8 +628,6 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
|||
} else {
|
||||
seltoy += _dragSelTo->height();
|
||||
}
|
||||
const auto visibleAreaTopGlobal = mapToGlobal(
|
||||
QPoint(0, _visibleAreaTop)).y();
|
||||
|
||||
auto mtop = migratedTop();
|
||||
auto htop = historyTop();
|
||||
|
@ -625,12 +640,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
|||
auto item = view->data();
|
||||
|
||||
auto top = mtop + block->y() + view->y();
|
||||
auto context = _controller->preparePaintContext({
|
||||
.theme = _theme.get(),
|
||||
.visibleAreaTop = _visibleAreaTop,
|
||||
.visibleAreaTopGlobal = visibleAreaTopGlobal,
|
||||
.clip = clip,
|
||||
}).translated(0, -top);
|
||||
context.translate(0, -top);
|
||||
p.translate(0, top);
|
||||
if (context.clip.y() < view->height()) while (top < drawToY) {
|
||||
context.outbg = view->hasOutLayout();
|
||||
|
@ -666,6 +676,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
|||
item = view->data();
|
||||
}
|
||||
p.translate(0, -top);
|
||||
context.translate(0, top);
|
||||
}
|
||||
if (htop >= 0) {
|
||||
auto iBlock = (_curHistory == _history ? _curBlock : 0);
|
||||
|
@ -675,15 +686,9 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
|||
auto item = view->data();
|
||||
auto readTill = (HistoryItem*)nullptr;
|
||||
auto top = htop + block->y() + view->y();
|
||||
auto context = _controller->preparePaintContext({
|
||||
.theme = _theme.get(),
|
||||
.visibleAreaTop = _visibleAreaTop,
|
||||
.visibleAreaTopGlobal = visibleAreaTopGlobal,
|
||||
.visibleAreaWidth = width(),
|
||||
.clip = clip.intersected(
|
||||
QRect(0, hdrawtop, width(), clip.top() + clip.height())
|
||||
),
|
||||
}).translated(0, -top);
|
||||
context.clip = clip.intersected(
|
||||
QRect(0, hdrawtop, width(), clip.top() + clip.height()));
|
||||
context.translate(0, -top);
|
||||
p.translate(0, top);
|
||||
while (top < drawToY) {
|
||||
const auto height = view->height();
|
||||
|
@ -812,10 +817,11 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
|||
? itemtop
|
||||
: (dateTop - st::msgServiceMargin.top());
|
||||
if (const auto date = view->Get<HistoryView::DateBadge>()) {
|
||||
date->paint(p, dateY, _contentWidth, _isChatWide);
|
||||
date->paint(p, context.st, dateY, _contentWidth, _isChatWide);
|
||||
} else {
|
||||
HistoryView::ServiceMessagePainter::paintDate(
|
||||
HistoryView::ServiceMessagePainter::PaintDate(
|
||||
p,
|
||||
context.st,
|
||||
view->dateTime(),
|
||||
dateY,
|
||||
_contentWidth,
|
||||
|
|
|
@ -35,6 +35,7 @@ class SessionController;
|
|||
|
||||
namespace Ui {
|
||||
class ChatTheme;
|
||||
class ChatStyle;
|
||||
class PopupMenu;
|
||||
enum class ReportReason;
|
||||
class PathShiftGradient;
|
||||
|
@ -246,7 +247,11 @@ private:
|
|||
std::unique_ptr<QMimeData> prepareDrag();
|
||||
void performDrag();
|
||||
|
||||
void paintEmpty(Painter &p, int width, int height);
|
||||
void paintEmpty(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
QPoint mapPointToItem(QPoint p, const Element *view) const;
|
||||
QPoint mapPointToItem(QPoint p, const HistoryItem *item) const;
|
||||
|
|
|
@ -107,6 +107,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/chat/pinned_bar.h"
|
||||
#include "ui/chat/group_call_bar.h"
|
||||
#include "ui/chat/chat_theme.h"
|
||||
#include "ui/chat/chat_style.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/item_text_options.h"
|
||||
#include "ui/unread_badge.h"
|
||||
|
@ -7058,9 +7059,10 @@ void HistoryWidget::paintEvent(QPaintEvent *e) {
|
|||
- st::msgServiceMargin.bottom()) / 2,
|
||||
w,
|
||||
h);
|
||||
HistoryView::ServiceMessagePainter::paintBubble(p, tr.x(), tr.y(), tr.width(), tr.height());
|
||||
const auto st = controller()->chatStyle();
|
||||
HistoryView::ServiceMessagePainter::PaintBubble(p, st, tr);
|
||||
|
||||
p.setPen(st::msgServiceFg);
|
||||
p.setPen(st->msgServiceFg());
|
||||
p.setFont(st::msgServiceFont->f);
|
||||
p.drawTextLeft(tr.left() + st::msgPadding.left(), tr.top() + st::msgServicePadding.top(), width(), tr::lng_willbe_history(tr::now));
|
||||
|
||||
|
|
|
@ -23,13 +23,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "chat_helpers/stickers_emoji_pack.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "ui/effects/path_shift_gradient.h"
|
||||
#include "ui/chat/chat_style.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/toasts/common_toasts.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_groups.h"
|
||||
#include "data/data_media_types.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "layout/layout_selection.h"
|
||||
#include "app.h"
|
||||
#include "styles/style_chat.h"
|
||||
|
||||
|
@ -62,10 +62,11 @@ bool IsAttachedToPreviousInSavedMessages(
|
|||
} // namespace
|
||||
|
||||
std::unique_ptr<Ui::PathShiftGradient> MakePathShiftGradient(
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
Fn<void()> update) {
|
||||
return std::make_unique<Ui::PathShiftGradient>(
|
||||
st::msgServiceBg,
|
||||
st::msgServiceBgSelected,
|
||||
st->msgServiceBg(),
|
||||
st->msgServiceBgSelected(),
|
||||
std::move(update));
|
||||
}
|
||||
|
||||
|
@ -73,7 +74,10 @@ SimpleElementDelegate::SimpleElementDelegate(
|
|||
not_null<Window::SessionController*> controller,
|
||||
Fn<void()> update)
|
||||
: _controller(controller)
|
||||
, _pathGradient(MakePathShiftGradient(std::move(update))) {
|
||||
, _pathGradient(
|
||||
MakePathShiftGradient(
|
||||
controller->chatStyle(),
|
||||
std::move(update))) {
|
||||
}
|
||||
|
||||
SimpleElementDelegate::~SimpleElementDelegate() = default;
|
||||
|
@ -259,7 +263,13 @@ int UnreadBar::marginTop() {
|
|||
return st::lineWidth + st::historyUnreadBarMargin;
|
||||
}
|
||||
|
||||
void UnreadBar::paint(Painter &p, int y, int w, bool chatWide) const {
|
||||
void UnreadBar::paint(
|
||||
Painter &p,
|
||||
const PaintContext &context,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide) const {
|
||||
const auto st = context.st;
|
||||
const auto bottom = y + height();
|
||||
y += marginTop();
|
||||
p.fillRect(
|
||||
|
@ -267,15 +277,15 @@ void UnreadBar::paint(Painter &p, int y, int w, bool chatWide) const {
|
|||
y,
|
||||
w,
|
||||
height() - marginTop() - st::lineWidth,
|
||||
st::historyUnreadBarBg);
|
||||
st->historyUnreadBarBg());
|
||||
p.fillRect(
|
||||
0,
|
||||
bottom - st::lineWidth,
|
||||
w,
|
||||
st::lineWidth,
|
||||
st::historyUnreadBarBorder);
|
||||
st->historyUnreadBarBorder());
|
||||
p.setFont(st::historyUnreadBarFont);
|
||||
p.setPen(st::historyUnreadBarFg);
|
||||
p.setPen(st->historyUnreadBarFg());
|
||||
|
||||
int maxwidth = w;
|
||||
if (chatWide) {
|
||||
|
@ -310,8 +320,13 @@ int DateBadge::height() const {
|
|||
+ st::msgServiceMargin.bottom();
|
||||
}
|
||||
|
||||
void DateBadge::paint(Painter &p, int y, int w, bool chatWide) const {
|
||||
ServiceMessagePainter::paintDate(p, text, width, y, w, chatWide);
|
||||
void DateBadge::paint(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide) const {
|
||||
ServiceMessagePainter::PaintDate(p, st, text, width, y, w, chatWide);
|
||||
}
|
||||
|
||||
Element::Element(
|
||||
|
@ -367,6 +382,7 @@ void Element::refreshDataIdHook() {
|
|||
|
||||
void Element::paintHighlight(
|
||||
Painter &p,
|
||||
const PaintContext &context,
|
||||
int geometryHeight) const {
|
||||
const auto top = marginTop();
|
||||
const auto bottom = marginBottom();
|
||||
|
@ -374,7 +390,7 @@ void Element::paintHighlight(
|
|||
const auto skiptop = top - fill;
|
||||
const auto fillheight = fill + geometryHeight + fill;
|
||||
|
||||
paintCustomHighlight(p, skiptop, fillheight, data());
|
||||
paintCustomHighlight(p, context, skiptop, fillheight, data());
|
||||
}
|
||||
|
||||
float64 Element::highlightOpacity(not_null<const HistoryItem*> item) const {
|
||||
|
@ -392,6 +408,7 @@ float64 Element::highlightOpacity(not_null<const HistoryItem*> item) const {
|
|||
|
||||
void Element::paintCustomHighlight(
|
||||
Painter &p,
|
||||
const PaintContext &context,
|
||||
int y,
|
||||
int height,
|
||||
not_null<const HistoryItem*> item) const {
|
||||
|
@ -406,7 +423,7 @@ void Element::paintCustomHighlight(
|
|||
y,
|
||||
width(),
|
||||
height,
|
||||
st::defaultTextPalette.selectOverlay);
|
||||
context.st->msgSelectOverlay());
|
||||
p.setOpacity(o);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace Ui {
|
|||
class PathShiftGradient;
|
||||
struct BubblePattern;
|
||||
struct ChatPaintContext;
|
||||
class ChatStyle;
|
||||
} // namespace Ui
|
||||
|
||||
namespace HistoryView {
|
||||
|
@ -36,6 +37,8 @@ struct StateRequest;
|
|||
struct TextState;
|
||||
class Media;
|
||||
|
||||
using PaintContext = Ui::ChatPaintContext;
|
||||
|
||||
enum class Context : char {
|
||||
History,
|
||||
Replies,
|
||||
|
@ -94,6 +97,7 @@ public:
|
|||
};
|
||||
|
||||
[[nodiscard]] std::unique_ptr<Ui::PathShiftGradient> MakePathShiftGradient(
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
Fn<void()> update);
|
||||
|
||||
class SimpleElementDelegate : public ElementDelegate {
|
||||
|
@ -177,7 +181,12 @@ struct UnreadBar : public RuntimeComponent<UnreadBar, Element> {
|
|||
static int height();
|
||||
static int marginTop();
|
||||
|
||||
void paint(Painter &p, int y, int w, bool chatWide) const;
|
||||
void paint(
|
||||
Painter &p,
|
||||
const PaintContext &context,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide) const;
|
||||
|
||||
QString text;
|
||||
int width = 0;
|
||||
|
@ -191,15 +200,18 @@ struct DateBadge : public RuntimeComponent<DateBadge, Element> {
|
|||
void init(const QString &date);
|
||||
|
||||
int height() const;
|
||||
void paint(Painter &p, int y, int w, bool chatWide) const;
|
||||
void paint(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide) const;
|
||||
|
||||
QString text;
|
||||
int width = 0;
|
||||
|
||||
};
|
||||
|
||||
using PaintContext = Ui::ChatPaintContext;
|
||||
|
||||
class Element
|
||||
: public Object
|
||||
, public RuntimeComposer<Element>
|
||||
|
@ -347,6 +359,7 @@ public:
|
|||
|
||||
void paintCustomHighlight(
|
||||
Painter &p,
|
||||
const PaintContext &context,
|
||||
int y,
|
||||
int height,
|
||||
not_null<const HistoryItem*> item) const;
|
||||
|
@ -376,6 +389,7 @@ public:
|
|||
protected:
|
||||
void paintHighlight(
|
||||
Painter &p,
|
||||
const PaintContext &context,
|
||||
int geometryHeight) const;
|
||||
|
||||
[[nodiscard]] ClickHandlerPtr fromLink() const;
|
||||
|
|
|
@ -7,17 +7,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "history/view/history_view_empty_list_bubble.h"
|
||||
|
||||
#include "history/view/history_view_list_widget.h"
|
||||
#include "ui/chat/chat_style.h"
|
||||
#include "history/view/history_view_service_message.h"
|
||||
|
||||
namespace HistoryView {
|
||||
|
||||
EmptyListBubbleWidget::EmptyListBubbleWidget(
|
||||
not_null<ListWidget*> parent,
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
const style::margins &padding)
|
||||
: RpWidget(parent)
|
||||
, _padding(padding) {
|
||||
|
||||
, _padding(padding)
|
||||
, _st(st) {
|
||||
parent->sizeValue(
|
||||
) | rpl::start_with_next([=](const QSize &s) {
|
||||
updateGeometry(s);
|
||||
|
@ -42,14 +43,9 @@ void EmptyListBubbleWidget::paintEvent(QPaintEvent *e) {
|
|||
Painter p(this);
|
||||
|
||||
const auto r = rect();
|
||||
HistoryView::ServiceMessagePainter::paintBubble(
|
||||
p,
|
||||
r.x(),
|
||||
r.y(),
|
||||
r.width(),
|
||||
r.height());
|
||||
HistoryView::ServiceMessagePainter::PaintBubble(p, _st, r);
|
||||
|
||||
p.setPen(st::msgServiceFg);
|
||||
p.setPen(_st->msgServiceFg());
|
||||
_text.draw(
|
||||
p,
|
||||
r.x() + _padding.left(),
|
||||
|
|
|
@ -9,14 +9,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "ui/rp_widget.h"
|
||||
|
||||
namespace HistoryView {
|
||||
namespace Ui {
|
||||
class ChatStyle;
|
||||
} // namespace Ui
|
||||
|
||||
class ListWidget;
|
||||
namespace HistoryView {
|
||||
|
||||
class EmptyListBubbleWidget : public Ui::RpWidget {
|
||||
public:
|
||||
EmptyListBubbleWidget(
|
||||
not_null<ListWidget*> parent,
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
const style::margins &padding);
|
||||
|
||||
void setText(const TextWithEntities &textWithEntities);
|
||||
|
@ -29,6 +32,7 @@ private:
|
|||
void updateGeometry(const QSize &size);
|
||||
|
||||
const style::margins &_padding;
|
||||
const not_null<const Ui::ChatStyle*> _st;
|
||||
Ui::Text::String _text;
|
||||
int _innerWidth = 0;
|
||||
int _forceWidth = 0;
|
||||
|
|
|
@ -256,7 +256,10 @@ ListWidget::ListWidget(
|
|||
, _controller(controller)
|
||||
, _context(_delegate->listContext())
|
||||
, _itemAverageHeight(itemMinimalHeight())
|
||||
, _pathGradient(MakePathShiftGradient([=] { update(); }))
|
||||
, _pathGradient(
|
||||
MakePathShiftGradient(
|
||||
controller->chatStyle(),
|
||||
[=] { update(); }))
|
||||
, _scrollDateCheck([this] { scrollDateCheck(); })
|
||||
, _applyUpdatedScrollState([this] { applyUpdatedScrollState(); })
|
||||
, _selectEnabled(_delegate->listAllowsMultiSelect())
|
||||
|
@ -1700,11 +1703,14 @@ void ListWidget::paintEvent(QPaintEvent *e) {
|
|||
int dateY = /*noFloatingDate ? itemtop :*/ (dateTop - st::msgServiceMargin.top());
|
||||
int width = view->width();
|
||||
if (const auto date = view->Get<HistoryView::DateBadge>()) {
|
||||
date->paint(p, dateY, width, _isChatWide);
|
||||
date->paint(p, context.st, dateY, width, _isChatWide);
|
||||
} else {
|
||||
ServiceMessagePainter::paintDate(
|
||||
ServiceMessagePainter::PaintDate(
|
||||
p,
|
||||
ItemDateText(view->data(), IsItemScheduledUntilOnline(view->data())),
|
||||
context.st,
|
||||
ItemDateText(
|
||||
view->data(),
|
||||
IsItemScheduledUntilOnline(view->data())),
|
||||
dateY,
|
||||
width,
|
||||
_isChatWide);
|
||||
|
|
|
@ -498,7 +498,12 @@ void Message::draw(Painter &p, const PaintContext &context) const {
|
|||
auto unreadbarh = bar->height();
|
||||
if (context.clip.intersects(QRect(0, dateh, width(), unreadbarh))) {
|
||||
p.translate(0, dateh);
|
||||
bar->paint(p, 0, width(), delegate()->elementIsChatWide());
|
||||
bar->paint(
|
||||
p,
|
||||
context,
|
||||
0,
|
||||
width(),
|
||||
delegate()->elementIsChatWide());
|
||||
p.translate(0, -dateh);
|
||||
}
|
||||
}
|
||||
|
@ -537,9 +542,9 @@ void Message::draw(Painter &p, const PaintContext &context) const {
|
|||
}
|
||||
|
||||
if (customHighlight) {
|
||||
media->drawHighlight(p, localMediaTop);
|
||||
media->drawHighlight(p, context, localMediaTop);
|
||||
} else {
|
||||
paintHighlight(p, g.height());
|
||||
paintHighlight(p, context, g.height());
|
||||
}
|
||||
|
||||
const auto roll = media ? media->bubbleRoll() : Media::BubbleRoll();
|
||||
|
|
|
@ -163,6 +163,7 @@ ScheduledWidget::ScheduledWidget(
|
|||
{
|
||||
auto emptyInfo = base::make_unique_q<EmptyListBubbleWidget>(
|
||||
_inner,
|
||||
controller->chatStyle(),
|
||||
st::msgServicePadding);
|
||||
const auto emptyText = Ui::Text::Semibold(
|
||||
tr::lng_scheduled_messages_empty(tr::now));
|
||||
|
|
|
@ -41,98 +41,6 @@ enum CornerHorizontalSide {
|
|||
CornerRight = 0x01,
|
||||
};
|
||||
|
||||
class ServiceMessageStyleData : public Data::AbstractStructure {
|
||||
public:
|
||||
ServiceMessageStyleData() {
|
||||
style::PaletteChanged(
|
||||
) | rpl::start_with_next([=] {
|
||||
for (auto &corner : corners) {
|
||||
corner = QPixmap();
|
||||
}
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
// circle[CircleMask value]
|
||||
QImage circle[2];
|
||||
|
||||
// corners[(CircleMask value) * MaskMultiplier | (CornerVerticalSide value) | (CornerHorizontalSide value)]
|
||||
QPixmap corners[8];
|
||||
|
||||
base::flat_map<std::pair<int, uint32>, QPixmap> overridenCorners;
|
||||
|
||||
private:
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
Data::GlobalStructurePointer<ServiceMessageStyleData> serviceMessageStyle;
|
||||
|
||||
int historyServiceMsgRadius() {
|
||||
static int HistoryServiceMsgRadius = ([]() {
|
||||
auto minMsgHeight = (st::msgServiceFont->height + st::msgServicePadding.top() + st::msgServicePadding.bottom());
|
||||
return minMsgHeight / 2;
|
||||
})();
|
||||
return HistoryServiceMsgRadius;
|
||||
}
|
||||
|
||||
int historyServiceMsgInvertedRadius() {
|
||||
static int HistoryServiceMsgInvertedRadius = ([]() {
|
||||
auto minRowHeight = st::msgServiceFont->height;
|
||||
return minRowHeight - historyServiceMsgRadius();
|
||||
})();
|
||||
return HistoryServiceMsgInvertedRadius;
|
||||
}
|
||||
|
||||
int historyServiceMsgInvertedShrink() {
|
||||
static int HistoryServiceMsgInvertedShrink = ([]() {
|
||||
return (historyServiceMsgInvertedRadius() * 2) / 3;
|
||||
})();
|
||||
return HistoryServiceMsgInvertedShrink;
|
||||
}
|
||||
|
||||
void createCircleMasks() {
|
||||
serviceMessageStyle.createIfNull();
|
||||
if (!serviceMessageStyle->circle[NormalMask].isNull()) return;
|
||||
|
||||
int size = historyServiceMsgRadius() * 2;
|
||||
serviceMessageStyle->circle[NormalMask] = style::createCircleMask(size);
|
||||
int sizeInverted = historyServiceMsgInvertedRadius() * 2;
|
||||
serviceMessageStyle->circle[InvertedMask] = style::createInvertedCircleMask(sizeInverted);
|
||||
}
|
||||
|
||||
uint32 ColorToUint(const style::color &bg) {
|
||||
const auto &c = bg->c;
|
||||
return c.red() << 24 | c.green() << 16 | c.blue() << 8 | c.alpha();
|
||||
}
|
||||
|
||||
QPixmap circleCorner(int corner, const style::color &bg) {
|
||||
auto ¤tCorner = (bg == st::msgServiceBg)
|
||||
? serviceMessageStyle->corners[corner]
|
||||
: serviceMessageStyle->overridenCorners[{ corner, ColorToUint(bg) }];
|
||||
if (currentCorner.isNull()) {
|
||||
int maskType = corner / MaskMultiplier;
|
||||
int radius = (maskType == NormalMask
|
||||
? historyServiceMsgRadius()
|
||||
: historyServiceMsgInvertedRadius());
|
||||
int size = radius * cIntRetinaFactor();
|
||||
|
||||
int xoffset = 0, yoffset = 0;
|
||||
if (corner & CornerRight) {
|
||||
xoffset = size;
|
||||
}
|
||||
if (corner & CornerBottom) {
|
||||
yoffset = size;
|
||||
}
|
||||
auto part = QRect(xoffset, yoffset, size, size);
|
||||
auto result = style::colorizeImage(
|
||||
serviceMessageStyle->circle[maskType],
|
||||
bg,
|
||||
part);
|
||||
result.setDevicePixelRatio(cRetinaFactor());
|
||||
currentCorner = Ui::PixmapFromImage(std::move(result));
|
||||
}
|
||||
return currentCorner;
|
||||
}
|
||||
|
||||
enum class SideStyle {
|
||||
Rounded,
|
||||
Plain,
|
||||
|
@ -140,96 +48,97 @@ enum class SideStyle {
|
|||
};
|
||||
|
||||
// Returns amount of pixels already painted vertically (so you can skip them in the complex rect shape).
|
||||
int paintBubbleSide(
|
||||
int PaintBubbleSide(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
SideStyle style,
|
||||
CornerVerticalSide side,
|
||||
const style::color &bg) {
|
||||
CornerVerticalSide side) {
|
||||
if (style == SideStyle::Rounded) {
|
||||
const auto corner = (int(NormalMask) * MaskMultiplier) | side;
|
||||
auto left = circleCorner(corner | CornerLeft, bg);
|
||||
int leftWidth = left.width() / cIntRetinaFactor();
|
||||
const auto &corners = st->serviceBgCornersNormal();
|
||||
const auto left = corners.p[(side == CornerTop) ? 0 : 2];
|
||||
const auto leftWidth = left.width() / cIntRetinaFactor();
|
||||
p.drawPixmap(x, y, left);
|
||||
|
||||
auto right = circleCorner(corner | CornerRight, bg);
|
||||
int rightWidth = right.width() / cIntRetinaFactor();
|
||||
const auto right = corners.p[(side == CornerTop) ? 1 : 3];
|
||||
const auto rightWidth = right.width() / cIntRetinaFactor();
|
||||
p.drawPixmap(x + width - rightWidth, y, right);
|
||||
|
||||
int cornerHeight = left.height() / cIntRetinaFactor();
|
||||
const auto cornerHeight = left.height() / cIntRetinaFactor();
|
||||
p.fillRect(
|
||||
x + leftWidth,
|
||||
y,
|
||||
width - leftWidth - rightWidth,
|
||||
cornerHeight,
|
||||
bg);
|
||||
st->msgServiceBg());
|
||||
return cornerHeight;
|
||||
} else if (style == SideStyle::Inverted) {
|
||||
// CornerLeft and CornerRight are inverted for SideStyle::Inverted sprites.
|
||||
const auto corner = (int(InvertedMask) * MaskMultiplier) | side;
|
||||
auto left = circleCorner(corner | CornerRight, bg);
|
||||
int leftWidth = left.width() / cIntRetinaFactor();
|
||||
// CornerLeft and CornerRight are inverted in the top part.
|
||||
const auto &corners = st->serviceBgCornersInverted();
|
||||
const auto left = corners.p[(side == CornerTop) ? 1 : 2];
|
||||
const auto leftWidth = left.width() / cIntRetinaFactor();
|
||||
p.drawPixmap(x - leftWidth, y, left);
|
||||
|
||||
auto right = circleCorner(corner | CornerLeft, bg);
|
||||
const auto right = corners.p[(side == CornerTop) ? 0 : 3];
|
||||
p.drawPixmap(x + width, y, right);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void paintBubblePart(
|
||||
void PaintBubblePart(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
SideStyle topStyle,
|
||||
SideStyle bottomStyle,
|
||||
const style::color &bg,
|
||||
bool forceShrink = false) {
|
||||
if ((topStyle == SideStyle::Inverted)
|
||||
|| (bottomStyle == SideStyle::Inverted)
|
||||
|| forceShrink) {
|
||||
width -= historyServiceMsgInvertedShrink() * 2;
|
||||
x += historyServiceMsgInvertedShrink();
|
||||
width -= Ui::HistoryServiceMsgInvertedShrink() * 2;
|
||||
x += Ui::HistoryServiceMsgInvertedShrink();
|
||||
}
|
||||
|
||||
if (int skip = paintBubbleSide(p, x, y, width, topStyle, CornerTop, bg)) {
|
||||
if (int skip = PaintBubbleSide(p, st, x, y, width, topStyle, CornerTop)) {
|
||||
y += skip;
|
||||
height -= skip;
|
||||
}
|
||||
int bottomSize = 0;
|
||||
if (bottomStyle == SideStyle::Rounded) {
|
||||
bottomSize = historyServiceMsgRadius();
|
||||
bottomSize = Ui::HistoryServiceMsgRadius();
|
||||
} else if (bottomStyle == SideStyle::Inverted) {
|
||||
bottomSize = historyServiceMsgInvertedRadius();
|
||||
bottomSize = Ui::HistoryServiceMsgInvertedRadius();
|
||||
}
|
||||
const auto skip = paintBubbleSide(
|
||||
const auto skip = PaintBubbleSide(
|
||||
p,
|
||||
st,
|
||||
x,
|
||||
y + height - bottomSize,
|
||||
width,
|
||||
bottomStyle,
|
||||
CornerBottom,
|
||||
bg);
|
||||
CornerBottom);
|
||||
if (skip) {
|
||||
height -= skip;
|
||||
}
|
||||
|
||||
p.fillRect(x, y, width, height, bg);
|
||||
p.fillRect(x, y, width, height, st->msgServiceBg());
|
||||
}
|
||||
|
||||
void paintPreparedDate(
|
||||
void PaintPreparedDate(
|
||||
Painter &p,
|
||||
const style::color &bg,
|
||||
const Ui::CornersPixmaps &corners,
|
||||
const style::color &fg,
|
||||
const QString &dateText,
|
||||
int dateTextWidth,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide,
|
||||
const style::color &bg,
|
||||
const style::color &fg) {
|
||||
bool chatWide) {
|
||||
int left = st::msgServiceMargin.left();
|
||||
const auto maxwidth = chatWide
|
||||
? std::min(w, WideChatWidth())
|
||||
|
@ -238,19 +147,27 @@ void paintPreparedDate(
|
|||
|
||||
left += (w - dateTextWidth - st::msgServicePadding.left() - st::msgServicePadding.right()) / 2;
|
||||
int height = st::msgServicePadding.top() + st::msgServiceFont->height + st::msgServicePadding.bottom();
|
||||
ServiceMessagePainter::paintBubble(
|
||||
ServiceMessagePainter::PaintBubble(
|
||||
p,
|
||||
left,
|
||||
y + st::msgServiceMargin.top(),
|
||||
dateTextWidth
|
||||
+ st::msgServicePadding.left()
|
||||
+ st::msgServicePadding.left(),
|
||||
height,
|
||||
bg);
|
||||
bg,
|
||||
corners,
|
||||
QRect(
|
||||
left,
|
||||
y + st::msgServiceMargin.top(),
|
||||
dateTextWidth
|
||||
+ st::msgServicePadding.left()
|
||||
+ st::msgServicePadding.left(),
|
||||
height));
|
||||
|
||||
p.setFont(st::msgServiceFont);
|
||||
p.setPen(fg);
|
||||
p.drawText(left + st::msgServicePadding.left(), y + st::msgServiceMargin.top() + st::msgServicePadding.top() + st::msgServiceFont->ascent, dateText);
|
||||
p.drawText(
|
||||
left + st::msgServicePadding.left(),
|
||||
(y
|
||||
+ st::msgServiceMargin.top()
|
||||
+ st::msgServicePadding.top()
|
||||
+ st::msgServiceFont->ascent),
|
||||
dateText);
|
||||
}
|
||||
|
||||
bool NeedAboutGroup(not_null<History*> history) {
|
||||
|
@ -268,88 +185,112 @@ int WideChatWidth() {
|
|||
return st::msgMaxWidth + 2 * st::msgPhotoSkip + 2 * st::msgMargin.left();
|
||||
}
|
||||
|
||||
void ServiceMessagePainter::paintDate(
|
||||
void ServiceMessagePainter::PaintDate(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
const QDateTime &date,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide,
|
||||
const style::color &bg,
|
||||
const style::color &fg) {
|
||||
const auto dateText = langDayOfMonthFull(date.date());
|
||||
const auto dateTextWidth = st::msgServiceFont->width(dateText);
|
||||
paintPreparedDate(p, dateText, dateTextWidth, y, w, chatWide, bg, fg);
|
||||
bool chatWide) {
|
||||
PaintDate(
|
||||
p,
|
||||
st,
|
||||
langDayOfMonthFull(date.date()),
|
||||
y,
|
||||
w,
|
||||
chatWide);
|
||||
}
|
||||
|
||||
void ServiceMessagePainter::paintDate(
|
||||
void ServiceMessagePainter::PaintDate(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
const QString &dateText,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide,
|
||||
const style::color &bg,
|
||||
const style::color &fg) {
|
||||
paintPreparedDate(
|
||||
bool chatWide) {
|
||||
PaintDate(
|
||||
p,
|
||||
st,
|
||||
dateText,
|
||||
st::msgServiceFont->width(dateText),
|
||||
y,
|
||||
w,
|
||||
chatWide,
|
||||
bg,
|
||||
fg);
|
||||
chatWide);
|
||||
}
|
||||
|
||||
void ServiceMessagePainter::paintDate(
|
||||
void ServiceMessagePainter::PaintDate(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
const QString &dateText,
|
||||
int dateTextWidth,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide,
|
||||
const style::color &bg,
|
||||
const style::color &fg) {
|
||||
paintPreparedDate(p, dateText, dateTextWidth, y, w, chatWide, bg, fg);
|
||||
}
|
||||
|
||||
void ServiceMessagePainter::paintBubble(
|
||||
Painter &p,
|
||||
int x,
|
||||
int y,
|
||||
int w,
|
||||
int h,
|
||||
const style::color &bg) {
|
||||
createCircleMasks();
|
||||
|
||||
paintBubblePart(
|
||||
bool chatWide) {
|
||||
PaintPreparedDate(
|
||||
p,
|
||||
x,
|
||||
st->msgServiceBg(),
|
||||
st->serviceBgCornersNormal(),
|
||||
st->msgServiceFg(),
|
||||
dateText,
|
||||
dateTextWidth,
|
||||
y,
|
||||
w,
|
||||
h,
|
||||
SideStyle::Rounded,
|
||||
SideStyle::Rounded,
|
||||
bg);
|
||||
chatWide);
|
||||
}
|
||||
|
||||
void ServiceMessagePainter::paintComplexBubble(
|
||||
void ServiceMessagePainter::PaintDate(
|
||||
Painter &p,
|
||||
const style::color &bg,
|
||||
const Ui::CornersPixmaps &corners,
|
||||
const style::color &fg,
|
||||
const QString &dateText,
|
||||
int dateTextWidth,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide) {
|
||||
PaintPreparedDate(
|
||||
p,
|
||||
bg,
|
||||
corners,
|
||||
fg,
|
||||
dateText,
|
||||
dateTextWidth,
|
||||
y,
|
||||
w,
|
||||
chatWide);
|
||||
}
|
||||
|
||||
void ServiceMessagePainter::PaintBubble(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
QRect rect) {
|
||||
PaintBubble(p, st->msgServiceBg(), st->serviceBgCornersNormal(), rect);
|
||||
}
|
||||
|
||||
void ServiceMessagePainter::PaintBubble(
|
||||
Painter &p,
|
||||
const style::color &bg,
|
||||
const Ui::CornersPixmaps &corners,
|
||||
QRect rect) {
|
||||
Ui::FillRoundRect(p, rect, bg, corners);
|
||||
}
|
||||
|
||||
void ServiceMessagePainter::PaintComplexBubble(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
int left,
|
||||
int width,
|
||||
const Ui::Text::String &text,
|
||||
const QRect &textRect,
|
||||
const style::color &bg) {
|
||||
createCircleMasks();
|
||||
|
||||
auto lineWidths = countLineWidths(text, textRect);
|
||||
const QRect &textRect) {
|
||||
const auto lineWidths = CountLineWidths(text, textRect);
|
||||
|
||||
int y = st::msgServiceMargin.top(), previousRichWidth = 0;
|
||||
bool previousShrink = false, forceShrink = false;
|
||||
SideStyle topStyle = SideStyle::Rounded, bottomStyle;
|
||||
for (int i = 0, count = lineWidths.size(); i < count; ++i) {
|
||||
auto lineWidth = lineWidths.at(i);
|
||||
const auto lineWidth = lineWidths[i];
|
||||
if (i + 1 < count) {
|
||||
auto nextLineWidth = lineWidths.at(i + 1);
|
||||
const auto nextLineWidth = lineWidths[i + 1];
|
||||
if (nextLineWidth > lineWidth) {
|
||||
bottomStyle = SideStyle::Inverted;
|
||||
} else if (nextLineWidth < lineWidth) {
|
||||
|
@ -374,15 +315,15 @@ void ServiceMessagePainter::paintComplexBubble(
|
|||
richHeight -= st::msgServicePadding.top();
|
||||
}
|
||||
forceShrink = previousShrink && (richWidth == previousRichWidth);
|
||||
paintBubblePart(
|
||||
PaintBubblePart(
|
||||
p,
|
||||
st,
|
||||
left + ((width - richWidth) / 2),
|
||||
y,
|
||||
richWidth,
|
||||
richHeight,
|
||||
topStyle,
|
||||
bottomStyle,
|
||||
bg,
|
||||
forceShrink);
|
||||
y += richHeight;
|
||||
|
||||
|
@ -399,38 +340,46 @@ void ServiceMessagePainter::paintComplexBubble(
|
|||
}
|
||||
}
|
||||
|
||||
QVector<int> ServiceMessagePainter::countLineWidths(const Ui::Text::String &text, const QRect &textRect) {
|
||||
int linesCount = qMax(textRect.height() / st::msgServiceFont->height, 1);
|
||||
QVector<int> lineWidths;
|
||||
lineWidths.reserve(linesCount);
|
||||
text.countLineWidths(textRect.width(), &lineWidths);
|
||||
QVector<int> ServiceMessagePainter::CountLineWidths(
|
||||
const Ui::Text::String &text,
|
||||
const QRect &textRect) {
|
||||
const auto linesCount = qMax(
|
||||
textRect.height() / st::msgServiceFont->height,
|
||||
1);
|
||||
auto result = QVector<int>();
|
||||
result.reserve(linesCount);
|
||||
text.countLineWidths(textRect.width(), &result);
|
||||
|
||||
int minDelta = 2 * (historyServiceMsgRadius() + historyServiceMsgInvertedRadius() - historyServiceMsgInvertedShrink());
|
||||
for (int i = 0, count = lineWidths.size(); i < count; ++i) {
|
||||
int width = qMax(lineWidths.at(i), 0);
|
||||
const auto minDelta = 2 * (Ui::HistoryServiceMsgRadius()
|
||||
+ Ui::HistoryServiceMsgInvertedRadius()
|
||||
- Ui::HistoryServiceMsgInvertedShrink());
|
||||
for (int i = 0, count = result.size(); i != count; ++i) {
|
||||
auto width = qMax(result[i], 0);
|
||||
if (i > 0) {
|
||||
int widthBefore = lineWidths.at(i - 1);
|
||||
const auto widthBefore = result[i - 1];
|
||||
if (width < widthBefore && width + minDelta > widthBefore) {
|
||||
width = widthBefore;
|
||||
}
|
||||
}
|
||||
if (i + 1 < count) {
|
||||
int widthAfter = lineWidths.at(i + 1);
|
||||
const auto widthAfter = result[i + 1];
|
||||
if (width < widthAfter && width + minDelta > widthAfter) {
|
||||
width = widthAfter;
|
||||
}
|
||||
}
|
||||
if (width > lineWidths.at(i)) {
|
||||
lineWidths[i] = width;
|
||||
if (width > result[i]) {
|
||||
result[i] = width;
|
||||
if (i > 0) {
|
||||
int widthBefore = lineWidths.at(i - 1);
|
||||
if (widthBefore != width && widthBefore < width + minDelta && widthBefore + minDelta > width) {
|
||||
int widthBefore = result[i - 1];
|
||||
if (widthBefore != width
|
||||
&& widthBefore < width + minDelta
|
||||
&& widthBefore + minDelta > width) {
|
||||
i -= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return lineWidths;
|
||||
return result;
|
||||
}
|
||||
|
||||
Service::Service(
|
||||
|
@ -527,7 +476,10 @@ void Service::draw(Painter &p, const PaintContext &context) const {
|
|||
return;
|
||||
}
|
||||
|
||||
auto height = this->height() - st::msgServiceMargin.top() - st::msgServiceMargin.bottom();
|
||||
const auto st = context.st;
|
||||
auto height = this->height()
|
||||
- st::msgServiceMargin.top()
|
||||
- st::msgServiceMargin.bottom();
|
||||
auto dateh = 0;
|
||||
auto unreadbarh = 0;
|
||||
auto clip = context.clip;
|
||||
|
@ -540,7 +492,12 @@ void Service::draw(Painter &p, const PaintContext &context) const {
|
|||
if (const auto bar = Get<UnreadBar>()) {
|
||||
unreadbarh = bar->height();
|
||||
if (clip.intersects(QRect(0, 0, width(), unreadbarh))) {
|
||||
bar->paint(p, 0, width(), delegate()->elementIsChatWide());
|
||||
bar->paint(
|
||||
p,
|
||||
context,
|
||||
0,
|
||||
width(),
|
||||
delegate()->elementIsChatWide());
|
||||
}
|
||||
p.translate(0, unreadbarh);
|
||||
clip.translate(0, -unreadbarh);
|
||||
|
@ -554,9 +511,9 @@ void Service::draw(Painter &p, const PaintContext &context) const {
|
|||
return;
|
||||
}
|
||||
|
||||
paintHighlight(p, height);
|
||||
paintHighlight(p, context, height);
|
||||
|
||||
p.setTextPalette(st::serviceTextPalette);
|
||||
p.setTextPalette(st->serviceTextPalette());
|
||||
|
||||
if (auto media = this->media()) {
|
||||
height -= st::msgServiceMargin.top() + media->height();
|
||||
|
@ -568,10 +525,16 @@ void Service::draw(Painter &p, const PaintContext &context) const {
|
|||
|
||||
auto trect = QRect(g.left(), st::msgServiceMargin.top(), g.width(), height).marginsAdded(-st::msgServicePadding);
|
||||
|
||||
ServiceMessagePainter::paintComplexBubble(p, g.left(), g.width(), item->_text, trect);
|
||||
ServiceMessagePainter::PaintComplexBubble(
|
||||
p,
|
||||
context.st,
|
||||
g.left(),
|
||||
g.width(),
|
||||
item->_text,
|
||||
trect);
|
||||
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.setPen(st::msgServiceFg);
|
||||
p.setPen(st->msgServiceFg());
|
||||
p.setFont(st::msgServiceFont);
|
||||
item->_text.draw(p, trect.x(), trect.y(), trect.width(), Qt::AlignCenter, 0, -1, context.selection, false);
|
||||
|
||||
|
@ -694,7 +657,11 @@ void EmptyPainter::fillAboutGroup() {
|
|||
}
|
||||
}
|
||||
|
||||
void EmptyPainter::paint(Painter &p, int width, int height) {
|
||||
void EmptyPainter::paint(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
int width,
|
||||
int height) {
|
||||
if (_phrases.empty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -731,15 +698,14 @@ void EmptyPainter::paint(Painter &p, int width, int height) {
|
|||
const auto bubbleLeft = (width - bubbleWidth) / 2;
|
||||
const auto bubbleTop = (height - bubbleHeight) / 2;
|
||||
|
||||
ServiceMessagePainter::paintBubble(
|
||||
ServiceMessagePainter::PaintBubble(
|
||||
p,
|
||||
bubbleLeft,
|
||||
bubbleTop,
|
||||
bubbleWidth,
|
||||
bubbleHeight);
|
||||
st->msgServiceBg(),
|
||||
st->serviceBgCornersNormal(),
|
||||
QRect(bubbleLeft, bubbleTop, bubbleWidth, bubbleHeight));
|
||||
|
||||
p.setPen(st::msgServiceFg);
|
||||
p.setBrush(st::msgServiceFg);
|
||||
p.setPen(st->msgServiceFg());
|
||||
p.setBrush(st->msgServiceFg());
|
||||
|
||||
const auto left = bubbleLeft + padding.left();
|
||||
auto top = bubbleTop + padding.top();
|
||||
|
@ -762,7 +728,7 @@ void EmptyPainter::paint(Painter &p, int width, int height) {
|
|||
top += textHeight(_text) + st::historyGroupAboutTextSkip;
|
||||
|
||||
for (const auto &text : _phrases) {
|
||||
p.setPen(st::msgServiceFg);
|
||||
p.setPen(st->msgServiceFg());
|
||||
text.drawElided(
|
||||
p,
|
||||
left + st::historyGroupAboutBulletSkip,
|
||||
|
|
|
@ -11,6 +11,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
class HistoryService;
|
||||
|
||||
namespace Ui {
|
||||
class ChatStyle;
|
||||
struct CornersPixmaps;
|
||||
} // namespace Ui
|
||||
|
||||
namespace HistoryView {
|
||||
|
||||
class Service : public Element {
|
||||
|
@ -48,50 +53,61 @@ int WideChatWidth();
|
|||
|
||||
class ServiceMessagePainter {
|
||||
public:
|
||||
static void paintDate(
|
||||
static void PaintDate(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
const QDateTime &date,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide,
|
||||
const style::color &bg = st::msgServiceBg,
|
||||
const style::color &fg = st::msgServiceFg);
|
||||
static void paintDate(
|
||||
bool chatWide);
|
||||
static void PaintDate(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
const QString &dateText,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide,
|
||||
const style::color &bg = st::msgServiceBg,
|
||||
const style::color &fg = st::msgServiceFg);
|
||||
static void paintDate(
|
||||
bool chatWide);
|
||||
static void PaintDate(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
const QString &dateText,
|
||||
int dateTextWidth,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide,
|
||||
const style::color &bg = st::msgServiceBg,
|
||||
const style::color &fg = st::msgServiceFg);
|
||||
|
||||
static void paintBubble(
|
||||
bool chatWide);
|
||||
static void PaintDate(
|
||||
Painter &p,
|
||||
int x,
|
||||
const style::color &bg,
|
||||
const Ui::CornersPixmaps &corners,
|
||||
const style::color &fg,
|
||||
const QString &dateText,
|
||||
int dateTextWidth,
|
||||
int y,
|
||||
int w,
|
||||
int h,
|
||||
const style::color &bg = st::msgServiceBg);
|
||||
bool chatWide);
|
||||
|
||||
static void paintComplexBubble(
|
||||
static void PaintBubble(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
QRect rect);
|
||||
static void PaintBubble(
|
||||
Painter &p,
|
||||
const style::color &bg,
|
||||
const Ui::CornersPixmaps &corners,
|
||||
QRect rect);
|
||||
|
||||
static void PaintComplexBubble(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
int left,
|
||||
int width,
|
||||
const Ui::Text::String &text,
|
||||
const QRect &textRect,
|
||||
const style::color &bg = st::msgServiceBg);
|
||||
const QRect &textRect);
|
||||
|
||||
private:
|
||||
static QVector<int> countLineWidths(const Ui::Text::String &text, const QRect &textRect);
|
||||
static QVector<int> CountLineWidths(
|
||||
const Ui::Text::String &text,
|
||||
const QRect &textRect);
|
||||
|
||||
};
|
||||
|
||||
|
@ -99,7 +115,11 @@ class EmptyPainter {
|
|||
public:
|
||||
explicit EmptyPainter(not_null<History*> history);
|
||||
|
||||
void paint(Painter &p, int width, int height);
|
||||
void paint(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
private:
|
||||
void fillAboutGroup();
|
||||
|
|
|
@ -86,7 +86,10 @@ public:
|
|||
}
|
||||
virtual void refreshParentId(not_null<HistoryItem*> realParent) {
|
||||
}
|
||||
virtual void drawHighlight(Painter &p, int top) const {
|
||||
virtual void drawHighlight(
|
||||
Painter &p,
|
||||
const PaintContext &context,
|
||||
int top) const {
|
||||
}
|
||||
virtual void draw(Painter &p, const PaintContext &context) const = 0;
|
||||
[[nodiscard]] virtual PointState pointState(QPoint point) const;
|
||||
|
|
|
@ -270,7 +270,10 @@ QMargins GroupedMedia::groupedPadding() const {
|
|||
(normal.bottom() - grouped.bottom()) + addToBottom);
|
||||
}
|
||||
|
||||
void GroupedMedia::drawHighlight(Painter &p, int top) const {
|
||||
void GroupedMedia::drawHighlight(
|
||||
Painter &p,
|
||||
const PaintContext &context,
|
||||
int top) const {
|
||||
if (_mode != Mode::Column) {
|
||||
return;
|
||||
}
|
||||
|
@ -278,7 +281,12 @@ void GroupedMedia::drawHighlight(Painter &p, int top) const {
|
|||
for (auto i = 0, count = int(_parts.size()); i != count; ++i) {
|
||||
const auto &part = _parts[i];
|
||||
const auto rect = part.geometry.translated(0, skip);
|
||||
_parent->paintCustomHighlight(p, rect.y(), rect.height(), part.item);
|
||||
_parent->paintCustomHighlight(
|
||||
p,
|
||||
context,
|
||||
rect.y(),
|
||||
rect.height(),
|
||||
part.item);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,10 @@ public:
|
|||
|
||||
void refreshParentId(not_null<HistoryItem*> realParent) override;
|
||||
|
||||
void drawHighlight(Painter &p, int top) const override;
|
||||
void drawHighlight(
|
||||
Painter &p,
|
||||
const PaintContext &context,
|
||||
int top) const override;
|
||||
void draw(Painter &p, const PaintContext &context) const override;
|
||||
PointState pointState(QPoint point) const override;
|
||||
TextState textState(
|
||||
|
|
|
@ -25,6 +25,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "window/window_peer_menu.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/controls/delete_message_context_action.h"
|
||||
#include "ui/chat/chat_style.h"
|
||||
#include "ui/cached_round_corners.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "ui/inactive_press.h"
|
||||
#include "lang/lang_keys.h"
|
||||
|
@ -94,6 +96,20 @@ struct ListWidget::Context {
|
|||
DragSelectAction dragSelectAction;
|
||||
};
|
||||
|
||||
struct ListWidget::DateBadge {
|
||||
DateBadge(Type type, Fn<void()> checkCallback, Fn<void()> hideCallback);
|
||||
|
||||
SingleQueuedInvokation check;
|
||||
base::Timer hideTimer;
|
||||
Ui::Animations::Simple opacity;
|
||||
Ui::CornersPixmaps corners;
|
||||
bool goodType = false;
|
||||
bool shown = false;
|
||||
QString text;
|
||||
int textWidth = 0;
|
||||
QRect rect;
|
||||
};
|
||||
|
||||
class ListWidget::Section {
|
||||
public:
|
||||
Section(Type type)
|
||||
|
@ -228,6 +244,17 @@ ListWidget::CachedItem &ListWidget::CachedItem::operator=(
|
|||
|
||||
ListWidget::CachedItem::~CachedItem() = default;
|
||||
|
||||
ListWidget::DateBadge::DateBadge(
|
||||
Type type,
|
||||
Fn<void()> checkCallback,
|
||||
Fn<void()> hideCallback)
|
||||
: check(std::move(checkCallback))
|
||||
, hideTimer(std::move(hideCallback))
|
||||
, goodType(type == Type::Photo
|
||||
|| type == Type::Video
|
||||
|| type == Type::GIF) {
|
||||
}
|
||||
|
||||
bool ListWidget::Section::addItem(not_null<BaseLayout*> item) {
|
||||
if (_items.empty() || belongsHere(item)) {
|
||||
if (_items.empty()) setHeader(item);
|
||||
|
@ -664,13 +691,10 @@ ListWidget::ListWidget(
|
|||
, _migrated(_controller->migrated())
|
||||
, _type(_controller->section().mediaType())
|
||||
, _slice(sliceKey(_universalAroundId))
|
||||
, _dateBadge(DateBadge{
|
||||
.check = SingleQueuedInvokation([=] { scrollDateCheck(); }),
|
||||
.hideTimer = base::Timer([=] { scrollDateHide(); }),
|
||||
.goodType = (_type == Type::Photo
|
||||
|| _type == Type::Video
|
||||
|| _type == Type::GIF),
|
||||
}) {
|
||||
, _dateBadge(std::make_unique<DateBadge>(
|
||||
_type,
|
||||
[=] { scrollDateCheck(); },
|
||||
[=] { scrollDateHide(); })) {
|
||||
setMouseTracking(true);
|
||||
start();
|
||||
}
|
||||
|
@ -1204,16 +1228,16 @@ void ListWidget::visibleTopBottomUpdated(
|
|||
checkMoveToOtherViewer();
|
||||
clearHeavyItems();
|
||||
|
||||
if (_dateBadge.goodType) {
|
||||
if (_dateBadge->goodType) {
|
||||
updateDateBadgeFor(_visibleTop);
|
||||
if (!_visibleTop) {
|
||||
if (_dateBadge.shown) {
|
||||
if (_dateBadge->shown) {
|
||||
scrollDateHide();
|
||||
} else {
|
||||
update(_dateBadge.rect);
|
||||
update(_dateBadge->rect);
|
||||
}
|
||||
} else {
|
||||
_dateBadge.check.call();
|
||||
_dateBadge->check.call();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1228,29 +1252,30 @@ void ListWidget::updateDateBadgeFor(int top) {
|
|||
+ st::msgServiceFont->height
|
||||
+ st::msgServicePadding.bottom();
|
||||
|
||||
_dateBadge.text = ItemDateText(layout->getItem(), false);
|
||||
_dateBadge.rect = QRect(0, top, width(), rectHeight);
|
||||
_dateBadge->text = ItemDateText(layout->getItem(), false);
|
||||
_dateBadge->textWidth = st::msgServiceFont->width(_dateBadge->text);
|
||||
_dateBadge->rect = QRect(0, top, width(), rectHeight);
|
||||
}
|
||||
|
||||
void ListWidget::scrollDateCheck() {
|
||||
if (!_dateBadge.shown) {
|
||||
if (!_dateBadge->shown) {
|
||||
toggleScrollDateShown();
|
||||
}
|
||||
_dateBadge.hideTimer.callOnce(st::infoScrollDateHideTimeout);
|
||||
_dateBadge->hideTimer.callOnce(st::infoScrollDateHideTimeout);
|
||||
}
|
||||
|
||||
void ListWidget::scrollDateHide() {
|
||||
if (_dateBadge.shown) {
|
||||
if (_dateBadge->shown) {
|
||||
toggleScrollDateShown();
|
||||
}
|
||||
}
|
||||
|
||||
void ListWidget::toggleScrollDateShown() {
|
||||
_dateBadge.shown = !_dateBadge.shown;
|
||||
_dateBadge.opacity.start(
|
||||
[=] { update(_dateBadge.rect); },
|
||||
_dateBadge.shown ? 0. : 1.,
|
||||
_dateBadge.shown ? 1. : 0.,
|
||||
_dateBadge->shown = !_dateBadge->shown;
|
||||
_dateBadge->opacity.start(
|
||||
[=] { update(_dateBadge->rect); },
|
||||
_dateBadge->shown ? 0. : 1.,
|
||||
_dateBadge->shown ? 1. : 0.,
|
||||
st::infoDateFadeDuration);
|
||||
}
|
||||
|
||||
|
@ -1403,19 +1428,27 @@ void ListWidget::paintEvent(QPaintEvent *e) {
|
|||
fromSectionIt->paintFloatingHeader(p, _visibleTop, outerWidth);
|
||||
}
|
||||
|
||||
if (_dateBadge.goodType && clip.intersects(_dateBadge.rect)) {
|
||||
if (_dateBadge->goodType && clip.intersects(_dateBadge->rect)) {
|
||||
const auto scrollDateOpacity =
|
||||
_dateBadge.opacity.value(_dateBadge.shown ? 1. : 0.);
|
||||
_dateBadge->opacity.value(_dateBadge->shown ? 1. : 0.);
|
||||
if (scrollDateOpacity > 0.) {
|
||||
p.setOpacity(scrollDateOpacity);
|
||||
HistoryView::ServiceMessagePainter::paintDate(
|
||||
if (_dateBadge->corners.p[0].isNull()) {
|
||||
_dateBadge->corners = Ui::PrepareCornerPixmaps(
|
||||
Ui::HistoryServiceMsgRadius(),
|
||||
st::roundedBg,
|
||||
nullptr);
|
||||
}
|
||||
HistoryView::ServiceMessagePainter::PaintDate(
|
||||
p,
|
||||
_dateBadge.text,
|
||||
st::roundedBg,
|
||||
_dateBadge->corners,
|
||||
st::roundedFg,
|
||||
_dateBadge->text,
|
||||
_dateBadge->textWidth,
|
||||
_visibleTop,
|
||||
outerWidth,
|
||||
false,
|
||||
st::roundedBg,
|
||||
st::roundedFg);
|
||||
false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ public:
|
|||
|
||||
private:
|
||||
struct Context;
|
||||
struct DateBadge;
|
||||
class Section;
|
||||
using CursorState = HistoryView::CursorState;
|
||||
using TextState = HistoryView::TextState;
|
||||
|
@ -331,15 +332,7 @@ private:
|
|||
DragSelectAction _dragSelectAction = DragSelectAction::None;
|
||||
bool _wasSelectedText = false; // was some text selected in current drag action
|
||||
|
||||
struct DateBadge {
|
||||
SingleQueuedInvokation check;
|
||||
base::Timer hideTimer;
|
||||
Ui::Animations::Simple opacity;
|
||||
bool goodType = false;
|
||||
bool shown = false;
|
||||
QString text;
|
||||
QRect rect;
|
||||
} _dateBadge;
|
||||
const std::unique_ptr<DateBadge> _dateBadge;
|
||||
|
||||
base::unique_qptr<Ui::PopupMenu> _contextMenu;
|
||||
rpl::event_stream<> _checkForHide;
|
||||
|
|
|
@ -95,9 +95,6 @@ void CreatePaletteCorners() {
|
|||
PrepareCorners(Doc4Corners, st::roundRadiusSmall, st::msgFile4Bg);
|
||||
|
||||
PrepareCorners(MessageInCorners, st::historyMessageRadius, st::msgInBg, &st::msgInShadow);
|
||||
PrepareCorners(MessageInSelectedCorners, st::historyMessageRadius, st::msgInBgSelected, &st::msgInShadowSelected);
|
||||
PrepareCorners(MessageOutCorners, st::historyMessageRadius, st::msgOutBg, &st::msgOutShadow);
|
||||
PrepareCorners(MessageOutSelectedCorners, st::historyMessageRadius, st::msgOutBgSelected, &st::msgOutShadowSelected);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -43,9 +43,6 @@ enum CachedRoundCorners : int {
|
|||
InSelectedShadowCorners,
|
||||
|
||||
MessageInCorners, // with shadow
|
||||
MessageInSelectedCorners,
|
||||
MessageOutCorners,
|
||||
MessageOutSelectedCorners,
|
||||
|
||||
RoundCornersCount
|
||||
};
|
||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/chat/chat_style.h"
|
||||
|
||||
#include "ui/chat/chat_theme.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
|
||||
|
@ -30,10 +31,36 @@ not_null<const MessageStyle*> ChatPaintContext::messageStyle() const {
|
|||
return &st->messageStyle(outbg, selected());
|
||||
}
|
||||
|
||||
int HistoryServiceMsgRadius() {
|
||||
static const auto result = [] {
|
||||
const auto minMessageHeight = st::msgServicePadding.top()
|
||||
+ st::msgServiceFont->height
|
||||
+ st::msgServicePadding.bottom();
|
||||
return minMessageHeight / 2;
|
||||
}();
|
||||
return result;
|
||||
}
|
||||
|
||||
int HistoryServiceMsgInvertedRadius() {
|
||||
static const auto result = [] {
|
||||
const auto minRowHeight = st::msgServiceFont->height;
|
||||
return minRowHeight - HistoryServiceMsgRadius();
|
||||
}();
|
||||
return result;
|
||||
}
|
||||
|
||||
int HistoryServiceMsgInvertedShrink() {
|
||||
static const auto result = [] {
|
||||
return (HistoryServiceMsgInvertedRadius() * 2) / 3;
|
||||
}();
|
||||
return result;
|
||||
}
|
||||
|
||||
ChatStyle::ChatStyle() {
|
||||
finalize();
|
||||
make(_historyPsaForwardPalette, st::historyPsaForwardPalette);
|
||||
make(_imgReplyTextPalette, st::imgReplyTextPalette);
|
||||
make(_serviceTextPalette, st::serviceTextPalette);
|
||||
make(_historyRepliesInvertedIcon, st::historyRepliesInvertedIcon);
|
||||
make(_historyViewsInvertedIcon, st::historyViewsInvertedIcon);
|
||||
make(_historyViewsSendingIcon, st::historyViewsSendingIcon);
|
||||
|
@ -212,9 +239,41 @@ void ChatStyle::assignPalette(not_null<const style::palette*> palette) {
|
|||
for (auto &style : _messageStyles) {
|
||||
style.corners = {};
|
||||
}
|
||||
_serviceBgCornersNormal = {};
|
||||
_serviceBgCornersInverted = {};
|
||||
_msgServiceBgCorners = {};
|
||||
_msgServiceBgSelectedCorners = {};
|
||||
_msgBotKbOverBgAddCorners = {};
|
||||
_msgDateImgBgCorners = {};
|
||||
_msgDateImgBgSelectedCorners = {};
|
||||
}
|
||||
|
||||
const CornersPixmaps &ChatStyle::serviceBgCornersNormal() const {
|
||||
EnsureCorners(
|
||||
_serviceBgCornersNormal,
|
||||
HistoryServiceMsgRadius(),
|
||||
msgServiceBg());
|
||||
return _serviceBgCornersNormal;
|
||||
}
|
||||
|
||||
const CornersPixmaps &ChatStyle::serviceBgCornersInverted() const {
|
||||
if (_serviceBgCornersInverted.p[0].isNull()) {
|
||||
const auto radius = HistoryServiceMsgInvertedRadius();
|
||||
const auto size = radius * style::DevicePixelRatio();
|
||||
auto circle = style::colorizeImage(
|
||||
style::createInvertedCircleMask(radius * 2),
|
||||
msgServiceBg());
|
||||
circle.setDevicePixelRatio(style::DevicePixelRatio());
|
||||
const auto fill = [&](int index, int xoffset, int yoffset) {
|
||||
_serviceBgCornersInverted.p[index] = PixmapFromImage(
|
||||
circle.copy(QRect(xoffset, yoffset, size, size)));
|
||||
};
|
||||
fill(0, 0, 0);
|
||||
fill(1, size, 0);
|
||||
fill(2, size, size);
|
||||
fill(3, 0, size);
|
||||
}
|
||||
return _serviceBgCornersInverted;
|
||||
}
|
||||
|
||||
const MessageStyle &ChatStyle::messageStyle(bool outbg, bool selected) const {
|
||||
|
|
|
@ -83,12 +83,19 @@ struct ChatPaintContext {
|
|||
|
||||
};
|
||||
|
||||
[[nodiscard]] int HistoryServiceMsgRadius();
|
||||
[[nodiscard]] int HistoryServiceMsgInvertedRadius();
|
||||
[[nodiscard]] int HistoryServiceMsgInvertedShrink();
|
||||
|
||||
class ChatStyle final : public style::palette {
|
||||
public:
|
||||
ChatStyle();
|
||||
|
||||
void apply(not_null<ChatTheme*> theme);
|
||||
|
||||
[[nodiscard]] const CornersPixmaps &serviceBgCornersNormal() const;
|
||||
[[nodiscard]] const CornersPixmaps &serviceBgCornersInverted() const;
|
||||
|
||||
[[nodiscard]] const MessageStyle &messageStyle(
|
||||
bool outbg,
|
||||
bool selected) const;
|
||||
|
@ -105,6 +112,9 @@ public:
|
|||
[[nodiscard]] const style::TextPalette &imgReplyTextPalette() const {
|
||||
return _imgReplyTextPalette;
|
||||
}
|
||||
[[nodiscard]] const style::TextPalette &serviceTextPalette() const {
|
||||
return _serviceTextPalette;
|
||||
}
|
||||
[[nodiscard]] const style::icon &historyRepliesInvertedIcon() const {
|
||||
return _historyRepliesInvertedIcon;
|
||||
}
|
||||
|
@ -174,6 +184,9 @@ private:
|
|||
const Type &originalOut,
|
||||
const Type &originalOutSelected);
|
||||
|
||||
mutable CornersPixmaps _serviceBgCornersNormal;
|
||||
mutable CornersPixmaps _serviceBgCornersInverted;
|
||||
|
||||
mutable std::array<MessageStyle, 4> _messageStyles;
|
||||
|
||||
mutable CornersPixmaps _msgServiceBgCorners;
|
||||
|
@ -184,6 +197,7 @@ private:
|
|||
|
||||
style::TextPalette _historyPsaForwardPalette;
|
||||
style::TextPalette _imgReplyTextPalette;
|
||||
style::TextPalette _serviceTextPalette;
|
||||
style::icon _historyRepliesInvertedIcon = { Qt::Uninitialized };
|
||||
style::icon _historyViewsInvertedIcon = { Qt::Uninitialized };
|
||||
style::icon _historyViewsSendingIcon = { Qt::Uninitialized };
|
||||
|
|
|
@ -416,6 +416,9 @@ public:
|
|||
};
|
||||
[[nodiscard]] Ui::ChatPaintContext preparePaintContext(
|
||||
PaintContextArgs &&args);
|
||||
[[nodiscard]] not_null<const Ui::ChatStyle*> chatStyle() const {
|
||||
return _chatStyle.get();
|
||||
}
|
||||
|
||||
rpl::lifetime &lifetime() {
|
||||
return _lifetime;
|
||||
|
@ -486,7 +489,7 @@ private:
|
|||
std::shared_ptr<Ui::ChatTheme> _defaultChatTheme;
|
||||
base::flat_map<uint64, CachedTheme> _customChatThemes;
|
||||
rpl::event_stream<std::shared_ptr<Ui::ChatTheme>> _cachedThemesStream;
|
||||
std::unique_ptr<Ui::ChatStyle> _chatStyle;
|
||||
const std::unique_ptr<Ui::ChatStyle> _chatStyle;
|
||||
std::weak_ptr<Ui::ChatTheme> _chatStyleTheme;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
|
Loading…
Add table
Reference in a new issue