mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 13:47:05 +02:00
Added initial implementation of chats filters tabs slider to td_ui.
This commit is contained in:
parent
5a4449f1a2
commit
f0a2c47613
3 changed files with 245 additions and 0 deletions
188
Telegram/SourceFiles/ui/widgets/chat_filters_tabs_slider.cpp
Normal file
188
Telegram/SourceFiles/ui/widgets/chat_filters_tabs_slider.cpp
Normal file
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
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/widgets/chat_filters_tabs_slider.h"
|
||||
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "styles/style_widgets.h"
|
||||
|
||||
#include <QScrollBar>
|
||||
|
||||
namespace Ui {
|
||||
|
||||
ChatsFiltersTabs::ChatsFiltersTabs(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
const style::SettingsSlider &st)
|
||||
: Ui::SettingsSlider(parent, st)
|
||||
, _st(st)
|
||||
, _unreadSt([&] {
|
||||
auto st = Ui::UnreadBadgeStyle();
|
||||
st.align = style::al_left;
|
||||
return st;
|
||||
}())
|
||||
, _unreadMaxString(u"99+"_q)
|
||||
, _unreadSkip(st::lineWidth * 5) {
|
||||
Expects(_st.barSnapToLabel && _st.strictSkip);
|
||||
if (_st.barRadius > 0) {
|
||||
_bar.emplace(_st.barRadius, _st.barFg);
|
||||
_barActive.emplace(_st.barRadius, _st.barFgActive);
|
||||
}
|
||||
{
|
||||
const auto one = Ui::CountUnreadBadgeSize(u"9"_q, _unreadSt, 1);
|
||||
_cachedBadgeWidths = {
|
||||
one.width(),
|
||||
Ui::CountUnreadBadgeSize(u"99"_q, _unreadSt, 2).width(),
|
||||
Ui::CountUnreadBadgeSize(u"999"_q, _unreadSt, 2).width(),
|
||||
};
|
||||
_cachedBadgeHeight = one.height();
|
||||
}
|
||||
}
|
||||
|
||||
int ChatsFiltersTabs::centerOfSection(int section) const {
|
||||
const auto widths = countSectionsWidths(0);
|
||||
auto result = 0;
|
||||
if (section >= 0 && section < widths.size()) {
|
||||
for (auto i = 0; i < section; i++) {
|
||||
result += widths[i];
|
||||
}
|
||||
result += widths[section] / 2;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ChatsFiltersTabs::fitWidthToSections() {
|
||||
const auto widths = countSectionsWidths(0);
|
||||
resizeToWidth(ranges::accumulate(widths, .0));
|
||||
}
|
||||
|
||||
void ChatsFiltersTabs::setUnreadCount(int index, int unreadCount) {
|
||||
const auto it = _unreadCounts.find(index);
|
||||
if (it == _unreadCounts.end()) {
|
||||
if (unreadCount) {
|
||||
_unreadCounts.emplace(index, Unread{
|
||||
.cache = cacheUnreadCount(unreadCount),
|
||||
.count = unreadCount,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (unreadCount) {
|
||||
it->second.count = unreadCount;
|
||||
it->second.cache = cacheUnreadCount(unreadCount);
|
||||
} else {
|
||||
_unreadCounts.erase(it);
|
||||
}
|
||||
}
|
||||
if (unreadCount) {
|
||||
const auto widthIndex = (unreadCount < 10)
|
||||
? 0
|
||||
: (unreadCount < 100)
|
||||
? 1
|
||||
: 2;
|
||||
setAdditionalContentWidthToSection(
|
||||
index,
|
||||
_cachedBadgeWidths[widthIndex] + _unreadSkip);
|
||||
} else {
|
||||
setAdditionalContentWidthToSection(index, 0);
|
||||
}
|
||||
}
|
||||
|
||||
QImage ChatsFiltersTabs::cacheUnreadCount(int count) const {
|
||||
const auto widthIndex = (count < 10) ? 0 : (count < 100) ? 1 : 2;
|
||||
auto image = QImage(
|
||||
QSize(_cachedBadgeWidths[widthIndex], _cachedBadgeHeight)
|
||||
* style::DevicePixelRatio(),
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
image.setDevicePixelRatio(style::DevicePixelRatio());
|
||||
image.fill(Qt::transparent);
|
||||
const auto string = (count > 99)
|
||||
? _unreadMaxString
|
||||
: QString::number(count);
|
||||
{
|
||||
auto p = QPainter(&image);
|
||||
Ui::PaintUnreadBadge(p, string, 0, 0, _unreadSt, 0);
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
void ChatsFiltersTabs::paintEvent(QPaintEvent *e) {
|
||||
auto p = QPainter(this);
|
||||
|
||||
const auto clip = e->rect();
|
||||
const auto range = getCurrentActiveRange();
|
||||
|
||||
auto index = 0;
|
||||
enumerateSections([&](Section §ion) {
|
||||
const auto activeWidth = _st.barSnapToLabel
|
||||
? section.contentWidth
|
||||
: section.width;
|
||||
const auto activeLeft = section.left
|
||||
+ (section.width - activeWidth) / 2;
|
||||
const auto active = 1.
|
||||
- std::clamp(
|
||||
std::abs(range.left - activeLeft) / float64(range.width),
|
||||
0.,
|
||||
1.);
|
||||
if (section.ripple) {
|
||||
const auto color = anim::color(
|
||||
_st.rippleBg,
|
||||
_st.rippleBgActive,
|
||||
active);
|
||||
section.ripple->paint(p, section.left, 0, width(), &color);
|
||||
if (section.ripple->empty()) {
|
||||
section.ripple.reset();
|
||||
}
|
||||
}
|
||||
const auto labelLeft = section.left
|
||||
+ (section.width - section.contentWidth) / 2;
|
||||
const auto rect = myrtlrect(
|
||||
labelLeft,
|
||||
_st.labelTop,
|
||||
section.contentWidth,
|
||||
_st.labelStyle.font->height);
|
||||
if (rect.intersects(clip)) {
|
||||
p.setPen(anim::pen(_st.labelFg, _st.labelFgActive, active));
|
||||
section.label.draw(p, {
|
||||
.position = QPoint(labelLeft, _st.labelTop),
|
||||
.outerWidth = width(),
|
||||
.availableWidth = section.label.maxWidth(),
|
||||
});
|
||||
{
|
||||
const auto it = _unreadCounts.find(index);
|
||||
if (it != _unreadCounts.end()) {
|
||||
p.drawImage(
|
||||
labelLeft
|
||||
+ _unreadSkip
|
||||
+ section.label.maxWidth(),
|
||||
_st.labelTop,
|
||||
it->second.cache);
|
||||
}
|
||||
}
|
||||
}
|
||||
index++;
|
||||
return true;
|
||||
});
|
||||
if (_st.barSnapToLabel) {
|
||||
const auto drawRect = [&](QRect rect, bool active) {
|
||||
const auto &bar = active ? _barActive : _bar;
|
||||
if (bar) {
|
||||
bar->paint(p, rect);
|
||||
} else {
|
||||
p.fillRect(rect, active ? _st.barFgActive : _st.barFg);
|
||||
}
|
||||
};
|
||||
const auto add = _st.barStroke / 2;
|
||||
const auto from = std::max(range.left - add, 0);
|
||||
const auto till = std::min(range.left + range.width + add, width());
|
||||
if (from < till) {
|
||||
drawRect(
|
||||
myrtlrect(from, _st.barTop, till - from, _st.barStroke),
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Ui
|
55
Telegram/SourceFiles/ui/widgets/chat_filters_tabs_slider.h
Normal file
55
Telegram/SourceFiles/ui/widgets/chat_filters_tabs_slider.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "ui/unread_badge_paint.h"
|
||||
#include "ui/widgets/discrete_sliders.h"
|
||||
|
||||
namespace style {
|
||||
struct SettingsSlider;
|
||||
} // namespace style
|
||||
|
||||
namespace Ui {
|
||||
|
||||
class RpWidget;
|
||||
class SettingsSlider;
|
||||
|
||||
class ChatsFiltersTabs final : public Ui::SettingsSlider {
|
||||
public:
|
||||
ChatsFiltersTabs(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
const style::SettingsSlider &st);
|
||||
|
||||
[[nodiscard]] int centerOfSection(int section) const;
|
||||
void fitWidthToSections();
|
||||
void setUnreadCount(int index, int unreadCount);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
[[nodiscard]] QImage cacheUnreadCount(int count) const;
|
||||
|
||||
using Index = int;
|
||||
struct Unread final {
|
||||
QImage cache;
|
||||
int count = 0;
|
||||
};
|
||||
base::flat_map<Index, Unread> _unreadCounts;
|
||||
const style::SettingsSlider &_st;
|
||||
const UnreadBadgeStyle _unreadSt;
|
||||
const QString _unreadMaxString;
|
||||
const int _unreadSkip;
|
||||
std::vector<int> _cachedBadgeWidths;
|
||||
int _cachedBadgeHeight = 0;
|
||||
std::optional<Ui::RoundRect> _bar;
|
||||
std::optional<Ui::RoundRect> _barActive;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Ui
|
|
@ -421,6 +421,8 @@ PRIVATE
|
|||
ui/widgets/fields/time_part_input_with_placeholder.cpp
|
||||
ui/widgets/fields/time_part_input_with_placeholder.h
|
||||
|
||||
ui/widgets/chat_filters_tabs_slider.cpp
|
||||
ui/widgets/chat_filters_tabs_slider.h
|
||||
ui/widgets/color_editor.cpp
|
||||
ui/widgets/color_editor.h
|
||||
ui/widgets/continuous_sliders.cpp
|
||||
|
|
Loading…
Add table
Reference in a new issue