From 004648c1d1fc30f4babddb30e53daac9d054b314 Mon Sep 17 00:00:00 2001 From: RadRussianRus Date: Fri, 31 Jul 2020 14:00:22 +0300 Subject: [PATCH] Change day/hour on hour/minute overflow --- .../view/history_view_schedule_box.cpp | 86 +++++++++++++++++-- 1 file changed, 78 insertions(+), 8 deletions(-) diff --git a/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp b/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp index 73960991b..c43d948dd 100644 --- a/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp +++ b/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp @@ -87,6 +87,11 @@ public: rpl::producer<> erasePrevious() const; rpl::producer putNext() const; + void setOverflowCallback(Fn callback); + bool hasOverflowCallback(); + bool add(int value); + bool remove(int value); + protected: void keyPressEvent(QKeyEvent *e) override; void wheelEvent(QWheelEvent *e) override; @@ -104,6 +109,8 @@ private: rpl::event_stream<> _erasePrevious; rpl::event_stream _putNext; + Fn _overflowCallback = nullptr; + }; int Number(not_null field) { @@ -126,6 +133,7 @@ public: void showError(); int resizeGetHeight(int width) override; + void setOverflowCallback(Fn callback); protected: void paintEvent(QPaintEvent *e) override; @@ -163,6 +171,8 @@ private: Ui::Animations::Simple _a_focused; bool _focused = false; + Fn _overflowCallback = nullptr; + }; QTime ValidateTime(const QString &value) { @@ -216,6 +226,40 @@ rpl::producer TimePart::putNext() const { return _putNext.events(); } +void TimePart::setOverflowCallback(Fn callback) { + _overflowCallback = std::move(callback); +} + +bool TimePart::hasOverflowCallback() { + return _overflowCallback != nullptr; +} + +bool TimePart::add(int value) { + auto time = Number(this) + value; + const auto max = _maxValue + 1; + if (time < 0) { + if (!_overflowCallback(time)) { + return false; + } + while (time < 0) { + time += max; + } + } else if (time >= max) { + if (!_overflowCallback(time)) { + return false; + } + while (time >= max) { + time -= max; + } + } + setText(QString::number(time)); + return true; +} + +bool TimePart::remove(int value) { + return add(-value); +} + void TimePart::keyPressEvent(QKeyEvent *e) { const auto isBackspace = (e->key() == Qt::Key_Backspace); const auto isBeginning = (cursorPosition() == 0); @@ -228,14 +272,7 @@ void TimePart::keyPressEvent(QKeyEvent *e) { void TimePart::wheelEvent(QWheelEvent *e) { const auto direction = ProcessWheelEvent(e); - auto time = Number(this) + (direction * _wheelStep); - const auto max = _maxValue + 1; - if (time < 0) { - time += max; - } else if (time >= max) { - time -= max; - } - setText(QString::number(time)); + add(direction * _wheelStep); } void TimePart::correctValue( @@ -333,11 +370,29 @@ TimeInput::TimeInput(QWidget *parent, const QString &value) _hour->putNext() | rpl::start_with_next([=](QChar ch) { putNext(_minute, ch); }, lifetime()); + _hour->setOverflowCallback([=] (int h) { + if (_overflowCallback) { + return _overflowCallback(h); + } + + return true; + }); _minute->setMaxValue(59); _minute->setWheelStep(10); _minute->erasePrevious() | rpl::start_with_next([=] { erasePrevious(_hour); }, lifetime()); + _minute->setOverflowCallback([=] (int m) { + if (_hour->hasOverflowCallback()) { + if (m > 59) { + return _hour->add(1); + } else if (m < 0) { + return _hour->remove(1); + } + } + + return true; + }); _separator1->setAttribute(Qt::WA_TransparentForMouseEvents); setMouseTracking(true); @@ -510,6 +565,10 @@ int TimeInput::resizeGetHeight(int width) { return st::scheduleDateField.heightMin; } +void TimeInput::setOverflowCallback(Fn callback) { + _overflowCallback = std::move(callback); +} + void TimeInput::showError() { setErrorShown(true); if (!_focused) { @@ -651,6 +710,17 @@ void ScheduleBox( return base::EventFilterResult::Continue; }); + timeInput->setOverflowCallback([=] (int h) { + // Since it will be triggered only on overflow, we don't need additional condition here. + const auto direction = (h < 0) ? -1 : 1; + + const auto prevDate = date->current(); + const auto d = date->current().addDays(direction); + *date = std::clamp(d, minDate, maxDate); + + return prevDate != date->current(); + }); + content->widthValue( ) | rpl::start_with_next([=](int width) { const auto paddings = width