tdesktop/Telegram/SourceFiles/ui/boxes/choose_time.cpp

138 lines
3.8 KiB
C++

/*
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/choose_time.h"
#include "base/qt_signal_producer.h"
#include "ui/ui_utility.h"
#include "ui/widgets/fields/time_part_input_with_placeholder.h"
#include "ui/wrap/padding_wrap.h"
#include "styles/style_boxes.h"
#include "styles/style_layers.h"
namespace Ui {
ChooseTimeResult ChooseTimeWidget(
not_null<RpWidget*> parent,
TimeId startSeconds) {
using TimeField = Ui::TimePartWithPlaceholder;
const auto putNext = [](not_null<TimeField*> field, QChar ch) {
field->setCursorPosition(0);
if (ch.unicode()) {
field->setText(ch + field->getLastText());
field->setCursorPosition(1);
}
field->onTextEdited();
field->setFocus();
};
const auto erasePrevious = [](not_null<TimeField*> field) {
const auto text = field->getLastText();
if (!text.isEmpty()) {
field->setCursorPosition(text.size() - 1);
field->setText(text.mid(0, text.size() - 1));
}
field->setFocus();
};
struct State {
not_null<TimeField*> day;
not_null<TimeField*> hour;
not_null<TimeField*> minute;
rpl::variable<int> valueInSeconds = 0;
};
auto content = object_ptr<Ui::FixedHeightWidget>(
parent,
st::scheduleHeight);
const auto startDays = startSeconds / 86400;
startSeconds -= startDays * 86400;
const auto startHours = startSeconds / 3600;
startSeconds -= startHours * 3600;
const auto startMinutes = startSeconds / 60;
const auto state = content->lifetime().make_state<State>(State{
.day = Ui::CreateChild<TimeField>(
content.data(),
st::muteBoxTimeField,
rpl::never<QString>(),
QString::number(startDays)),
.hour = Ui::CreateChild<TimeField>(
content.data(),
st::muteBoxTimeField,
rpl::never<QString>(),
QString::number(startHours)),
.minute = Ui::CreateChild<TimeField>(
content.data(),
st::muteBoxTimeField,
rpl::never<QString>(),
QString::number(startMinutes)),
});
const auto day = Ui::MakeWeak(state->day);
const auto hour = Ui::MakeWeak(state->hour);
const auto minute = Ui::MakeWeak(state->minute);
day->setPhrase(tr::lng_days);
day->setMaxValue(31);
day->setWheelStep(1);
day->putNext() | rpl::start_with_next([=](QChar ch) {
putNext(hour, ch);
}, content->lifetime());
hour->setPhrase(tr::lng_hours);
hour->setMaxValue(23);
hour->setWheelStep(1);
hour->putNext() | rpl::start_with_next([=](QChar ch) {
putNext(minute, ch);
}, content->lifetime());
hour->erasePrevious() | rpl::start_with_next([=] {
erasePrevious(day);
}, content->lifetime());
minute->setPhrase(tr::lng_minutes);
minute->setMaxValue(59);
minute->setWheelStep(10);
minute->erasePrevious() | rpl::start_with_next([=] {
erasePrevious(hour);
}, content->lifetime());
content->sizeValue(
) | rpl::start_with_next([=](const QSize &s) {
const auto inputWidth = s.width() / 3;
auto rect = QRect(
0,
(s.height() - day->height()) / 2,
inputWidth,
day->height());
for (const auto &input : { day, hour, minute }) {
input->setGeometry(rect - st::muteBoxTimeFieldPadding);
rect.translate(inputWidth, 0);
}
}, content->lifetime());
rpl::merge(
rpl::single(rpl::empty),
base::qt_signal_producer(day.data(), &MaskedInputField::changed),
base::qt_signal_producer(hour.data(), &MaskedInputField::changed),
base::qt_signal_producer(minute.data(), &MaskedInputField::changed)
) | rpl::start_with_next([=] {
state->valueInSeconds = 0
+ day->getLastText().toUInt() * 3600 * 24
+ hour->getLastText().toUInt() * 3600
+ minute->getLastText().toUInt() * 60;
}, content->lifetime());
return {
object_ptr<Ui::RpWidget>::fromRaw(content.release()),
state->valueInSeconds.value(),
};
}
} // namespace Ui