mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
Added month and year picker to calendar box by clicking on title.
This commit is contained in:
@@ -9,14 +9,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/widgets/vertical_drum_picker.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/chat/chat_style.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/cached_round_corners.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_settings.h"
|
||||
#include "styles/style_layers.h"
|
||||
|
||||
#include <QtCore/QLocale>
|
||||
|
||||
@@ -32,6 +36,172 @@ constexpr auto kJumpDelay = 2 * crl::time(1000);
|
||||
return (kDaysInWeek + date.dayOfWeek() - firstDayOfWeek) % kDaysInWeek;
|
||||
}
|
||||
|
||||
void FillMonthYearPicker(
|
||||
not_null<GenericBox*> box,
|
||||
QDate current,
|
||||
QDate minDate,
|
||||
QDate maxDate,
|
||||
const style::CalendarSizes &st,
|
||||
Fn<void(QDate)> done) {
|
||||
box->setWidth(st::boxWideWidth);
|
||||
const auto content = box->addRow(
|
||||
object_ptr<FixedHeightWidget>(box, st::settingsWorkingHoursPicker));
|
||||
|
||||
const auto font = st::boxTextFont;
|
||||
const auto itemHeight = st::settingsWorkingHoursPickerItemHeight;
|
||||
const auto picker = [=](
|
||||
int count,
|
||||
int startIndex,
|
||||
Fn<void(QPainter&, QRectF, int)> paint) {
|
||||
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());
|
||||
constexpr auto kMinYScale = 0.2;
|
||||
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);
|
||||
paint(p, r, index);
|
||||
p.restore();
|
||||
};
|
||||
const auto result = CreateChild<VerticalDrumPicker>(
|
||||
content,
|
||||
std::move(paintCallback),
|
||||
count,
|
||||
itemHeight,
|
||||
startIndex);
|
||||
result->show();
|
||||
return result;
|
||||
};
|
||||
|
||||
const auto effectiveMaxDate = maxDate.isValid()
|
||||
? maxDate
|
||||
: QDate::currentDate().addDays(365);
|
||||
const auto minYear = minDate.isValid() ? minDate.year() : 2013;
|
||||
const auto maxYear = effectiveMaxDate.year();
|
||||
const auto yearsCount = maxYear - minYear + 1;
|
||||
const auto yearsStartIndex = current.year() - minYear;
|
||||
const auto yearsPaint = [=](QPainter &p, QRectF rect, int index) {
|
||||
p.drawText(rect, QString::number(minYear + index), style::al_center);
|
||||
};
|
||||
const auto years = picker(yearsCount, yearsStartIndex, yearsPaint);
|
||||
|
||||
const auto monthsRange = [=](int year) {
|
||||
auto minMonth = 1;
|
||||
auto maxMonth = 12;
|
||||
if (minDate.isValid() && minDate.year() == year) {
|
||||
minMonth = minDate.month();
|
||||
}
|
||||
if (maxDate.isValid() && maxDate.year() == year) {
|
||||
maxMonth = maxDate.month();
|
||||
}
|
||||
return std::make_pair(minMonth, maxMonth);
|
||||
};
|
||||
|
||||
struct State {
|
||||
base::unique_qptr<VerticalDrumPicker> months;
|
||||
int currentMinMonth = 0;
|
||||
int currentMaxMonth = 0;
|
||||
};
|
||||
const auto state = box->lifetime().make_state<State>();
|
||||
|
||||
const auto [minMonth, maxMonth] = monthsRange(current.year());
|
||||
const auto monthsCount = maxMonth - minMonth + 1;
|
||||
const auto monthsStartIndex = current.month() - minMonth;
|
||||
const auto monthsPaint = [=, minMonth = minMonth](
|
||||
QPainter &p,
|
||||
QRectF rect,
|
||||
int index) {
|
||||
p.drawText(
|
||||
rect,
|
||||
Lang::Month(minMonth + index)(tr::now),
|
||||
style::al_center);
|
||||
};
|
||||
state->months = base::unique_qptr<VerticalDrumPicker>(
|
||||
picker(monthsCount, monthsStartIndex, monthsPaint));
|
||||
state->currentMinMonth = minMonth;
|
||||
state->currentMaxMonth = maxMonth;
|
||||
|
||||
years->value(
|
||||
) | rpl::skip(1) | rpl::start_with_next([=](int yearIndex) {
|
||||
const auto year = minYear + yearIndex;
|
||||
const auto [newMinMonth, newMaxMonth] = monthsRange(year);
|
||||
|
||||
if (newMinMonth != state->currentMinMonth
|
||||
|| newMaxMonth != state->currentMaxMonth) {
|
||||
const auto newMonthsCount = newMaxMonth - newMinMonth + 1;
|
||||
const auto oldMonth = state->currentMinMonth
|
||||
+ state->months->index();
|
||||
const auto clampedMonth = std::clamp(
|
||||
oldMonth - newMinMonth,
|
||||
0,
|
||||
newMonthsCount - 1);
|
||||
const auto newMonthsPaint = [=, minMonth = newMinMonth](
|
||||
QPainter &p,
|
||||
QRectF rect,
|
||||
int index) {
|
||||
p.drawText(
|
||||
rect,
|
||||
Lang::Month(minMonth + index)(tr::now),
|
||||
style::al_center);
|
||||
};
|
||||
state->months = base::unique_qptr<VerticalDrumPicker>(
|
||||
picker(newMonthsCount, clampedMonth, newMonthsPaint));
|
||||
state->currentMinMonth = newMinMonth;
|
||||
state->currentMaxMonth = newMaxMonth;
|
||||
const auto s = content->size();
|
||||
if (s.isValid()) {
|
||||
const auto half = s.width() / 2;
|
||||
state->months->setGeometry(0, 0, half, s.height());
|
||||
}
|
||||
}
|
||||
}, box->lifetime());
|
||||
|
||||
content->sizeValue(
|
||||
) | rpl::start_with_next([=](QSize s) {
|
||||
const auto half = s.width() / 2;
|
||||
state->months->setGeometry(0, 0, half, s.height());
|
||||
years->setGeometry(half, 0, half, s.height());
|
||||
}, 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());
|
||||
|
||||
box->addButton(tr::lng_gift_menu_show(), [=] {
|
||||
const auto year = minYear + years->index();
|
||||
const auto [minMonth, maxMonth] = monthsRange(year);
|
||||
const auto month = minMonth + state->months->index();
|
||||
done(QDate(year, month, 1));
|
||||
box->closeBox();
|
||||
});
|
||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class CalendarBox::Context {
|
||||
@@ -755,7 +925,7 @@ void CalendarBox::Inner::setDateChosenCallback(Fn<void(QDate)> callback) {
|
||||
|
||||
CalendarBox::Inner::~Inner() = default;
|
||||
|
||||
class CalendarBox::Title final : public RpWidget {
|
||||
class CalendarBox::Title final : public AbstractButton {
|
||||
public:
|
||||
Title(
|
||||
QWidget *parent,
|
||||
@@ -786,7 +956,7 @@ CalendarBox::Title::Title(
|
||||
not_null<Context*> context,
|
||||
const style::CalendarSizes &st,
|
||||
const style::CalendarColors &styleColors)
|
||||
: RpWidget(parent)
|
||||
: AbstractButton(parent)
|
||||
, _st(st)
|
||||
, _styleColors(styleColors)
|
||||
, _context(context) {
|
||||
@@ -804,13 +974,18 @@ CalendarBox::Title::Title(
|
||||
) | rpl::start_with_next([=] {
|
||||
if (!_context->selectionMode()) {
|
||||
setTextFromMonth(_context->month());
|
||||
} else if (!_context->selectedMin()) {
|
||||
setText(tr::lng_calendar_select_days(tr::now));
|
||||
setAttribute(Qt::WA_TransparentForMouseEvents, false);
|
||||
} else {
|
||||
setText(tr::lng_calendar_days(
|
||||
tr::now,
|
||||
lt_count,
|
||||
(1 + *_context->selectedMax() - *_context->selectedMin())));
|
||||
setAttribute(Qt::WA_TransparentForMouseEvents, true);
|
||||
if (!_context->selectedMin()) {
|
||||
setText(tr::lng_calendar_select_days(tr::now));
|
||||
} else {
|
||||
setText(tr::lng_calendar_days(
|
||||
tr::now,
|
||||
lt_count,
|
||||
(1 + *_context->selectedMax()
|
||||
- *_context->selectedMin())));
|
||||
}
|
||||
}
|
||||
}, lifetime());
|
||||
}
|
||||
@@ -879,11 +1054,28 @@ CalendarBox::CalendarBox(QWidget*, CalendarBoxArgs &&args)
|
||||
, _finalize(std::move(args.finalize))
|
||||
, _jumpTimer([=] { jump(_jumpButton); })
|
||||
, _selectionChanged(std::move(args.selectionChanged)) {
|
||||
_title->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
_context->setAllowsSelection(args.allowsSelection);
|
||||
_context->setMinDate(args.minDate);
|
||||
_context->setMaxDate(args.maxDate);
|
||||
|
||||
_title->setClickedCallback([=,
|
||||
minDate = args.minDate,
|
||||
maxDate = args.maxDate] {
|
||||
BoxContent::uiShow()->show(Box([=](not_null<GenericBox*> box) {
|
||||
FillMonthYearPicker(
|
||||
box,
|
||||
_context->month(),
|
||||
minDate,
|
||||
maxDate,
|
||||
_st,
|
||||
[=](QDate date) {
|
||||
_watchScroll = false;
|
||||
_context->showMonth(date);
|
||||
setExactScroll();
|
||||
});
|
||||
}), LayerOption::KeepOther);
|
||||
});
|
||||
|
||||
_scroll->scrolls(
|
||||
) | rpl::filter([=] {
|
||||
return _watchScroll;
|
||||
|
||||
Reference in New Issue
Block a user