mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Added ability to override background color for service messages.
This commit is contained in:
parent
cfbbce26c4
commit
7ee35bc80c
2 changed files with 177 additions and 36 deletions
|
@ -50,6 +50,8 @@ public:
|
||||||
|
|
||||||
// corners[(CircleMask value) * MaskMultiplier | (CornerVerticalSide value) | (CornerHorizontalSide value)]
|
// corners[(CircleMask value) * MaskMultiplier | (CornerVerticalSide value) | (CornerHorizontalSide value)]
|
||||||
QPixmap corners[8];
|
QPixmap corners[8];
|
||||||
|
|
||||||
|
base::flat_map<std::pair<int, uint32>, QPixmap> overridenCorners;
|
||||||
};
|
};
|
||||||
Data::GlobalStructurePointer<ServiceMessageStyleData> serviceMessageStyle;
|
Data::GlobalStructurePointer<ServiceMessageStyleData> serviceMessageStyle;
|
||||||
|
|
||||||
|
@ -86,10 +88,20 @@ void createCircleMasks() {
|
||||||
serviceMessageStyle->circle[InvertedMask] = style::createInvertedCircleMask(sizeInverted);
|
serviceMessageStyle->circle[InvertedMask] = style::createInvertedCircleMask(sizeInverted);
|
||||||
}
|
}
|
||||||
|
|
||||||
QPixmap circleCorner(int corner) {
|
uint32 ColorToUint(const style::color &bg) {
|
||||||
if (serviceMessageStyle->corners[corner].isNull()) {
|
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 maskType = corner / MaskMultiplier;
|
||||||
int radius = (maskType == NormalMask ? historyServiceMsgRadius() : historyServiceMsgInvertedRadius());
|
int radius = (maskType == NormalMask
|
||||||
|
? historyServiceMsgRadius()
|
||||||
|
: historyServiceMsgInvertedRadius());
|
||||||
int size = radius * cIntRetinaFactor();
|
int size = radius * cIntRetinaFactor();
|
||||||
|
|
||||||
int xoffset = 0, yoffset = 0;
|
int xoffset = 0, yoffset = 0;
|
||||||
|
@ -100,11 +112,14 @@ QPixmap circleCorner(int corner) {
|
||||||
yoffset = size;
|
yoffset = size;
|
||||||
}
|
}
|
||||||
auto part = QRect(xoffset, yoffset, size, size);
|
auto part = QRect(xoffset, yoffset, size, size);
|
||||||
auto result = style::colorizeImage(serviceMessageStyle->circle[maskType], st::msgServiceBg, part);
|
auto result = style::colorizeImage(
|
||||||
|
serviceMessageStyle->circle[maskType],
|
||||||
|
bg,
|
||||||
|
part);
|
||||||
result.setDevicePixelRatio(cRetinaFactor());
|
result.setDevicePixelRatio(cRetinaFactor());
|
||||||
serviceMessageStyle->corners[corner] = App::pixmapFromImageInPlace(std::move(result));
|
currentCorner = App::pixmapFromImageInPlace(std::move(result));
|
||||||
}
|
}
|
||||||
return serviceMessageStyle->corners[corner];
|
return currentCorner;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class SideStyle {
|
enum class SideStyle {
|
||||||
|
@ -114,38 +129,63 @@ enum class SideStyle {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns amount of pixels already painted vertically (so you can skip them in the complex rect shape).
|
// Returns amount of pixels already painted vertically (so you can skip them in the complex rect shape).
|
||||||
int paintBubbleSide(Painter &p, int x, int y, int width, SideStyle style, CornerVerticalSide side) {
|
int paintBubbleSide(
|
||||||
|
Painter &p,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int width,
|
||||||
|
SideStyle style,
|
||||||
|
CornerVerticalSide side,
|
||||||
|
const style::color &bg) {
|
||||||
if (style == SideStyle::Rounded) {
|
if (style == SideStyle::Rounded) {
|
||||||
auto left = circleCorner((NormalMask * MaskMultiplier) | side | CornerLeft);
|
const auto corner = (NormalMask * MaskMultiplier) | side;
|
||||||
|
auto left = circleCorner(corner | CornerLeft, bg);
|
||||||
int leftWidth = left.width() / cIntRetinaFactor();
|
int leftWidth = left.width() / cIntRetinaFactor();
|
||||||
p.drawPixmap(x, y, left);
|
p.drawPixmap(x, y, left);
|
||||||
|
|
||||||
auto right = circleCorner((NormalMask * MaskMultiplier) | side | CornerRight);
|
auto right = circleCorner(corner | CornerRight, bg);
|
||||||
int rightWidth = right.width() / cIntRetinaFactor();
|
int rightWidth = right.width() / cIntRetinaFactor();
|
||||||
p.drawPixmap(x + width - rightWidth, y, right);
|
p.drawPixmap(x + width - rightWidth, y, right);
|
||||||
|
|
||||||
int cornerHeight = left.height() / cIntRetinaFactor();
|
int cornerHeight = left.height() / cIntRetinaFactor();
|
||||||
p.fillRect(x + leftWidth, y, width - leftWidth - rightWidth, cornerHeight, st::msgServiceBg);
|
p.fillRect(
|
||||||
|
x + leftWidth,
|
||||||
|
y,
|
||||||
|
width - leftWidth - rightWidth,
|
||||||
|
cornerHeight,
|
||||||
|
bg);
|
||||||
return cornerHeight;
|
return cornerHeight;
|
||||||
} else if (style == SideStyle::Inverted) {
|
} else if (style == SideStyle::Inverted) {
|
||||||
// CornerLeft and CornerRight are inverted for SideStyle::Inverted sprites.
|
// CornerLeft and CornerRight are inverted for SideStyle::Inverted sprites.
|
||||||
auto left = circleCorner((InvertedMask * MaskMultiplier) | side | CornerRight);
|
const auto corner = (InvertedMask * MaskMultiplier) | side;
|
||||||
|
auto left = circleCorner(corner | CornerRight, bg);
|
||||||
int leftWidth = left.width() / cIntRetinaFactor();
|
int leftWidth = left.width() / cIntRetinaFactor();
|
||||||
p.drawPixmap(x - leftWidth, y, left);
|
p.drawPixmap(x - leftWidth, y, left);
|
||||||
|
|
||||||
auto right = circleCorner((InvertedMask * MaskMultiplier) | side | CornerLeft);
|
auto right = circleCorner(corner | CornerLeft, bg);
|
||||||
p.drawPixmap(x + width, y, right);
|
p.drawPixmap(x + width, y, right);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void paintBubblePart(Painter &p, int x, int y, int width, int height, SideStyle topStyle, SideStyle bottomStyle, bool forceShrink = false) {
|
void paintBubblePart(
|
||||||
if (topStyle == SideStyle::Inverted || bottomStyle == SideStyle::Inverted || forceShrink) {
|
Painter &p,
|
||||||
|
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;
|
width -= historyServiceMsgInvertedShrink() * 2;
|
||||||
x += historyServiceMsgInvertedShrink();
|
x += historyServiceMsgInvertedShrink();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (int skip = paintBubbleSide(p, x, y, width, topStyle, CornerTop)) {
|
if (int skip = paintBubbleSide(p, x, y, width, topStyle, CornerTop, bg)) {
|
||||||
y += skip;
|
y += skip;
|
||||||
height -= skip;
|
height -= skip;
|
||||||
}
|
}
|
||||||
|
@ -155,14 +195,28 @@ void paintBubblePart(Painter &p, int x, int y, int width, int height, SideStyle
|
||||||
} else if (bottomStyle == SideStyle::Inverted) {
|
} else if (bottomStyle == SideStyle::Inverted) {
|
||||||
bottomSize = historyServiceMsgInvertedRadius();
|
bottomSize = historyServiceMsgInvertedRadius();
|
||||||
}
|
}
|
||||||
if (int skip = paintBubbleSide(p, x, y + height - bottomSize, width, bottomStyle, CornerBottom)) {
|
const auto skip = paintBubbleSide(
|
||||||
|
p,
|
||||||
|
x,
|
||||||
|
y + height - bottomSize,
|
||||||
|
width,
|
||||||
|
bottomStyle,
|
||||||
|
CornerBottom,
|
||||||
|
bg);
|
||||||
|
if (skip) {
|
||||||
height -= skip;
|
height -= skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
p.fillRect(x, y, width, height, st::msgServiceBg);
|
p.fillRect(x, y, width, height, bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void paintPreparedDate(Painter &p, const QString &dateText, int dateTextWidth, int y, int w) {
|
void paintPreparedDate(
|
||||||
|
Painter &p,
|
||||||
|
const QString &dateText,
|
||||||
|
int dateTextWidth,
|
||||||
|
int y,
|
||||||
|
int w,
|
||||||
|
const style::color &bg) {
|
||||||
int left = st::msgServiceMargin.left();
|
int left = st::msgServiceMargin.left();
|
||||||
int maxwidth = w;
|
int maxwidth = w;
|
||||||
if (Core::App().settings().chatWide()) {
|
if (Core::App().settings().chatWide()) {
|
||||||
|
@ -172,7 +226,15 @@ void paintPreparedDate(Painter &p, const QString &dateText, int dateTextWidth, i
|
||||||
|
|
||||||
left += (w - dateTextWidth - st::msgServicePadding.left() - st::msgServicePadding.right()) / 2;
|
left += (w - dateTextWidth - st::msgServicePadding.left() - st::msgServicePadding.right()) / 2;
|
||||||
int height = st::msgServicePadding.top() + st::msgServiceFont->height + st::msgServicePadding.bottom();
|
int height = st::msgServicePadding.top() + st::msgServiceFont->height + st::msgServicePadding.bottom();
|
||||||
ServiceMessagePainter::paintBubble(p, left, y + st::msgServiceMargin.top(), dateTextWidth + st::msgServicePadding.left() + st::msgServicePadding.left(), height);
|
ServiceMessagePainter::paintBubble(
|
||||||
|
p,
|
||||||
|
left,
|
||||||
|
y + st::msgServiceMargin.top(),
|
||||||
|
dateTextWidth
|
||||||
|
+ st::msgServicePadding.left()
|
||||||
|
+ st::msgServicePadding.left(),
|
||||||
|
height,
|
||||||
|
bg);
|
||||||
|
|
||||||
p.setFont(st::msgServiceFont);
|
p.setFont(st::msgServiceFont);
|
||||||
p.setPen(st::msgServiceFg);
|
p.setPen(st::msgServiceFg);
|
||||||
|
@ -194,27 +256,69 @@ int WideChatWidth() {
|
||||||
return st::msgMaxWidth + 2 * st::msgPhotoSkip + 2 * st::msgMargin.left();
|
return st::msgMaxWidth + 2 * st::msgPhotoSkip + 2 * st::msgMargin.left();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceMessagePainter::paintDate(Painter &p, const QDateTime &date, int y, int w) {
|
void ServiceMessagePainter::paintDate(
|
||||||
auto dateText = langDayOfMonthFull(date.date());
|
Painter &p,
|
||||||
auto dateTextWidth = st::msgServiceFont->width(dateText);
|
const QDateTime &date,
|
||||||
paintPreparedDate(p, dateText, dateTextWidth, y, w);
|
int y,
|
||||||
|
int w,
|
||||||
|
const style::color &bg) {
|
||||||
|
const auto dateText = langDayOfMonthFull(date.date());
|
||||||
|
const auto dateTextWidth = st::msgServiceFont->width(dateText);
|
||||||
|
paintPreparedDate(p, dateText, dateTextWidth, y, w, bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceMessagePainter::paintDate(Painter &p, const QString &dateText, int y, int w) {
|
void ServiceMessagePainter::paintDate(
|
||||||
paintPreparedDate(p, dateText, st::msgServiceFont->width(dateText), y, w);
|
Painter &p,
|
||||||
|
const QString &dateText,
|
||||||
|
int y,
|
||||||
|
int w,
|
||||||
|
const style::color &bg) {
|
||||||
|
paintPreparedDate(
|
||||||
|
p,
|
||||||
|
dateText,
|
||||||
|
st::msgServiceFont->width(dateText),
|
||||||
|
y,
|
||||||
|
w,
|
||||||
|
bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceMessagePainter::paintDate(Painter &p, const QString &dateText, int dateTextWidth, int y, int w) {
|
void ServiceMessagePainter::paintDate(
|
||||||
paintPreparedDate(p, dateText, dateTextWidth, y, w);
|
Painter &p,
|
||||||
|
const QString &dateText,
|
||||||
|
int dateTextWidth,
|
||||||
|
int y,
|
||||||
|
int w,
|
||||||
|
const style::color &bg) {
|
||||||
|
paintPreparedDate(p, dateText, dateTextWidth, y, w, bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceMessagePainter::paintBubble(Painter &p, int x, int y, int w, int h) {
|
void ServiceMessagePainter::paintBubble(
|
||||||
|
Painter &p,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int w,
|
||||||
|
int h,
|
||||||
|
const style::color &bg) {
|
||||||
createCircleMasks();
|
createCircleMasks();
|
||||||
|
|
||||||
paintBubblePart(p, x, y, w, h, SideStyle::Rounded, SideStyle::Rounded);
|
paintBubblePart(
|
||||||
|
p,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
w,
|
||||||
|
h,
|
||||||
|
SideStyle::Rounded,
|
||||||
|
SideStyle::Rounded,
|
||||||
|
bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceMessagePainter::paintComplexBubble(Painter &p, int left, int width, const Ui::Text::String &text, const QRect &textRect) {
|
void ServiceMessagePainter::paintComplexBubble(
|
||||||
|
Painter &p,
|
||||||
|
int left,
|
||||||
|
int width,
|
||||||
|
const Ui::Text::String &text,
|
||||||
|
const QRect &textRect,
|
||||||
|
const style::color &bg) {
|
||||||
createCircleMasks();
|
createCircleMasks();
|
||||||
|
|
||||||
auto lineWidths = countLineWidths(text, textRect);
|
auto lineWidths = countLineWidths(text, textRect);
|
||||||
|
@ -250,7 +354,16 @@ void ServiceMessagePainter::paintComplexBubble(Painter &p, int left, int width,
|
||||||
richHeight -= st::msgServicePadding.top();
|
richHeight -= st::msgServicePadding.top();
|
||||||
}
|
}
|
||||||
forceShrink = previousShrink && (richWidth == previousRichWidth);
|
forceShrink = previousShrink && (richWidth == previousRichWidth);
|
||||||
paintBubblePart(p, left + ((width - richWidth) / 2), y, richWidth, richHeight, topStyle, bottomStyle, forceShrink);
|
paintBubblePart(
|
||||||
|
p,
|
||||||
|
left + ((width - richWidth) / 2),
|
||||||
|
y,
|
||||||
|
richWidth,
|
||||||
|
richHeight,
|
||||||
|
topStyle,
|
||||||
|
bottomStyle,
|
||||||
|
bg,
|
||||||
|
forceShrink);
|
||||||
y += richHeight;
|
y += richHeight;
|
||||||
|
|
||||||
previousShrink = forceShrink || (topStyle == SideStyle::Inverted) || (bottomStyle == SideStyle::Inverted);
|
previousShrink = forceShrink || (topStyle == SideStyle::Inverted) || (bottomStyle == SideStyle::Inverted);
|
||||||
|
|
|
@ -63,13 +63,41 @@ struct PaintContext {
|
||||||
|
|
||||||
class ServiceMessagePainter {
|
class ServiceMessagePainter {
|
||||||
public:
|
public:
|
||||||
static void paintDate(Painter &p, const QDateTime &date, int y, int w);
|
static void paintDate(
|
||||||
static void paintDate(Painter &p, const QString &dateText, int y, int w);
|
Painter &p,
|
||||||
static void paintDate(Painter &p, const QString &dateText, int dateTextWidth, int y, int w);
|
const QDateTime &date,
|
||||||
|
int y,
|
||||||
|
int w,
|
||||||
|
const style::color &bg = st::msgServiceBg);
|
||||||
|
static void paintDate(
|
||||||
|
Painter &p,
|
||||||
|
const QString &dateText,
|
||||||
|
int y,
|
||||||
|
int w,
|
||||||
|
const style::color &bg = st::msgServiceBg);
|
||||||
|
static void paintDate(
|
||||||
|
Painter &p,
|
||||||
|
const QString &dateText,
|
||||||
|
int dateTextWidth,
|
||||||
|
int y,
|
||||||
|
int w,
|
||||||
|
const style::color &bg = st::msgServiceBg);
|
||||||
|
|
||||||
static void paintBubble(Painter &p, int x, int y, int w, int h);
|
static void paintBubble(
|
||||||
|
Painter &p,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int w,
|
||||||
|
int h,
|
||||||
|
const style::color &bg = st::msgServiceBg);
|
||||||
|
|
||||||
static void paintComplexBubble(Painter &p, int left, int width, const Ui::Text::String &text, const QRect &textRect);
|
static void paintComplexBubble(
|
||||||
|
Painter &p,
|
||||||
|
int left,
|
||||||
|
int width,
|
||||||
|
const Ui::Text::String &text,
|
||||||
|
const QRect &textRect,
|
||||||
|
const style::color &bg = st::msgServiceBg);
|
||||||
|
|
||||||
private:
|
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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue