| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- /*
- This file is part of Telegram Desktop,
- the official desktop application for the Telegram messaging service.
- For license and copyright information please follow this link:
- https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
- */
- #include "ui/unread_badge_paint.h"
- #include "ui/ui_utility.h"
- #include "styles/style_dialogs.h"
- namespace Ui {
- namespace {
- struct UnreadBadgeSizeData {
- QImage circle;
- QPixmap left[6], right[6];
- };
- class UnreadBadgeStyleData {
- public:
- UnreadBadgeStyleData();
- UnreadBadgeSizeData sizes[static_cast<int>(UnreadBadgeSize::kCount)];
- style::color bg[6] = {
- st::dialogsUnreadBg,
- st::dialogsUnreadBgOver,
- st::dialogsUnreadBgActive,
- st::dialogsUnreadBgMuted,
- st::dialogsUnreadBgMutedOver,
- st::dialogsUnreadBgMutedActive
- };
- style::color reactionBg[6] = {
- st::dialogsDraftFg,
- st::dialogsDraftFgOver,
- st::dialogsDraftFgActive,
- st::dialogsUnreadBgMuted,
- st::dialogsUnreadBgMutedOver,
- st::dialogsUnreadBgMutedActive
- };
- rpl::lifetime lifetime;
- };
- UnreadBadgeStyleData::UnreadBadgeStyleData() {
- style::PaletteChanged(
- ) | rpl::start_with_next([=] {
- for (auto &data : sizes) {
- for (auto &left : data.left) {
- left = QPixmap();
- }
- for (auto &right : data.right) {
- right = QPixmap();
- }
- }
- }, lifetime);
- }
- UnreadBadgeStyleData &UnreadBadgeStyles() {
- static auto result = UnreadBadgeStyleData();
- return result;
- }
- void CreateCircleMask(UnreadBadgeSizeData *data, int size) {
- if (!data->circle.isNull()) {
- return;
- }
- data->circle = style::createCircleMask(size);
- }
- [[nodiscard]] QImage ColorizeCircleHalf(
- UnreadBadgeSizeData *data,
- int size,
- int half,
- int xoffset,
- style::color color) {
- auto result = style::colorizeImage(data->circle, color, QRect(xoffset, 0, half, size));
- result.setDevicePixelRatio(style::DevicePixelRatio());
- return result;
- }
- [[nodiscard]] QString ComputeUnreadBadgeText(
- const QString &unreadCount,
- int allowDigits) {
- return (allowDigits > 0) && (unreadCount.size() > allowDigits + 1)
- ? u".."_q + unreadCount.mid(unreadCount.size() - allowDigits)
- : unreadCount;
- }
- void PaintUnreadBadge(QPainter &p, const QRect &rect, const UnreadBadgeStyle &st) {
- Assert(rect.height() == st.size);
- int index = (st.muted ? 0x03 : 0x00) + (st.active ? 0x02 : (st.selected ? 0x01 : 0x00));
- int size = st.size, sizehalf = size / 2;
- auto &styles = UnreadBadgeStyles();
- auto badgeData = styles.sizes;
- if (st.sizeId > UnreadBadgeSize()) {
- Assert(st.sizeId < UnreadBadgeSize::kCount);
- badgeData = &styles.sizes[static_cast<int>(st.sizeId)];
- }
- const auto bg = (st.sizeId == UnreadBadgeSize::ReactionInDialogs)
- ? styles.reactionBg[index]
- : styles.bg[index];
- if (badgeData->left[index].isNull()) {
- const auto ratio = style::DevicePixelRatio();
- int imgsize = size * ratio, imgsizehalf = sizehalf * ratio;
- CreateCircleMask(badgeData, size);
- badgeData->left[index] = PixmapFromImage(
- ColorizeCircleHalf(badgeData, imgsize, imgsizehalf, 0, bg));
- badgeData->right[index] = PixmapFromImage(ColorizeCircleHalf(
- badgeData,
- imgsize,
- imgsizehalf,
- imgsize - imgsizehalf,
- bg));
- }
- int bar = rect.width() - 2 * sizehalf;
- p.drawPixmap(rect.x(), rect.y(), badgeData->left[index]);
- if (bar) {
- p.fillRect(rect.x() + sizehalf, rect.y(), bar, rect.height(), bg);
- }
- p.drawPixmap(rect.x() + sizehalf + bar, rect.y(), badgeData->right[index]);
- }
- } // namespace
- UnreadBadgeStyle::UnreadBadgeStyle()
- : size(st::dialogsUnreadHeight)
- , padding(st::dialogsUnreadPadding)
- , font(st::dialogsUnreadFont) {
- }
- QSize CountUnreadBadgeSize(
- const QString &unreadCount,
- const UnreadBadgeStyle &st,
- int allowDigits) {
- const auto text = ComputeUnreadBadgeText(unreadCount, allowDigits);
- const auto unreadRectHeight = st.size;
- const auto unreadWidth = st.font->width(text);
- return {
- std::max(unreadWidth + 2 * st.padding, unreadRectHeight),
- unreadRectHeight,
- };
- }
- QRect PaintUnreadBadge(
- QPainter &p,
- const QString &unreadCount,
- int x,
- int y,
- const UnreadBadgeStyle &st,
- int allowDigits) {
- const auto text = ComputeUnreadBadgeText(unreadCount, allowDigits);
- const auto unreadRectHeight = st.size;
- const auto unreadWidth = st.font->width(text);
- const auto unreadRectWidth = std::max(
- unreadWidth + 2 * st.padding,
- unreadRectHeight);
- const auto unreadRectLeft = ((st.align & Qt::AlignHorizontal_Mask) & style::al_center)
- ? (x - unreadRectWidth) / 2
- : ((st.align & Qt::AlignHorizontal_Mask) & style::al_right)
- ? (x - unreadRectWidth)
- : x;
- const auto unreadRectTop = y;
- const auto badge = QRect(unreadRectLeft, unreadRectTop, unreadRectWidth, unreadRectHeight);
- PaintUnreadBadge(p, badge, st);
- const auto textTop = st.textTop ? st.textTop : (unreadRectHeight - st.font->height) / 2;
- p.setFont(st.font);
- p.setPen(st.active
- ? st::dialogsUnreadFgActive
- : st.selected
- ? st::dialogsUnreadFgOver
- : st::dialogsUnreadFg);
- p.drawText(unreadRectLeft + (unreadRectWidth - unreadWidth) / 2, unreadRectTop + textTop + st.font->ascent, text);
- return badge;
- }
- } // namespace Ui
|