| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- /*
- 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/boxes/time_picker_box.h"
- #include "base/event_filter.h"
- #include "lang/lang_keys.h"
- #include "ui/layers/generic_box.h"
- #include "ui/effects/animation_value.h"
- #include "ui/ui_utility.h"
- #include "ui/widgets/vertical_drum_picker.h"
- #include "styles/style_chat_helpers.h"
- #include "styles/style_layers.h"
- namespace Ui {
- namespace {
- constexpr auto kMinYScale = 0.2;
- } // namespace
- std::vector<TimeId> DefaultTimePickerValues() {
- return {
- (60 * 15),
- (60 * 30),
- (3600 * 1),
- (3600 * 2),
- (3600 * 3),
- (3600 * 4),
- (3600 * 8),
- (3600 * 12),
- (86400 * 1),
- (86400 * 2),
- (86400 * 3),
- (86400 * 7 * 1),
- (86400 * 7 * 2),
- (86400 * 31 * 1),
- (86400 * 31 * 2),
- (86400 * 31 * 3),
- };
- }
- Fn<TimeId()> TimePickerBox(
- not_null<GenericBox*> box,
- std::vector<TimeId> values,
- std::vector<QString> phrases,
- TimeId startValue) {
- Expects(phrases.size() == values.size());
- const auto startIndex = [&, &v = startValue] {
- const auto it = ranges::lower_bound(values, v);
- if (it == begin(values)) {
- return 0;
- }
- const auto left = *(it - 1);
- const auto right = *it;
- const auto shift = (std::abs(v - left) < std::abs(v - right))
- ? -1
- : 0;
- return int(std::distance(begin(values), it - shift));
- }();
- const auto content = box->addRow(object_ptr<Ui::FixedHeightWidget>(
- box,
- st::historyMessagesTTLPickerHeight));
- const auto font = st::boxTextFont;
- const auto maxPhraseWidth = [&] {
- // We have to use QFontMetricsF instead of
- // FontData::width for more precise calculation.
- const auto mf = QFontMetricsF(font->f);
- const auto maxPhrase = ranges::max_element(
- phrases,
- std::less<>(),
- [&](const QString &s) { return mf.horizontalAdvance(s); });
- return std::ceil(mf.horizontalAdvance(*maxPhrase));
- }();
- const auto itemHeight = st::historyMessagesTTLPickerItemHeight;
- auto paintCallback = [=](
- QPainter &p,
- int index,
- float64 y,
- float64 distanceFromCenter,
- int outerWidth) {
- const auto r = QRectF(0, y, outerWidth, itemHeight);
- const auto progress = std::abs(distanceFromCenter);
- const auto revProgress = 1. - progress;
- p.save();
- p.translate(r.center());
- const auto yScale = kMinYScale
- + (1. - kMinYScale) * anim::easeOutCubic(1., revProgress);
- p.scale(1., yScale);
- p.translate(-r.center());
- p.setOpacity(revProgress);
- p.setFont(font);
- p.setPen(st::defaultFlatLabel.textFg);
- p.drawText(r, phrases[index], style::al_center);
- p.restore();
- };
- const auto picker = Ui::CreateChild<Ui::VerticalDrumPicker>(
- content,
- std::move(paintCallback),
- phrases.size(),
- itemHeight,
- startIndex);
- content->sizeValue(
- ) | rpl::start_with_next([=](const QSize &s) {
- picker->resize(maxPhraseWidth, s.height());
- picker->moveToLeft((s.width() - picker->width()) / 2, 0);
- }, content->lifetime());
- content->paintRequest(
- ) | rpl::start_with_next([=](const QRect &r) {
- auto p = QPainter(content);
- p.fillRect(r, Qt::transparent);
- const auto lineRect = QRect(
- 0,
- content->height() / 2,
- content->width(),
- st::defaultInputField.borderActive);
- p.fillRect(lineRect.translated(0, itemHeight / 2), st::activeLineFg);
- p.fillRect(lineRect.translated(0, -itemHeight / 2), st::activeLineFg);
- }, content->lifetime());
- base::install_event_filter(content, [=](not_null<QEvent*> e) {
- if ((e->type() == QEvent::MouseButtonPress)
- || (e->type() == QEvent::MouseButtonRelease)
- || (e->type() == QEvent::MouseMove)) {
- picker->handleMouseEvent(static_cast<QMouseEvent*>(e.get()));
- } else if (e->type() == QEvent::Wheel) {
- picker->handleWheelEvent(static_cast<QWheelEvent*>(e.get()));
- }
- return base::EventFilterResult::Continue;
- });
- base::install_event_filter(box, [=](not_null<QEvent*> e) {
- if (e->type() == QEvent::KeyPress) {
- picker->handleKeyEvent(static_cast<QKeyEvent*>(e.get()));
- }
- return base::EventFilterResult::Continue;
- });
- return [=] { return values[picker->index()]; };
- }
- } // namespace Ui
|