mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-04-08 10:33:06 +00:00
Use QImage bubbles background for some Media parts.
This commit is contained in:
parent
f4fdadd3b0
commit
784d57a2bc
@ -619,8 +619,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
|||||||
.visibleAreaTop = _visibleAreaTop,
|
.visibleAreaTop = _visibleAreaTop,
|
||||||
.visibleAreaTopGlobal = visibleAreaTopGlobal,
|
.visibleAreaTopGlobal = visibleAreaTopGlobal,
|
||||||
.clip = clip,
|
.clip = clip,
|
||||||
.initialShift = top,
|
}).translated(0, -top);
|
||||||
});
|
|
||||||
p.translate(0, top);
|
p.translate(0, top);
|
||||||
if (context.clip.y() < view->height()) while (top < drawToY) {
|
if (context.clip.y() < view->height()) while (top < drawToY) {
|
||||||
context.selection = itemRenderSelection(
|
context.selection = itemRenderSelection(
|
||||||
@ -639,8 +638,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
|||||||
|
|
||||||
const auto height = view->height();
|
const auto height = view->height();
|
||||||
top += height;
|
top += height;
|
||||||
context.viewport.translate(0, -height);
|
context.translate(0, -height);
|
||||||
context.clip.translate(0, -height);
|
|
||||||
p.translate(0, height);
|
p.translate(0, height);
|
||||||
|
|
||||||
++iItem;
|
++iItem;
|
||||||
@ -672,8 +670,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
|||||||
.clip = clip.intersected(
|
.clip = clip.intersected(
|
||||||
QRect(0, hdrawtop, width(), clip.top() + clip.height())
|
QRect(0, hdrawtop, width(), clip.top() + clip.height())
|
||||||
),
|
),
|
||||||
.initialShift = top,
|
}).translated(0, -top);
|
||||||
});
|
|
||||||
p.translate(0, top);
|
p.translate(0, top);
|
||||||
while (top < drawToY) {
|
while (top < drawToY) {
|
||||||
const auto height = view->height();
|
const auto height = view->height();
|
||||||
@ -704,8 +701,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
top += height;
|
top += height;
|
||||||
context.viewport.translate(0, -height);
|
context.translate(0, -height);
|
||||||
context.clip.translate(0, -height);
|
|
||||||
p.translate(0, height);
|
p.translate(0, height);
|
||||||
|
|
||||||
++iItem;
|
++iItem;
|
||||||
|
@ -198,6 +198,22 @@ struct PaintContext {
|
|||||||
QRect clip;
|
QRect clip;
|
||||||
TextSelection selection;
|
TextSelection selection;
|
||||||
crl::time now = 0;
|
crl::time now = 0;
|
||||||
|
|
||||||
|
void translate(int x, int y) {
|
||||||
|
viewport.translate(x, y);
|
||||||
|
clip.translate(x, y);
|
||||||
|
}
|
||||||
|
void translate(QPoint point) {
|
||||||
|
translate(point.x(), point.y());
|
||||||
|
}
|
||||||
|
[[nodiscard]] PaintContext translated(int x, int y) const {
|
||||||
|
auto result = *this;
|
||||||
|
result.translate(x, y);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
[[nodiscard]] PaintContext translated(QPoint point) const {
|
||||||
|
return translated(point.x(), point.y());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Element
|
class Element
|
||||||
|
@ -594,25 +594,22 @@ void Message::draw(Painter &p, const PaintContext &context) const {
|
|||||||
auto mediaTop = (trect.y() + trect.height() - mediaHeight);
|
auto mediaTop = (trect.y() + trect.height() - mediaHeight);
|
||||||
|
|
||||||
p.translate(mediaLeft, mediaTop);
|
p.translate(mediaLeft, mediaTop);
|
||||||
media->draw(
|
auto mediaContext = context.translated(-mediaLeft, -mediaTop);
|
||||||
p,
|
mediaContext.selection = skipTextSelection(context.selection);
|
||||||
context.clip.translated(-mediaLeft, -mediaTop),
|
media->draw(p, mediaContext);
|
||||||
skipTextSelection(context.selection), context.now);
|
|
||||||
p.translate(-mediaLeft, -mediaTop);
|
p.translate(-mediaLeft, -mediaTop);
|
||||||
}
|
}
|
||||||
if (entry) {
|
if (entry) {
|
||||||
auto entryLeft = inner.left();
|
auto entryLeft = inner.left();
|
||||||
auto entryTop = trect.y() + trect.height();
|
auto entryTop = trect.y() + trect.height();
|
||||||
p.translate(entryLeft, entryTop);
|
p.translate(entryLeft, entryTop);
|
||||||
auto entrySelection = skipTextSelection(context.selection);
|
auto entryContext = context.translated(-entryLeft, -entryTop);
|
||||||
|
entryContext.selection = skipTextSelection(context.selection);
|
||||||
if (mediaDisplayed) {
|
if (mediaDisplayed) {
|
||||||
entrySelection = media->skipSelection(entrySelection);
|
entryContext.selection = media->skipSelection(
|
||||||
|
entryContext.selection);
|
||||||
}
|
}
|
||||||
entry->draw(
|
entry->draw(p, entryContext);
|
||||||
p,
|
|
||||||
context.clip.translated(-entryLeft, -entryTop),
|
|
||||||
entrySelection,
|
|
||||||
context.now);
|
|
||||||
p.translate(-entryLeft, -entryTop);
|
p.translate(-entryLeft, -entryTop);
|
||||||
}
|
}
|
||||||
const auto needDrawInfo = entry
|
const auto needDrawInfo = entry
|
||||||
@ -652,11 +649,9 @@ void Message::draw(Painter &p, const PaintContext &context) const {
|
|||||||
}
|
}
|
||||||
} else if (media && media->isDisplayed()) {
|
} else if (media && media->isDisplayed()) {
|
||||||
p.translate(g.topLeft());
|
p.translate(g.topLeft());
|
||||||
media->draw(
|
auto mediaContext = context.translated(-g.topLeft());
|
||||||
p,
|
mediaContext.selection = skipTextSelection(context.selection);
|
||||||
context.clip.translated(-g.topLeft()),
|
media->draw(p, mediaContext);
|
||||||
skipTextSelection(context.selection),
|
|
||||||
context.now);
|
|
||||||
p.translate(-g.topLeft());
|
p.translate(-g.topLeft());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -561,7 +561,9 @@ void Service::draw(Painter &p, const PaintContext &context) const {
|
|||||||
height -= st::msgServiceMargin.top() + media->height();
|
height -= st::msgServiceMargin.top() + media->height();
|
||||||
auto left = st::msgServiceMargin.left() + (g.width() - media->maxWidth()) / 2, top = st::msgServiceMargin.top() + height + st::msgServiceMargin.top();
|
auto left = st::msgServiceMargin.left() + (g.width() - media->maxWidth()) / 2, top = st::msgServiceMargin.top() + height + st::msgServiceMargin.top();
|
||||||
p.translate(left, top);
|
p.translate(left, top);
|
||||||
media->draw(p, clip.translated(-left, -top), TextSelection(), context.now);
|
auto mediaContext = context.translated(-left, -top);
|
||||||
|
mediaContext.selection = TextSelection();
|
||||||
|
media->draw(p, mediaContext);
|
||||||
p.translate(-left, -top);
|
p.translate(-left, -top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,12 +72,12 @@ QSize Call::countOptimalSize() {
|
|||||||
return { maxWidth, minHeight };
|
return { maxWidth, minHeight };
|
||||||
}
|
}
|
||||||
|
|
||||||
void Call::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
|
void Call::draw(Painter &p, const PaintContext &context) const {
|
||||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||||
auto paintw = width();
|
auto paintw = width();
|
||||||
|
|
||||||
auto outbg = _parent->hasOutLayout();
|
auto outbg = _parent->hasOutLayout();
|
||||||
auto selected = (selection == FullSelection);
|
auto selected = (context.selection == FullSelection);
|
||||||
|
|
||||||
accumulate_min(paintw, maxWidth());
|
accumulate_min(paintw, maxWidth());
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ public:
|
|||||||
not_null<Element*> parent,
|
not_null<Element*> parent,
|
||||||
not_null<Data::Call*> call);
|
not_null<Data::Call*> call);
|
||||||
|
|
||||||
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
|
void draw(Painter &p, const PaintContext &context) const override;
|
||||||
TextState textState(QPoint point, StateRequest request) const override;
|
TextState textState(QPoint point, StateRequest request) const override;
|
||||||
|
|
||||||
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
|
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
|
||||||
|
@ -153,12 +153,12 @@ QSize Contact::countOptimalSize() {
|
|||||||
return { maxWidth, minHeight };
|
return { maxWidth, minHeight };
|
||||||
}
|
}
|
||||||
|
|
||||||
void Contact::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
|
void Contact::draw(Painter &p, const PaintContext &context) const {
|
||||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||||
auto paintw = width();
|
auto paintw = width();
|
||||||
|
|
||||||
auto outbg = _parent->hasOutLayout();
|
auto outbg = _parent->hasOutLayout();
|
||||||
bool selected = (selection == FullSelection);
|
bool selected = (context.selection == FullSelection);
|
||||||
|
|
||||||
accumulate_min(paintw, maxWidth());
|
accumulate_min(paintw, maxWidth());
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ public:
|
|||||||
const QString &phone);
|
const QString &phone);
|
||||||
~Contact();
|
~Contact();
|
||||||
|
|
||||||
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
|
void draw(Painter &p, const PaintContext &context) const override;
|
||||||
TextState textState(QPoint point, StateRequest request) const override;
|
TextState textState(QPoint point, StateRequest request) const override;
|
||||||
|
|
||||||
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
|
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
|
||||||
|
@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "ui/image/image.h"
|
#include "ui/image/image.h"
|
||||||
#include "ui/text/format_values.h"
|
#include "ui/text/format_values.h"
|
||||||
#include "ui/text/format_song_document_name.h"
|
#include "ui/text/format_song_document_name.h"
|
||||||
|
#include "ui/chat/message_bubble.h"
|
||||||
#include "ui/cached_round_corners.h"
|
#include "ui/cached_round_corners.h"
|
||||||
#include "ui/ui_utility.h"
|
#include "ui/ui_utility.h"
|
||||||
#include "layout/layout_selection.h" // FullSelection
|
#include "layout/layout_selection.h" // FullSelection
|
||||||
@ -325,19 +326,14 @@ QSize Document::countCurrentSize(int newWidth) {
|
|||||||
return { newWidth, newHeight };
|
return { newWidth, newHeight };
|
||||||
}
|
}
|
||||||
|
|
||||||
void Document::draw(
|
void Document::draw(Painter &p, const PaintContext &context) const {
|
||||||
Painter &p,
|
draw(p, width(), context, LayoutMode::Full);
|
||||||
const QRect &r,
|
|
||||||
TextSelection selection,
|
|
||||||
crl::time ms) const {
|
|
||||||
draw(p, width(), selection, ms, LayoutMode::Full);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Document::draw(
|
void Document::draw(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
int width,
|
int width,
|
||||||
TextSelection selection,
|
const PaintContext &context,
|
||||||
crl::time ms,
|
|
||||||
LayoutMode mode) const {
|
LayoutMode mode) const {
|
||||||
if (width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
if (width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||||
|
|
||||||
@ -349,7 +345,7 @@ void Document::draw(
|
|||||||
_dataMedia->automaticLoad(_realParent->fullId(), _realParent);
|
_dataMedia->automaticLoad(_realParent->fullId(), _realParent);
|
||||||
}
|
}
|
||||||
bool loaded = dataLoaded(), displayLoading = _data->displayLoading();
|
bool loaded = dataLoaded(), displayLoading = _data->displayLoading();
|
||||||
bool selected = (selection == FullSelection);
|
bool selected = (context.selection == FullSelection);
|
||||||
|
|
||||||
int captionw = width - st::msgPadding.left() - st::msgPadding.right();
|
int captionw = width - st::msgPadding.left() - st::msgPadding.right();
|
||||||
auto outbg = _parent->hasOutLayout();
|
auto outbg = _parent->hasOutLayout();
|
||||||
@ -507,19 +503,33 @@ void Document::draw(
|
|||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}();
|
}();
|
||||||
if (previous && radialOpacity > 0. && radialOpacity < 1.) {
|
|
||||||
PaintInterpolatedIcon(p, *icon, *previous, radialOpacity, inner);
|
const auto paintContent = [&](Painter &q) {
|
||||||
|
if (previous && radialOpacity > 0. && radialOpacity < 1.) {
|
||||||
|
PaintInterpolatedIcon(q, *icon, *previous, radialOpacity, inner);
|
||||||
|
} else {
|
||||||
|
icon->paintInCenter(q, inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (radial && !cornerDownload) {
|
||||||
|
QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
|
||||||
|
auto fg = outbg ? (selected ? st::historyFileOutRadialFgSelected : st::historyFileOutRadialFg) : (selected ? st::historyFileInRadialFgSelected : st::historyFileInRadialFg);
|
||||||
|
_animation->radial.draw(q, rinner, st::msgFileRadialLine, fg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (_data->isSongWithCover() || !usesBubblePattern(context)) {
|
||||||
|
paintContent(p);
|
||||||
} else {
|
} else {
|
||||||
icon->paintInCenter(p, inner);
|
Ui::PaintPatternBubblePart(
|
||||||
|
p,
|
||||||
|
context.viewport,
|
||||||
|
context.bubblesPattern->pixmap,
|
||||||
|
inner,
|
||||||
|
paintContent,
|
||||||
|
_iconCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (radial && !cornerDownload) {
|
drawCornerDownload(p, context, mode);
|
||||||
QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
|
|
||||||
auto fg = outbg ? (selected ? st::historyFileOutRadialFgSelected : st::historyFileOutRadialFg) : (selected ? st::historyFileInRadialFgSelected : st::historyFileInRadialFg);
|
|
||||||
_animation->radial.draw(p, rinner, st::msgFileRadialLine, fg);
|
|
||||||
}
|
|
||||||
|
|
||||||
drawCornerDownload(p, selected, mode);
|
|
||||||
}
|
}
|
||||||
auto namewidth = width - nameleft - nameright;
|
auto namewidth = width - nameleft - nameright;
|
||||||
auto statuswidth = namewidth;
|
auto statuswidth = namewidth;
|
||||||
@ -595,7 +605,7 @@ void Document::draw(
|
|||||||
|
|
||||||
if (auto captioned = Get<HistoryDocumentCaptioned>()) {
|
if (auto captioned = Get<HistoryDocumentCaptioned>()) {
|
||||||
p.setPen(outbg ? (selected ? st::historyTextOutFgSelected : st::historyTextOutFg) : (selected ? st::historyTextInFgSelected : st::historyTextInFg));
|
p.setPen(outbg ? (selected ? st::historyTextOutFgSelected : st::historyTextOutFg) : (selected ? st::historyTextInFgSelected : st::historyTextInFg));
|
||||||
captioned->_caption.draw(p, st::msgPadding.left(), bottom, captionw, style::al_left, 0, -1, selection);
|
captioned->_caption.draw(p, st::msgPadding.left(), bottom, captionw, style::al_left, 0, -1, context.selection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,7 +635,10 @@ bool Document::downloadInCorner() const {
|
|||||||
&& IsServerMsgId(_realParent->id);
|
&& IsServerMsgId(_realParent->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Document::drawCornerDownload(Painter &p, bool selected, LayoutMode mode) const {
|
void Document::drawCornerDownload(
|
||||||
|
Painter &p,
|
||||||
|
const PaintContext &context,
|
||||||
|
LayoutMode mode) const {
|
||||||
if (dataLoaded()
|
if (dataLoaded()
|
||||||
|| _data->loadedInMediaCache()
|
|| _data->loadedInMediaCache()
|
||||||
|| !downloadInCorner()) {
|
|| !downloadInCorner()) {
|
||||||
@ -633,6 +646,7 @@ void Document::drawCornerDownload(Painter &p, bool selected, LayoutMode mode) co
|
|||||||
}
|
}
|
||||||
auto outbg = _parent->hasOutLayout();
|
auto outbg = _parent->hasOutLayout();
|
||||||
auto topMinus = isBubbleTop() ? 0 : st::msgFileTopMinus;
|
auto topMinus = isBubbleTop() ? 0 : st::msgFileTopMinus;
|
||||||
|
const auto selected = (context.selection == FullSelection);
|
||||||
const auto thumbed = false;
|
const auto thumbed = false;
|
||||||
const auto &st = (mode == LayoutMode::Full)
|
const auto &st = (mode == LayoutMode::Full)
|
||||||
? (thumbed ? st::msgFileThumbLayout : st::msgFileLayout)
|
? (thumbed ? st::msgFileThumbLayout : st::msgFileLayout)
|
||||||
@ -640,11 +654,16 @@ void Document::drawCornerDownload(Painter &p, bool selected, LayoutMode mode) co
|
|||||||
const auto shift = st::historyAudioDownloadShift;
|
const auto shift = st::historyAudioDownloadShift;
|
||||||
const auto size = st::historyAudioDownloadSize;
|
const auto size = st::historyAudioDownloadSize;
|
||||||
const auto inner = style::rtlrect(st.padding.left() + shift, st.padding.top() - topMinus + shift, size, size, width());
|
const auto inner = style::rtlrect(st.padding.left() + shift, st.padding.top() - topMinus + shift, size, size, width());
|
||||||
auto pen = (selected
|
const auto bubblePattern = usesBubblePattern(context);
|
||||||
? (outbg ? st::msgOutBgSelected : st::msgInBgSelected)
|
if (bubblePattern) {
|
||||||
: (outbg ? st::msgOutBg : st::msgInBg))->p;
|
p.setPen(Qt::NoPen);
|
||||||
pen.setWidth(st::lineWidth);
|
} else {
|
||||||
p.setPen(pen);
|
auto pen = (selected
|
||||||
|
? (outbg ? st::msgOutBgSelected : st::msgInBgSelected)
|
||||||
|
: (outbg ? st::msgOutBg : st::msgInBg))->p;
|
||||||
|
pen.setWidth(st::lineWidth);
|
||||||
|
p.setPen(pen);
|
||||||
|
}
|
||||||
if (selected) {
|
if (selected) {
|
||||||
p.setBrush(outbg ? st::msgFileOutBgSelected : st::msgFileInBgSelected);
|
p.setBrush(outbg ? st::msgFileOutBgSelected : st::msgFileInBgSelected);
|
||||||
} else {
|
} else {
|
||||||
@ -660,11 +679,34 @@ void Document::drawCornerDownload(Painter &p, bool selected, LayoutMode mode) co
|
|||||||
}
|
}
|
||||||
return &(outbg ? (selected ? st::historyAudioOutDownloadSelected : st::historyAudioOutDownload) : (selected ? st::historyAudioInDownloadSelected : st::historyAudioInDownload));
|
return &(outbg ? (selected ? st::historyAudioOutDownloadSelected : st::historyAudioOutDownload) : (selected ? st::historyAudioInDownloadSelected : st::historyAudioInDownload));
|
||||||
}();
|
}();
|
||||||
icon->paintInCenter(p, inner);
|
const auto paintContent = [&](Painter &q) {
|
||||||
if (_animation && _animation->radial.animating()) {
|
if (bubblePattern) {
|
||||||
const auto rinner = inner.marginsRemoved(QMargins(st::historyAudioRadialLine, st::historyAudioRadialLine, st::historyAudioRadialLine, st::historyAudioRadialLine));
|
auto hq = PainterHighQualityEnabler(q);
|
||||||
auto fg = outbg ? (selected ? st::historyFileOutRadialFgSelected : st::historyFileOutRadialFg) : (selected ? st::historyFileInRadialFgSelected : st::historyFileInRadialFg);
|
auto pen = st::msgOutBg->p;
|
||||||
_animation->radial.draw(p, rinner, st::historyAudioRadialLine, fg);
|
pen.setWidth(st::lineWidth);
|
||||||
|
q.setPen(pen);
|
||||||
|
q.setBrush(Qt::NoBrush);
|
||||||
|
q.drawEllipse(inner);
|
||||||
|
}
|
||||||
|
icon->paintInCenter(q, inner);
|
||||||
|
if (_animation && _animation->radial.animating()) {
|
||||||
|
const auto rinner = inner.marginsRemoved(QMargins(st::historyAudioRadialLine, st::historyAudioRadialLine, st::historyAudioRadialLine, st::historyAudioRadialLine));
|
||||||
|
auto fg = outbg ? (selected ? st::historyFileOutRadialFgSelected : st::historyFileOutRadialFg) : (selected ? st::historyFileInRadialFgSelected : st::historyFileInRadialFg);
|
||||||
|
_animation->radial.draw(q, rinner, st::historyAudioRadialLine, fg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (bubblePattern) {
|
||||||
|
const auto add = st::lineWidth * 2;
|
||||||
|
const auto target = inner.marginsAdded({ add, add, add, add });
|
||||||
|
Ui::PaintPatternBubblePart(
|
||||||
|
p,
|
||||||
|
context.viewport,
|
||||||
|
context.bubblesPattern->pixmap,
|
||||||
|
target,
|
||||||
|
paintContent,
|
||||||
|
_cornerDownloadCache);
|
||||||
|
} else {
|
||||||
|
paintContent(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -978,9 +1020,7 @@ QSize Document::sizeForGrouping(int width) const {
|
|||||||
|
|
||||||
void Document::drawGrouped(
|
void Document::drawGrouped(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const QRect &clip,
|
const PaintContext &context,
|
||||||
TextSelection selection,
|
|
||||||
crl::time ms,
|
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
@ -991,8 +1031,7 @@ void Document::drawGrouped(
|
|||||||
draw(
|
draw(
|
||||||
p,
|
p,
|
||||||
geometry.width(),
|
geometry.width(),
|
||||||
selection,
|
context.translated(-geometry.topLeft()),
|
||||||
ms,
|
|
||||||
LayoutMode::Grouped);
|
LayoutMode::Grouped);
|
||||||
p.translate(-geometry.topLeft());
|
p.translate(-geometry.topLeft());
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ public:
|
|||||||
not_null<DocumentData*> document);
|
not_null<DocumentData*> document);
|
||||||
~Document();
|
~Document();
|
||||||
|
|
||||||
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
|
void draw(Painter &p, const PaintContext &context) const override;
|
||||||
TextState textState(QPoint point, StateRequest request) const override;
|
TextState textState(QPoint point, StateRequest request) const override;
|
||||||
void updatePressed(QPoint point) override;
|
void updatePressed(QPoint point) override;
|
||||||
|
|
||||||
@ -65,9 +65,7 @@ public:
|
|||||||
QSize sizeForGrouping(int width) const override;
|
QSize sizeForGrouping(int width) const override;
|
||||||
void drawGrouped(
|
void drawGrouped(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const QRect &clip,
|
const PaintContext &context,
|
||||||
TextSelection selection,
|
|
||||||
crl::time ms,
|
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
@ -109,8 +107,7 @@ private:
|
|||||||
void draw(
|
void draw(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
int width,
|
int width,
|
||||||
TextSelection selection,
|
const PaintContext &context,
|
||||||
crl::time ms,
|
|
||||||
LayoutMode mode) const;
|
LayoutMode mode) const;
|
||||||
[[nodiscard]] TextState textState(
|
[[nodiscard]] TextState textState(
|
||||||
QPoint point,
|
QPoint point,
|
||||||
@ -131,7 +128,10 @@ private:
|
|||||||
bool updateStatusText() const; // returns showPause
|
bool updateStatusText() const; // returns showPause
|
||||||
|
|
||||||
[[nodiscard]] bool downloadInCorner() const;
|
[[nodiscard]] bool downloadInCorner() const;
|
||||||
void drawCornerDownload(Painter &p, bool selected, LayoutMode mode) const;
|
void drawCornerDownload(
|
||||||
|
Painter &p,
|
||||||
|
const PaintContext &context,
|
||||||
|
LayoutMode mode) const;
|
||||||
[[nodiscard]] TextState cornerDownloadTextState(
|
[[nodiscard]] TextState cornerDownloadTextState(
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request,
|
StateRequest request,
|
||||||
@ -139,6 +139,8 @@ private:
|
|||||||
|
|
||||||
not_null<DocumentData*> _data;
|
not_null<DocumentData*> _data;
|
||||||
mutable std::shared_ptr<Data::DocumentMedia> _dataMedia;
|
mutable std::shared_ptr<Data::DocumentMedia> _dataMedia;
|
||||||
|
mutable QImage _iconCache;
|
||||||
|
mutable QImage _cornerDownloadCache;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -198,12 +198,12 @@ TextSelection Game::fromDescriptionSelection(
|
|||||||
return ShiftItemSelection(selection, _title);
|
return ShiftItemSelection(selection, _title);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
|
void Game::draw(Painter &p, const PaintContext &context) const {
|
||||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||||
auto paintw = width();
|
auto paintw = width();
|
||||||
|
|
||||||
auto outbg = _parent->hasOutLayout();
|
auto outbg = _parent->hasOutLayout();
|
||||||
bool selected = (selection == FullSelection);
|
bool selected = (context.selection == FullSelection);
|
||||||
|
|
||||||
auto &barfg = selected ? (outbg ? st::msgOutReplyBarSelColor : st::msgInReplyBarSelColor) : (outbg ? st::msgOutReplyBarColor : st::msgInReplyBarColor);
|
auto &barfg = selected ? (outbg ? st::msgOutReplyBarSelColor : st::msgInReplyBarSelColor) : (outbg ? st::msgOutReplyBarColor : st::msgInReplyBarColor);
|
||||||
auto &semibold = selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg);
|
auto &semibold = selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg);
|
||||||
@ -227,7 +227,7 @@ void Game::draw(Painter &p, const QRect &r, TextSelection selection, crl::time m
|
|||||||
if (_title.hasSkipBlock()) {
|
if (_title.hasSkipBlock()) {
|
||||||
endskip = _parent->skipBlockWidth();
|
endskip = _parent->skipBlockWidth();
|
||||||
}
|
}
|
||||||
_title.drawLeftElided(p, padding.left(), tshift, paintw, width(), _titleLines, style::al_left, 0, -1, endskip, false, selection);
|
_title.drawLeftElided(p, padding.left(), tshift, paintw, width(), _titleLines, style::al_left, 0, -1, endskip, false, context.selection);
|
||||||
tshift += _titleLines * lineHeight;
|
tshift += _titleLines * lineHeight;
|
||||||
}
|
}
|
||||||
if (_descriptionLines) {
|
if (_descriptionLines) {
|
||||||
@ -236,7 +236,7 @@ void Game::draw(Painter &p, const QRect &r, TextSelection selection, crl::time m
|
|||||||
if (_description.hasSkipBlock()) {
|
if (_description.hasSkipBlock()) {
|
||||||
endskip = _parent->skipBlockWidth();
|
endskip = _parent->skipBlockWidth();
|
||||||
}
|
}
|
||||||
_description.drawLeftElided(p, padding.left(), tshift, paintw, width(), _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(selection));
|
_description.drawLeftElided(p, padding.left(), tshift, paintw, width(), _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(context.selection));
|
||||||
tshift += _descriptionLines * lineHeight;
|
tshift += _descriptionLines * lineHeight;
|
||||||
}
|
}
|
||||||
if (_attach) {
|
if (_attach) {
|
||||||
@ -247,10 +247,11 @@ void Game::draw(Painter &p, const QRect &r, TextSelection selection, crl::time m
|
|||||||
auto attachTop = tshift - bubble.top();
|
auto attachTop = tshift - bubble.top();
|
||||||
if (rtl()) attachLeft = width() - attachLeft - _attach->width();
|
if (rtl()) attachLeft = width() - attachLeft - _attach->width();
|
||||||
|
|
||||||
auto attachSelection = selected ? FullSelection : TextSelection { 0, 0 };
|
auto attachContext = context.translated(-attachLeft, -attachTop);
|
||||||
|
attachContext.selection = selected ? FullSelection : TextSelection { 0, 0 };
|
||||||
|
|
||||||
p.translate(attachLeft, attachTop);
|
p.translate(attachLeft, attachTop);
|
||||||
_attach->draw(p, r.translated(-attachLeft, -attachTop), attachSelection, ms);
|
_attach->draw(p, attachContext);
|
||||||
auto pixwidth = _attach->width();
|
auto pixwidth = _attach->width();
|
||||||
auto pixheight = _attach->height();
|
auto pixheight = _attach->height();
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ public:
|
|||||||
|
|
||||||
void refreshParentId(not_null<HistoryItem*> realParent) override;
|
void refreshParentId(not_null<HistoryItem*> realParent) override;
|
||||||
|
|
||||||
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
|
void draw(Painter &p, const PaintContext &context) const override;
|
||||||
TextState textState(QPoint point, StateRequest request) const override;
|
TextState textState(QPoint point, StateRequest request) const override;
|
||||||
|
|
||||||
[[nodiscard]] TextSelection adjustSelection(
|
[[nodiscard]] TextSelection adjustSelection(
|
||||||
|
@ -276,14 +276,14 @@ bool Gif::autoplayEnabled() const {
|
|||||||
_data);
|
_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
|
void Gif::draw(Painter &p, const PaintContext &context) const {
|
||||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||||
|
|
||||||
ensureDataMediaCreated();
|
ensureDataMediaCreated();
|
||||||
const auto item = _parent->data();
|
const auto item = _parent->data();
|
||||||
const auto loaded = dataLoaded();
|
const auto loaded = dataLoaded();
|
||||||
const auto displayLoading = item->isSending() || _data->displayLoading();
|
const auto displayLoading = item->isSending() || _data->displayLoading();
|
||||||
const auto selected = (selection == FullSelection);
|
const auto selected = (context.selection == FullSelection);
|
||||||
const auto autoPaused = _parent->delegate()->elementIsGifPaused();
|
const auto autoPaused = _parent->delegate()->elementIsGifPaused();
|
||||||
const auto cornerDownload = downloadInCorner();
|
const auto cornerDownload = downloadInCorner();
|
||||||
const auto canBePlayed = _dataMedia->canBePlayed();
|
const auto canBePlayed = _dataMedia->canBePlayed();
|
||||||
@ -613,7 +613,7 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms
|
|||||||
}
|
}
|
||||||
if (!isRound && !_caption.isEmpty()) {
|
if (!isRound && !_caption.isEmpty()) {
|
||||||
p.setPen(outbg ? (selected ? st::historyTextOutFgSelected : st::historyTextOutFg) : (selected ? st::historyTextInFgSelected : st::historyTextInFg));
|
p.setPen(outbg ? (selected ? st::historyTextOutFgSelected : st::historyTextOutFg) : (selected ? st::historyTextInFgSelected : st::historyTextInFg));
|
||||||
_caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, selection);
|
_caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, context.selection);
|
||||||
} else if (!inWebPage) {
|
} else if (!inWebPage) {
|
||||||
auto fullRight = paintx + usex + usew;
|
auto fullRight = paintx + usex + usew;
|
||||||
auto fullBottom = painty + painth;
|
auto fullBottom = painty + painth;
|
||||||
@ -896,9 +896,7 @@ QSize Gif::sizeForGrouping(int width) const {
|
|||||||
|
|
||||||
void Gif::drawGrouped(
|
void Gif::drawGrouped(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const QRect &clip,
|
const PaintContext &context,
|
||||||
TextSelection selection,
|
|
||||||
crl::time ms,
|
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
@ -909,7 +907,7 @@ void Gif::drawGrouped(
|
|||||||
const auto item = _parent->data();
|
const auto item = _parent->data();
|
||||||
const auto loaded = dataLoaded();
|
const auto loaded = dataLoaded();
|
||||||
const auto displayLoading = (item->id < 0) || _data->displayLoading();
|
const auto displayLoading = (item->id < 0) || _data->displayLoading();
|
||||||
const auto selected = (selection == FullSelection);
|
const auto selected = (context.selection == FullSelection);
|
||||||
const auto autoPaused = _parent->delegate()->elementIsGifPaused();
|
const auto autoPaused = _parent->delegate()->elementIsGifPaused();
|
||||||
const auto fullFeatured = fullFeaturedGrouped(sides);
|
const auto fullFeatured = fullFeaturedGrouped(sides);
|
||||||
const auto cornerDownload = fullFeatured && downloadInCorner();
|
const auto cornerDownload = fullFeatured && downloadInCorner();
|
||||||
|
@ -45,7 +45,7 @@ public:
|
|||||||
not_null<DocumentData*> document);
|
not_null<DocumentData*> document);
|
||||||
~Gif();
|
~Gif();
|
||||||
|
|
||||||
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
|
void draw(Painter &p, const PaintContext &context) const override;
|
||||||
TextState textState(QPoint point, StateRequest request) const override;
|
TextState textState(QPoint point, StateRequest request) const override;
|
||||||
|
|
||||||
[[nodiscard]] TextSelection adjustSelection(
|
[[nodiscard]] TextSelection adjustSelection(
|
||||||
@ -73,9 +73,7 @@ public:
|
|||||||
QSize sizeForGrouping(int width) const override;
|
QSize sizeForGrouping(int width) const override;
|
||||||
void drawGrouped(
|
void drawGrouped(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const QRect &clip,
|
const PaintContext &context,
|
||||||
TextSelection selection,
|
|
||||||
crl::time ms,
|
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
|
@ -199,12 +199,12 @@ void Invoice::refreshParentId(not_null<HistoryItem*> realParent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Invoice::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
|
void Invoice::draw(Painter &p, const PaintContext &context) const {
|
||||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||||
auto paintw = width();
|
auto paintw = width();
|
||||||
|
|
||||||
auto outbg = _parent->hasOutLayout();
|
auto outbg = _parent->hasOutLayout();
|
||||||
bool selected = (selection == FullSelection);
|
bool selected = (context.selection == FullSelection);
|
||||||
|
|
||||||
auto &semibold = selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg);
|
auto &semibold = selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg);
|
||||||
|
|
||||||
@ -226,14 +226,14 @@ void Invoice::draw(Painter &p, const QRect &r, TextSelection selection, crl::tim
|
|||||||
if (_title.hasSkipBlock()) {
|
if (_title.hasSkipBlock()) {
|
||||||
endskip = _parent->skipBlockWidth();
|
endskip = _parent->skipBlockWidth();
|
||||||
}
|
}
|
||||||
_title.drawLeftElided(p, padding.left(), tshift, paintw, width(), _titleHeight / lineHeight, style::al_left, 0, -1, endskip, false, selection);
|
_title.drawLeftElided(p, padding.left(), tshift, paintw, width(), _titleHeight / lineHeight, style::al_left, 0, -1, endskip, false, context.selection);
|
||||||
tshift += _titleHeight;
|
tshift += _titleHeight;
|
||||||
|
|
||||||
p.setTextPalette(selected ? (outbg ? st::outTextPaletteSelected : st::inTextPaletteSelected) : (outbg ? st::outTextPalette : st::inTextPalette));
|
p.setTextPalette(selected ? (outbg ? st::outTextPaletteSelected : st::inTextPaletteSelected) : (outbg ? st::outTextPalette : st::inTextPalette));
|
||||||
}
|
}
|
||||||
if (_descriptionHeight) {
|
if (_descriptionHeight) {
|
||||||
p.setPen(outbg ? st::webPageDescriptionOutFg : st::webPageDescriptionInFg);
|
p.setPen(outbg ? st::webPageDescriptionOutFg : st::webPageDescriptionInFg);
|
||||||
_description.drawLeft(p, padding.left(), tshift, paintw, width(), style::al_left, 0, -1, toDescriptionSelection(selection));
|
_description.drawLeft(p, padding.left(), tshift, paintw, width(), style::al_left, 0, -1, toDescriptionSelection(context.selection));
|
||||||
tshift += _descriptionHeight;
|
tshift += _descriptionHeight;
|
||||||
}
|
}
|
||||||
if (_attach) {
|
if (_attach) {
|
||||||
@ -244,10 +244,11 @@ void Invoice::draw(Painter &p, const QRect &r, TextSelection selection, crl::tim
|
|||||||
auto attachTop = tshift - bubble.top();
|
auto attachTop = tshift - bubble.top();
|
||||||
if (rtl()) attachLeft = width() - attachLeft - _attach->width();
|
if (rtl()) attachLeft = width() - attachLeft - _attach->width();
|
||||||
|
|
||||||
auto attachSelection = selected ? FullSelection : TextSelection { 0, 0 };
|
auto attachContext = context.translated(-attachLeft, -attachTop);
|
||||||
|
attachContext.selection = selected ? FullSelection : TextSelection { 0, 0 };
|
||||||
|
|
||||||
p.translate(attachLeft, attachTop);
|
p.translate(attachLeft, attachTop);
|
||||||
_attach->draw(p, r.translated(-attachLeft, -attachTop), attachSelection, ms);
|
_attach->draw(p, attachContext);
|
||||||
auto pixwidth = _attach->width();
|
auto pixwidth = _attach->width();
|
||||||
|
|
||||||
auto available = _status.maxWidth();
|
auto available = _status.maxWidth();
|
||||||
|
@ -34,7 +34,7 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
|
void draw(Painter &p, const PaintContext &context) const override;
|
||||||
TextState textState(QPoint point, StateRequest request) const override;
|
TextState textState(QPoint point, StateRequest request) const override;
|
||||||
|
|
||||||
[[nodiscard]] TextSelection adjustSelection(
|
[[nodiscard]] TextSelection adjustSelection(
|
||||||
|
@ -148,12 +148,12 @@ TextSelection Location::fromDescriptionSelection(
|
|||||||
return ShiftItemSelection(selection, _title);
|
return ShiftItemSelection(selection, _title);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Location::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
|
void Location::draw(Painter &p, const PaintContext &context) const {
|
||||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||||
auto paintx = 0, painty = 0, paintw = width(), painth = height();
|
auto paintx = 0, painty = 0, paintw = width(), painth = height();
|
||||||
bool bubble = _parent->hasBubble();
|
bool bubble = _parent->hasBubble();
|
||||||
auto outbg = _parent->hasOutLayout();
|
auto outbg = _parent->hasOutLayout();
|
||||||
bool selected = (selection == FullSelection);
|
bool selected = (context.selection == FullSelection);
|
||||||
|
|
||||||
if (bubble) {
|
if (bubble) {
|
||||||
if (!_title.isEmpty() || !_description.isEmpty()) {
|
if (!_title.isEmpty() || !_description.isEmpty()) {
|
||||||
@ -166,12 +166,12 @@ void Location::draw(Painter &p, const QRect &r, TextSelection selection, crl::ti
|
|||||||
|
|
||||||
if (!_title.isEmpty()) {
|
if (!_title.isEmpty()) {
|
||||||
p.setPen(outbg ? st::webPageTitleOutFg : st::webPageTitleInFg);
|
p.setPen(outbg ? st::webPageTitleOutFg : st::webPageTitleInFg);
|
||||||
_title.drawLeftElided(p, paintx + st::msgPadding.left(), painty, textw, width(), 2, style::al_left, 0, -1, 0, false, selection);
|
_title.drawLeftElided(p, paintx + st::msgPadding.left(), painty, textw, width(), 2, style::al_left, 0, -1, 0, false, context.selection);
|
||||||
painty += qMin(_title.countHeight(textw), 2 * st::webPageTitleFont->height);
|
painty += qMin(_title.countHeight(textw), 2 * st::webPageTitleFont->height);
|
||||||
}
|
}
|
||||||
if (!_description.isEmpty()) {
|
if (!_description.isEmpty()) {
|
||||||
p.setPen(outbg ? st::webPageDescriptionOutFg : st::webPageDescriptionInFg);
|
p.setPen(outbg ? st::webPageDescriptionOutFg : st::webPageDescriptionInFg);
|
||||||
_description.drawLeftElided(p, paintx + st::msgPadding.left(), painty, textw, width(), 3, style::al_left, 0, -1, 0, false, toDescriptionSelection(selection));
|
_description.drawLeftElided(p, paintx + st::msgPadding.left(), painty, textw, width(), 3, style::al_left, 0, -1, 0, false, toDescriptionSelection(context.selection));
|
||||||
painty += qMin(_description.countHeight(textw), 3 * st::webPageDescriptionFont->height);
|
painty += qMin(_description.countHeight(textw), 3 * st::webPageDescriptionFont->height);
|
||||||
}
|
}
|
||||||
if (!_title.isEmpty() || !_description.isEmpty()) {
|
if (!_title.isEmpty() || !_description.isEmpty()) {
|
||||||
|
@ -27,7 +27,7 @@ public:
|
|||||||
const QString &description = QString());
|
const QString &description = QString());
|
||||||
~Location();
|
~Location();
|
||||||
|
|
||||||
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
|
void draw(Painter &p, const PaintContext &context) const override;
|
||||||
TextState textState(QPoint point, StateRequest request) const override;
|
TextState textState(QPoint point, StateRequest request) const override;
|
||||||
|
|
||||||
[[nodiscard]] TextSelection adjustSelection(
|
[[nodiscard]] TextSelection adjustSelection(
|
||||||
|
@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "history/view/history_view_cursor_state.h"
|
#include "history/view/history_view_cursor_state.h"
|
||||||
#include "lottie/lottie_single_player.h"
|
#include "lottie/lottie_single_player.h"
|
||||||
#include "storage/storage_shared_media.h"
|
#include "storage/storage_shared_media.h"
|
||||||
|
#include "layout/layout_selection.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
#include "ui/item_text_options.h"
|
#include "ui/item_text_options.h"
|
||||||
#include "ui/chat/message_bubble.h"
|
#include "ui/chat/message_bubble.h"
|
||||||
@ -173,6 +174,13 @@ auto Media::getBubbleSelectionIntervals(
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Media::usesBubblePattern(const PaintContext &context) const {
|
||||||
|
return (context.selection != FullSelection)
|
||||||
|
&& _parent->hasOutLayout()
|
||||||
|
&& context.bubblesPattern
|
||||||
|
&& !context.viewport.isEmpty()
|
||||||
|
&& !context.bubblesPattern->pixmap.size().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
PointState Media::pointState(QPoint point) const {
|
PointState Media::pointState(QPoint point) const {
|
||||||
return QRect(0, 0, width(), height()).contains(point)
|
return QRect(0, 0, width(), height()).contains(point)
|
||||||
|
@ -40,6 +40,7 @@ enum class CursorState : char;
|
|||||||
enum class InfoDisplayType : char;
|
enum class InfoDisplayType : char;
|
||||||
struct TextState;
|
struct TextState;
|
||||||
struct StateRequest;
|
struct StateRequest;
|
||||||
|
struct PaintContext;
|
||||||
class Element;
|
class Element;
|
||||||
|
|
||||||
enum class MediaInBubbleState {
|
enum class MediaInBubbleState {
|
||||||
@ -85,11 +86,7 @@ public:
|
|||||||
}
|
}
|
||||||
virtual void drawHighlight(Painter &p, int top) const {
|
virtual void drawHighlight(Painter &p, int top) const {
|
||||||
}
|
}
|
||||||
virtual void draw(
|
virtual void draw(Painter &p, const PaintContext &context) const = 0;
|
||||||
Painter &p,
|
|
||||||
const QRect &r,
|
|
||||||
TextSelection selection,
|
|
||||||
crl::time ms) const = 0;
|
|
||||||
[[nodiscard]] virtual PointState pointState(QPoint point) const;
|
[[nodiscard]] virtual PointState pointState(QPoint point) const;
|
||||||
[[nodiscard]] virtual TextState textState(
|
[[nodiscard]] virtual TextState textState(
|
||||||
QPoint point,
|
QPoint point,
|
||||||
@ -170,9 +167,7 @@ public:
|
|||||||
}
|
}
|
||||||
virtual void drawGrouped(
|
virtual void drawGrouped(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const QRect &clip,
|
const PaintContext &context,
|
||||||
TextSelection selection,
|
|
||||||
crl::time ms,
|
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
@ -299,6 +294,8 @@ protected:
|
|||||||
virtual void playAnimation(bool autoplay) {
|
virtual void playAnimation(bool autoplay) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool usesBubblePattern(const PaintContext &context) const;
|
||||||
|
|
||||||
const not_null<Element*> _parent;
|
const not_null<Element*> _parent;
|
||||||
MediaInBubbleState _inBubbleState = MediaInBubbleState::None;
|
MediaInBubbleState _inBubbleState = MediaInBubbleState::None;
|
||||||
|
|
||||||
|
@ -281,21 +281,19 @@ void GroupedMedia::drawHighlight(Painter &p, int top) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupedMedia::draw(
|
void GroupedMedia::draw(Painter &p, const PaintContext &context) const {
|
||||||
Painter &p,
|
|
||||||
const QRect &clip,
|
|
||||||
TextSelection selection,
|
|
||||||
crl::time ms) const {
|
|
||||||
auto wasCache = false;
|
auto wasCache = false;
|
||||||
auto nowCache = false;
|
auto nowCache = false;
|
||||||
const auto groupPadding = groupedPadding();
|
const auto groupPadding = groupedPadding();
|
||||||
|
auto selection = context.selection;
|
||||||
const auto fullSelection = (selection == FullSelection);
|
const auto fullSelection = (selection == FullSelection);
|
||||||
const auto textSelection = (_mode == Mode::Column)
|
const auto textSelection = (_mode == Mode::Column)
|
||||||
&& !fullSelection
|
&& !fullSelection
|
||||||
&& !IsSubGroupSelection(selection);
|
&& !IsSubGroupSelection(selection);
|
||||||
for (auto i = 0, count = int(_parts.size()); i != count; ++i) {
|
for (auto i = 0, count = int(_parts.size()); i != count; ++i) {
|
||||||
const auto &part = _parts[i];
|
const auto &part = _parts[i];
|
||||||
const auto partSelection = fullSelection
|
auto partContext = context;
|
||||||
|
partContext.selection = fullSelection
|
||||||
? FullSelection
|
? FullSelection
|
||||||
: textSelection
|
: textSelection
|
||||||
? selection
|
? selection
|
||||||
@ -313,9 +311,7 @@ void GroupedMedia::draw(
|
|||||||
}
|
}
|
||||||
part.content->drawGrouped(
|
part.content->drawGrouped(
|
||||||
p,
|
p,
|
||||||
clip,
|
partContext,
|
||||||
partSelection,
|
|
||||||
ms,
|
|
||||||
part.geometry.translated(0, groupPadding.top()),
|
part.geometry.translated(0, groupPadding.top()),
|
||||||
part.sides,
|
part.sides,
|
||||||
cornersFromSides(part.sides),
|
cornersFromSides(part.sides),
|
||||||
|
@ -32,11 +32,7 @@ public:
|
|||||||
void refreshParentId(not_null<HistoryItem*> realParent) override;
|
void refreshParentId(not_null<HistoryItem*> realParent) override;
|
||||||
|
|
||||||
void drawHighlight(Painter &p, int top) const override;
|
void drawHighlight(Painter &p, int top) const override;
|
||||||
void draw(
|
void draw(Painter &p, const PaintContext &context) const override;
|
||||||
Painter &p,
|
|
||||||
const QRect &clip,
|
|
||||||
TextSelection selection,
|
|
||||||
crl::time ms) const override;
|
|
||||||
PointState pointState(QPoint point) const override;
|
PointState pointState(QPoint point) const override;
|
||||||
TextState textState(
|
TextState textState(
|
||||||
QPoint point,
|
QPoint point,
|
||||||
|
@ -105,15 +105,11 @@ QSize UnwrappedMedia::countCurrentSize(int newWidth) {
|
|||||||
return { newWidth, newHeight };
|
return { newWidth, newHeight };
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnwrappedMedia::draw(
|
void UnwrappedMedia::draw(Painter &p, const PaintContext &context) const {
|
||||||
Painter &p,
|
|
||||||
const QRect &r,
|
|
||||||
TextSelection selection,
|
|
||||||
crl::time ms) const {
|
|
||||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) {
|
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool selected = (selection == FullSelection);
|
bool selected = (context.selection == FullSelection);
|
||||||
|
|
||||||
const auto rightAligned = _parent->hasOutLayout()
|
const auto rightAligned = _parent->hasOutLayout()
|
||||||
&& !_parent->delegate()->elementIsChatWide();
|
&& !_parent->delegate()->elementIsChatWide();
|
||||||
|
@ -57,7 +57,7 @@ public:
|
|||||||
not_null<Element*> parent,
|
not_null<Element*> parent,
|
||||||
std::unique_ptr<Content> content);
|
std::unique_ptr<Content> content);
|
||||||
|
|
||||||
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
|
void draw(Painter &p, const PaintContext &context) const override;
|
||||||
PointState pointState(QPoint point) const override;
|
PointState pointState(QPoint point) const override;
|
||||||
TextState textState(QPoint point, StateRequest request) const override;
|
TextState textState(QPoint point, StateRequest request) const override;
|
||||||
|
|
||||||
|
@ -223,12 +223,12 @@ QSize Photo::countCurrentSize(int newWidth) {
|
|||||||
return { newWidth, newHeight };
|
return { newWidth, newHeight };
|
||||||
}
|
}
|
||||||
|
|
||||||
void Photo::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
|
void Photo::draw(Painter &p, const PaintContext &context) const {
|
||||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||||
|
|
||||||
ensureDataMediaCreated();
|
ensureDataMediaCreated();
|
||||||
_dataMedia->automaticLoad(_realParent->fullId(), _parent->data());
|
_dataMedia->automaticLoad(_realParent->fullId(), _parent->data());
|
||||||
auto selected = (selection == FullSelection);
|
auto selected = (context.selection == FullSelection);
|
||||||
auto loaded = _dataMedia->loaded();
|
auto loaded = _dataMedia->loaded();
|
||||||
auto displayLoading = _data->displayLoading();
|
auto displayLoading = _data->displayLoading();
|
||||||
|
|
||||||
@ -330,7 +330,7 @@ void Photo::draw(Painter &p, const QRect &r, TextSelection selection, crl::time
|
|||||||
if (!_caption.isEmpty()) {
|
if (!_caption.isEmpty()) {
|
||||||
auto outbg = _parent->hasOutLayout();
|
auto outbg = _parent->hasOutLayout();
|
||||||
p.setPen(outbg ? (selected ? st::historyTextOutFgSelected : st::historyTextOutFg) : (selected ? st::historyTextInFgSelected : st::historyTextInFg));
|
p.setPen(outbg ? (selected ? st::historyTextOutFgSelected : st::historyTextOutFg) : (selected ? st::historyTextInFgSelected : st::historyTextInFg));
|
||||||
_caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, selection);
|
_caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, context.selection);
|
||||||
} else if (!inWebPage) {
|
} else if (!inWebPage) {
|
||||||
auto fullRight = paintx + paintw;
|
auto fullRight = paintx + paintw;
|
||||||
auto fullBottom = painty + painth;
|
auto fullBottom = painty + painth;
|
||||||
@ -489,9 +489,7 @@ QSize Photo::sizeForGrouping(int width) const {
|
|||||||
|
|
||||||
void Photo::drawGrouped(
|
void Photo::drawGrouped(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const QRect &clip,
|
const PaintContext &context,
|
||||||
TextSelection selection,
|
|
||||||
crl::time ms,
|
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
@ -503,7 +501,7 @@ void Photo::drawGrouped(
|
|||||||
|
|
||||||
validateGroupedCache(geometry, corners, cacheKey, cache);
|
validateGroupedCache(geometry, corners, cacheKey, cache);
|
||||||
|
|
||||||
const auto selected = (selection == FullSelection);
|
const auto selected = (context.selection == FullSelection);
|
||||||
const auto loaded = _dataMedia->loaded();
|
const auto loaded = _dataMedia->loaded();
|
||||||
const auto displayLoading = _data->displayLoading();
|
const auto displayLoading = _data->displayLoading();
|
||||||
const auto bubble = _parent->hasBubble();
|
const auto bubble = _parent->hasBubble();
|
||||||
|
@ -37,7 +37,7 @@ public:
|
|||||||
int width);
|
int width);
|
||||||
~Photo();
|
~Photo();
|
||||||
|
|
||||||
void draw(Painter &p, const QRect &clip, TextSelection selection, crl::time ms) const override;
|
void draw(Painter &p, const PaintContext &context) const override;
|
||||||
TextState textState(QPoint point, StateRequest request) const override;
|
TextState textState(QPoint point, StateRequest request) const override;
|
||||||
|
|
||||||
[[nodiscard]] TextSelection adjustSelection(
|
[[nodiscard]] TextSelection adjustSelection(
|
||||||
@ -62,9 +62,7 @@ public:
|
|||||||
QSize sizeForGrouping(int width) const override;
|
QSize sizeForGrouping(int width) const override;
|
||||||
void drawGrouped(
|
void drawGrouped(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const QRect &clip,
|
const PaintContext &context,
|
||||||
TextSelection selection,
|
|
||||||
crl::time ms,
|
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
|
@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "history/view/history_view_element.h"
|
#include "history/view/history_view_element.h"
|
||||||
#include "history/view/history_view_cursor_state.h"
|
#include "history/view/history_view_cursor_state.h"
|
||||||
#include "calls/calls_instance.h"
|
#include "calls/calls_instance.h"
|
||||||
|
#include "ui/chat/message_bubble.h"
|
||||||
#include "ui/text/text_options.h"
|
#include "ui/text/text_options.h"
|
||||||
#include "ui/text/text_utilities.h"
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/text/format_values.h"
|
#include "ui/text/format_values.h"
|
||||||
@ -715,15 +716,15 @@ void Poll::updateAnswerVotes() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Poll::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
|
void Poll::draw(Painter &p, const PaintContext &context) const {
|
||||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||||
auto paintw = width();
|
auto paintw = width();
|
||||||
|
|
||||||
checkSendingAnimation();
|
checkSendingAnimation();
|
||||||
_poll->checkResultsReload(_parent->data(), ms);
|
_poll->checkResultsReload(_parent->data(), context.now);
|
||||||
|
|
||||||
const auto outbg = _parent->hasOutLayout();
|
const auto outbg = _parent->hasOutLayout();
|
||||||
const auto selected = (selection == FullSelection);
|
const auto selected = (context.selection == FullSelection);
|
||||||
const auto ®ular = selected ? (outbg ? st::msgOutDateFgSelected : st::msgInDateFgSelected) : (outbg ? st::msgOutDateFg : st::msgInDateFg);
|
const auto ®ular = selected ? (outbg ? st::msgOutDateFgSelected : st::msgInDateFgSelected) : (outbg ? st::msgOutDateFg : st::msgInDateFg);
|
||||||
|
|
||||||
const auto padding = st::msgPadding;
|
const auto padding = st::msgPadding;
|
||||||
@ -734,14 +735,14 @@ void Poll::draw(Painter &p, const QRect &r, TextSelection selection, crl::time m
|
|||||||
paintw -= padding.left() + padding.right();
|
paintw -= padding.left() + padding.right();
|
||||||
|
|
||||||
p.setPen(outbg ? st::webPageTitleOutFg : st::webPageTitleInFg);
|
p.setPen(outbg ? st::webPageTitleOutFg : st::webPageTitleInFg);
|
||||||
_question.drawLeft(p, padding.left(), tshift, paintw, width(), style::al_left, 0, -1, selection);
|
_question.drawLeft(p, padding.left(), tshift, paintw, width(), style::al_left, 0, -1, context.selection);
|
||||||
tshift += _question.countHeight(paintw) + st::historyPollSubtitleSkip;
|
tshift += _question.countHeight(paintw) + st::historyPollSubtitleSkip;
|
||||||
|
|
||||||
p.setPen(regular);
|
p.setPen(regular);
|
||||||
_subtitle.drawLeftElided(p, padding.left(), tshift, paintw, width());
|
_subtitle.drawLeftElided(p, padding.left(), tshift, paintw, width());
|
||||||
paintRecentVoters(p, padding.left() + _subtitle.maxWidth(), tshift, selection);
|
paintRecentVoters(p, padding.left() + _subtitle.maxWidth(), tshift, context);
|
||||||
paintCloseByTimer(p, padding.left() + paintw, tshift, selection);
|
paintCloseByTimer(p, padding.left() + paintw, tshift, context.selection);
|
||||||
paintShowSolution(p, padding.left() + paintw, tshift, selection);
|
paintShowSolution(p, padding.left() + paintw, tshift, context.selection);
|
||||||
tshift += st::msgDateFont->height + st::historyPollAnswersSkip;
|
tshift += st::msgDateFont->height + st::historyPollAnswersSkip;
|
||||||
|
|
||||||
const auto progress = _answersAnimation
|
const auto progress = _answersAnimation
|
||||||
@ -773,14 +774,14 @@ void Poll::draw(Painter &p, const QRect &r, TextSelection selection, crl::time m
|
|||||||
tshift,
|
tshift,
|
||||||
paintw,
|
paintw,
|
||||||
width(),
|
width(),
|
||||||
selection);
|
context.selection);
|
||||||
tshift += height;
|
tshift += height;
|
||||||
}
|
}
|
||||||
if (!inlineFooter()) {
|
if (!inlineFooter()) {
|
||||||
paintBottom(p, padding.left(), tshift, paintw, selection);
|
paintBottom(p, padding.left(), tshift, paintw, context.selection);
|
||||||
} else if (!_totalVotesLabel.isEmpty()) {
|
} else if (!_totalVotesLabel.isEmpty()) {
|
||||||
tshift += st::msgPadding.bottom();
|
tshift += st::msgPadding.bottom();
|
||||||
paintInlineFooter(p, padding.left(), tshift, paintw, selection);
|
paintInlineFooter(p, padding.left(), tshift, paintw, context.selection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -864,7 +865,7 @@ void Poll::paintRecentVoters(
|
|||||||
Painter &p,
|
Painter &p,
|
||||||
int left,
|
int left,
|
||||||
int top,
|
int top,
|
||||||
TextSelection selection) const {
|
const PaintContext &context) const {
|
||||||
const auto count = int(_recentVoters.size());
|
const auto count = int(_recentVoters.size());
|
||||||
if (!count) {
|
if (!count) {
|
||||||
return;
|
return;
|
||||||
@ -875,7 +876,7 @@ void Poll::paintRecentVoters(
|
|||||||
auto y = top;
|
auto y = top;
|
||||||
const auto size = st::historyPollRecentVoterSize;
|
const auto size = st::historyPollRecentVoterSize;
|
||||||
const auto outbg = _parent->hasOutLayout();
|
const auto outbg = _parent->hasOutLayout();
|
||||||
const auto selected = (selection == FullSelection);
|
const auto selected = (context.selection == FullSelection);
|
||||||
auto pen = (selected
|
auto pen = (selected
|
||||||
? (outbg ? st::msgOutBgSelected : st::msgInBgSelected)
|
? (outbg ? st::msgOutBgSelected : st::msgInBgSelected)
|
||||||
: (outbg ? st::msgOutBg : st::msgInBg))->p;
|
: (outbg ? st::msgOutBg : st::msgInBg))->p;
|
||||||
@ -888,10 +889,26 @@ void Poll::paintRecentVoters(
|
|||||||
if (!was && recent.userpic) {
|
if (!was && recent.userpic) {
|
||||||
created = true;
|
created = true;
|
||||||
}
|
}
|
||||||
p.setPen(pen);
|
const auto paintContent = [&](Painter &p) {
|
||||||
p.setBrush(Qt::NoBrush);
|
p.setPen(pen);
|
||||||
PainterHighQualityEnabler hq(p);
|
p.setBrush(Qt::NoBrush);
|
||||||
p.drawEllipse(x, y, size, size);
|
PainterHighQualityEnabler hq(p);
|
||||||
|
p.drawEllipse(x, y, size, size);
|
||||||
|
};
|
||||||
|
if (usesBubblePattern(context)) {
|
||||||
|
const auto add = st::lineWidth * 2;
|
||||||
|
const auto target = QRect(x, y, size, size).marginsAdded(
|
||||||
|
{ add, add, add, add });
|
||||||
|
Ui::PaintPatternBubblePart(
|
||||||
|
p,
|
||||||
|
context.viewport,
|
||||||
|
context.bubblesPattern->pixmap,
|
||||||
|
target,
|
||||||
|
paintContent,
|
||||||
|
_userpicCircleCache);
|
||||||
|
} else {
|
||||||
|
paintContent(p);
|
||||||
|
}
|
||||||
x -= st::historyPollRecentVoterSkip;
|
x -= st::historyPollRecentVoterSkip;
|
||||||
}
|
}
|
||||||
if (created) {
|
if (created) {
|
||||||
|
@ -30,7 +30,7 @@ public:
|
|||||||
not_null<PollData*> poll);
|
not_null<PollData*> poll);
|
||||||
~Poll();
|
~Poll();
|
||||||
|
|
||||||
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
|
void draw(Painter &p, const PaintContext &context) const override;
|
||||||
TextState textState(QPoint point, StateRequest request) const override;
|
TextState textState(QPoint point, StateRequest request) const override;
|
||||||
|
|
||||||
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
|
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
|
||||||
@ -107,7 +107,7 @@ private:
|
|||||||
Painter &p,
|
Painter &p,
|
||||||
int left,
|
int left,
|
||||||
int top,
|
int top,
|
||||||
TextSelection selection) const;
|
const PaintContext &context) const;
|
||||||
void paintCloseByTimer(
|
void paintCloseByTimer(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
int right,
|
int right,
|
||||||
@ -213,6 +213,7 @@ private:
|
|||||||
mutable std::unique_ptr<Ui::FireworksAnimation> _fireworksAnimation;
|
mutable std::unique_ptr<Ui::FireworksAnimation> _fireworksAnimation;
|
||||||
Ui::Animations::Simple _wrongAnswerAnimation;
|
Ui::Animations::Simple _wrongAnswerAnimation;
|
||||||
mutable QPoint _lastLinkPoint;
|
mutable QPoint _lastLinkPoint;
|
||||||
|
mutable QImage _userpicCircleCache;
|
||||||
|
|
||||||
mutable std::unique_ptr<CloseInformation> _close;
|
mutable std::unique_ptr<CloseInformation> _close;
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ QSize ThemeDocument::countCurrentSize(int newWidth) {
|
|||||||
return { newWidth, newHeight };
|
return { newWidth, newHeight };
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThemeDocument::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
|
void ThemeDocument::draw(Painter &p, const PaintContext &context) const {
|
||||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||||
|
|
||||||
ensureDataMediaCreated();
|
ensureDataMediaCreated();
|
||||||
@ -158,7 +158,7 @@ void ThemeDocument::draw(Painter &p, const QRect &r, TextSelection selection, cr
|
|||||||
if (_data) {
|
if (_data) {
|
||||||
_dataMedia->automaticLoad(_realParent->fullId(), _parent->data());
|
_dataMedia->automaticLoad(_realParent->fullId(), _parent->data());
|
||||||
}
|
}
|
||||||
auto selected = (selection == FullSelection);
|
auto selected = (context.selection == FullSelection);
|
||||||
auto loaded = dataLoaded();
|
auto loaded = dataLoaded();
|
||||||
auto displayLoading = _data && _data->displayLoading();
|
auto displayLoading = _data && _data->displayLoading();
|
||||||
|
|
||||||
|
@ -27,11 +27,7 @@ public:
|
|||||||
const std::optional<Data::WallPaper> ¶ms);
|
const std::optional<Data::WallPaper> ¶ms);
|
||||||
~ThemeDocument();
|
~ThemeDocument();
|
||||||
|
|
||||||
void draw(
|
void draw(Painter &p, const PaintContext &context) const override;
|
||||||
Painter &p,
|
|
||||||
const QRect &clip,
|
|
||||||
TextSelection selection,
|
|
||||||
crl::time ms) const override;
|
|
||||||
TextState textState(QPoint point, StateRequest request) const override;
|
TextState textState(QPoint point, StateRequest request) const override;
|
||||||
|
|
||||||
DocumentData *getDocument() const override {
|
DocumentData *getDocument() const override {
|
||||||
|
@ -448,12 +448,12 @@ void WebPage::unloadHeavyPart() {
|
|||||||
_photoMedia = nullptr;
|
_photoMedia = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebPage::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
|
void WebPage::draw(Painter &p, const PaintContext &context) const {
|
||||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||||
auto paintw = width();
|
auto paintw = width();
|
||||||
|
|
||||||
auto outbg = _parent->hasOutLayout();
|
auto outbg = _parent->hasOutLayout();
|
||||||
bool selected = (selection == FullSelection);
|
bool selected = (context.selection == FullSelection);
|
||||||
|
|
||||||
auto &barfg = selected ? (outbg ? st::msgOutReplyBarSelColor : st::msgInReplyBarSelColor) : (outbg ? st::msgOutReplyBarColor : st::msgInReplyBarColor);
|
auto &barfg = selected ? (outbg ? st::msgOutReplyBarSelColor : st::msgInReplyBarSelColor) : (outbg ? st::msgOutReplyBarColor : st::msgInReplyBarColor);
|
||||||
auto &semibold = selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg);
|
auto &semibold = selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg);
|
||||||
@ -512,7 +512,7 @@ void WebPage::draw(Painter &p, const QRect &r, TextSelection selection, crl::tim
|
|||||||
if (_siteName.hasSkipBlock()) {
|
if (_siteName.hasSkipBlock()) {
|
||||||
endskip = _parent->skipBlockWidth();
|
endskip = _parent->skipBlockWidth();
|
||||||
}
|
}
|
||||||
_siteName.drawLeftElided(p, padding.left(), tshift, paintw, width(), _siteNameLines, style::al_left, 0, -1, endskip, false, selection);
|
_siteName.drawLeftElided(p, padding.left(), tshift, paintw, width(), _siteNameLines, style::al_left, 0, -1, endskip, false, context.selection);
|
||||||
tshift += lineHeight;
|
tshift += lineHeight;
|
||||||
}
|
}
|
||||||
if (_titleLines) {
|
if (_titleLines) {
|
||||||
@ -521,7 +521,7 @@ void WebPage::draw(Painter &p, const QRect &r, TextSelection selection, crl::tim
|
|||||||
if (_title.hasSkipBlock()) {
|
if (_title.hasSkipBlock()) {
|
||||||
endskip = _parent->skipBlockWidth();
|
endskip = _parent->skipBlockWidth();
|
||||||
}
|
}
|
||||||
_title.drawLeftElided(p, padding.left(), tshift, paintw, width(), _titleLines, style::al_left, 0, -1, endskip, false, toTitleSelection(selection));
|
_title.drawLeftElided(p, padding.left(), tshift, paintw, width(), _titleLines, style::al_left, 0, -1, endskip, false, toTitleSelection(context.selection));
|
||||||
tshift += _titleLines * lineHeight;
|
tshift += _titleLines * lineHeight;
|
||||||
}
|
}
|
||||||
if (_descriptionLines) {
|
if (_descriptionLines) {
|
||||||
@ -531,10 +531,10 @@ void WebPage::draw(Painter &p, const QRect &r, TextSelection selection, crl::tim
|
|||||||
endskip = _parent->skipBlockWidth();
|
endskip = _parent->skipBlockWidth();
|
||||||
}
|
}
|
||||||
if (_descriptionLines > 0) {
|
if (_descriptionLines > 0) {
|
||||||
_description.drawLeftElided(p, padding.left(), tshift, paintw, width(), _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(selection));
|
_description.drawLeftElided(p, padding.left(), tshift, paintw, width(), _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(context.selection));
|
||||||
tshift += _descriptionLines * lineHeight;
|
tshift += _descriptionLines * lineHeight;
|
||||||
} else {
|
} else {
|
||||||
_description.drawLeft(p, padding.left(), tshift, paintw, width(), style::al_left, 0, -1, toDescriptionSelection(selection));
|
_description.drawLeft(p, padding.left(), tshift, paintw, width(), style::al_left, 0, -1, toDescriptionSelection(context.selection));
|
||||||
tshift += _description.countHeight(paintw);
|
tshift += _description.countHeight(paintw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -548,8 +548,9 @@ void WebPage::draw(Painter &p, const QRect &r, TextSelection selection, crl::tim
|
|||||||
|
|
||||||
p.translate(attachLeft, attachTop);
|
p.translate(attachLeft, attachTop);
|
||||||
|
|
||||||
auto attachSelection = selected ? FullSelection : TextSelection { 0, 0 };
|
auto attachContext = context.translated(-attachLeft, -attachTop);
|
||||||
_attach->draw(p, r.translated(-attachLeft, -attachTop), attachSelection, ms);
|
attachContext.selection = selected ? FullSelection : TextSelection { 0, 0 };
|
||||||
|
_attach->draw(p, attachContext);
|
||||||
auto pixwidth = _attach->width();
|
auto pixwidth = _attach->width();
|
||||||
auto pixheight = _attach->height();
|
auto pixheight = _attach->height();
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ public:
|
|||||||
|
|
||||||
void refreshParentId(not_null<HistoryItem*> realParent) override;
|
void refreshParentId(not_null<HistoryItem*> realParent) override;
|
||||||
|
|
||||||
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
|
void draw(Painter &p, const PaintContext &context) const override;
|
||||||
TextState textState(QPoint point, StateRequest request) const override;
|
TextState textState(QPoint point, StateRequest request) const override;
|
||||||
|
|
||||||
bool hideMessageText() const override {
|
bool hideMessageText() const override {
|
||||||
|
@ -93,10 +93,11 @@ void PaintPatternBubble(Painter &p, const SimpleBubble &args) {
|
|||||||
const auto fill = rect.intersected(args.patternViewport);
|
const auto fill = rect.intersected(args.patternViewport);
|
||||||
if (!fill.isEmpty()) {
|
if (!fill.isEmpty()) {
|
||||||
p.setClipRect(fill);
|
p.setClipRect(fill);
|
||||||
// #TODO bubbles optimizes
|
PaintPatternBubblePart(
|
||||||
const auto to = args.patternViewport;
|
p,
|
||||||
const auto from = QRect(QPoint(), pattern->pixmap.size());
|
args.patternViewport,
|
||||||
p.drawPixmap(to, pattern->pixmap, from);
|
pattern->pixmap,
|
||||||
|
fill);
|
||||||
p.setClipping(false);
|
p.setClipping(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -112,26 +113,13 @@ void PaintPatternBubble(Painter &p, const SimpleBubble &args) {
|
|||||||
int y,
|
int y,
|
||||||
const QImage &mask,
|
const QImage &mask,
|
||||||
QImage &cache) {
|
QImage &cache) {
|
||||||
Expects(mask.bytesPerLine() == mask.width() * 4);
|
PaintPatternBubblePart(
|
||||||
Expects(mask.format() == QImage::Format_ARGB32_Premultiplied);
|
p,
|
||||||
|
args.patternViewport,
|
||||||
if (cache.size() != mask.size()) {
|
pattern->pixmap,
|
||||||
cache = QImage(
|
QRect(QPoint(x, y), mask.size() / int(mask.devicePixelRatio())),
|
||||||
mask.size(),
|
mask,
|
||||||
QImage::Format_ARGB32_Premultiplied);
|
cache);
|
||||||
}
|
|
||||||
cache.setDevicePixelRatio(mask.devicePixelRatio());
|
|
||||||
Assert(cache.bytesPerLine() == cache.width() * 4);
|
|
||||||
memcpy(cache.bits(), mask.constBits(), mask.sizeInBytes());
|
|
||||||
|
|
||||||
auto q = QPainter(&cache);
|
|
||||||
q.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
|
||||||
const auto to = args.patternViewport.translated(-x, -y);
|
|
||||||
const auto from = QRect(QPoint(), pattern->pixmap.size());
|
|
||||||
q.drawPixmap(to, pattern->pixmap, from);
|
|
||||||
q.end();
|
|
||||||
|
|
||||||
p.drawImage(x, y, cache);
|
|
||||||
};
|
};
|
||||||
const auto fillCorner = [&](int x, int y, int index) {
|
const auto fillCorner = [&](int x, int y, int index) {
|
||||||
fillPattern(
|
fillPattern(
|
||||||
@ -365,4 +353,72 @@ void PaintBubble(Painter &p, const ComplexBubble &args) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PaintPatternBubblePart(
|
||||||
|
QPainter &p,
|
||||||
|
const QRect &viewport,
|
||||||
|
const QPixmap &pixmap,
|
||||||
|
const QRect &target) {
|
||||||
|
// #TODO bubbles optimizes
|
||||||
|
const auto to = viewport;
|
||||||
|
const auto from = QRect(QPoint(), pixmap.size());
|
||||||
|
p.drawPixmap(to, pixmap, from);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PaintPatternBubblePart(
|
||||||
|
QPainter &p,
|
||||||
|
const QRect &viewport,
|
||||||
|
const QPixmap &pixmap,
|
||||||
|
const QRect &target,
|
||||||
|
const QImage &mask,
|
||||||
|
QImage &cache) {
|
||||||
|
Expects(mask.bytesPerLine() == mask.width() * 4);
|
||||||
|
Expects(mask.format() == QImage::Format_ARGB32_Premultiplied);
|
||||||
|
|
||||||
|
if (cache.size() != mask.size()) {
|
||||||
|
cache = QImage(
|
||||||
|
mask.size(),
|
||||||
|
QImage::Format_ARGB32_Premultiplied);
|
||||||
|
}
|
||||||
|
cache.setDevicePixelRatio(mask.devicePixelRatio());
|
||||||
|
Assert(cache.bytesPerLine() == cache.width() * 4);
|
||||||
|
memcpy(cache.bits(), mask.constBits(), mask.sizeInBytes());
|
||||||
|
|
||||||
|
auto q = QPainter(&cache);
|
||||||
|
q.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||||
|
PaintPatternBubblePart(
|
||||||
|
q,
|
||||||
|
viewport.translated(-target.topLeft()),
|
||||||
|
pixmap,
|
||||||
|
QRect(QPoint(), cache.size() / int(cache.devicePixelRatio())));
|
||||||
|
q.end();
|
||||||
|
|
||||||
|
p.drawImage(target, cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PaintPatternBubblePart(
|
||||||
|
QPainter &p,
|
||||||
|
const QRect &viewport,
|
||||||
|
const QPixmap &pixmap,
|
||||||
|
const QRect &target,
|
||||||
|
Fn<void(Painter&)> paintContent,
|
||||||
|
QImage &cache) {
|
||||||
|
Expects(paintContent != nullptr);
|
||||||
|
|
||||||
|
if (cache.size() != target.size() * style::DevicePixelRatio()) {
|
||||||
|
cache = QImage(
|
||||||
|
target.size() * style::DevicePixelRatio(),
|
||||||
|
QImage::Format_ARGB32_Premultiplied);
|
||||||
|
cache.setDevicePixelRatio(style::DevicePixelRatio());
|
||||||
|
}
|
||||||
|
cache.fill(Qt::transparent);
|
||||||
|
auto q = Painter(&cache);
|
||||||
|
q.translate(-target.topLeft());
|
||||||
|
paintContent(q);
|
||||||
|
q.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||||
|
PaintPatternBubblePart(q, viewport, pixmap, target);
|
||||||
|
q.end();
|
||||||
|
|
||||||
|
p.drawImage(target, cache);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
@ -49,4 +49,26 @@ struct ComplexBubble {
|
|||||||
void PaintBubble(Painter &p, const SimpleBubble &args);
|
void PaintBubble(Painter &p, const SimpleBubble &args);
|
||||||
void PaintBubble(Painter &p, const ComplexBubble &args);
|
void PaintBubble(Painter &p, const ComplexBubble &args);
|
||||||
|
|
||||||
|
void PaintPatternBubblePart(
|
||||||
|
QPainter &p,
|
||||||
|
const QRect &viewport,
|
||||||
|
const QPixmap &pixmap,
|
||||||
|
const QRect &target);
|
||||||
|
|
||||||
|
void PaintPatternBubblePart(
|
||||||
|
QPainter &p,
|
||||||
|
const QRect &viewport,
|
||||||
|
const QPixmap &pixmap,
|
||||||
|
const QRect &target,
|
||||||
|
const QImage &mask,
|
||||||
|
QImage &cache);
|
||||||
|
|
||||||
|
void PaintPatternBubblePart(
|
||||||
|
QPainter &p,
|
||||||
|
const QRect &viewport,
|
||||||
|
const QPixmap &pixmap,
|
||||||
|
const QRect &target,
|
||||||
|
Fn<void(Painter&)> paintContent,
|
||||||
|
QImage &cache);
|
||||||
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
@ -1484,8 +1484,8 @@ HistoryView::PaintContext SessionController::bubblesContext(
|
|||||||
//}
|
//}
|
||||||
return {
|
return {
|
||||||
.bubblesPattern = _bubblesBackgroundPattern.get(),
|
.bubblesPattern = _bubblesBackgroundPattern.get(),
|
||||||
.viewport = viewport.translated(0, -args.initialShift),
|
.viewport = viewport,
|
||||||
.clip = args.clip.translated(0, -args.initialShift),
|
.clip = args.clip,
|
||||||
.now = crl::now(),
|
.now = crl::now(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -454,7 +454,6 @@ public:
|
|||||||
int visibleAreaTopGlobal = 0;
|
int visibleAreaTopGlobal = 0;
|
||||||
int visibleAreaWidth = 0;
|
int visibleAreaWidth = 0;
|
||||||
QRect clip;
|
QRect clip;
|
||||||
int initialShift = 0;
|
|
||||||
};
|
};
|
||||||
[[nodiscard]] HistoryView::PaintContext bubblesContext(
|
[[nodiscard]] HistoryView::PaintContext bubblesContext(
|
||||||
BubblesContextArgs &&args);
|
BubblesContextArgs &&args);
|
||||||
|
Loading…
Reference in New Issue
Block a user