Track month in CalendarBox while scrolling.

This commit is contained in:
John Preston 2021-11-11 17:03:06 +04:00
parent be7cd51740
commit b9b609f445
4 changed files with 51 additions and 3 deletions

View File

@ -519,7 +519,7 @@ defaultCalendarSizes: CalendarSizes {
daysHeight: 40px;
cellSize: size(48px, 40px);
cellInner: 34px;
padding: margins(14px, 7px, 14px, 10px);
padding: margins(14px, 0px, 14px, 0px);
}
calendarDaysFont: normalFont;
calendarDaysFg: boxTitleAdditionalFg;

View File

@ -100,5 +100,5 @@ exportCalendarSizes: CalendarSizes(defaultCalendarSizes) {
daysHeight: 40px;
cellSize: size(42px, 38px);
cellInner: 32px;
padding: margins(14px, 7px, 14px, 10px);
padding: margins(14px, 0px, 14px, 0px);
}

View File

@ -43,6 +43,7 @@ public:
void skipMonth(int skip);
void showMonth(QDate month);
[[nodiscard]] bool showsMonthOf(QDate date) const;
[[nodiscard]] int highlightedIndex() const {
return _highlightedIndex;
@ -122,6 +123,11 @@ void CalendarBox::Context::showMonth(QDate month) {
applyMonth(month);
}
bool CalendarBox::Context::showsMonthOf(QDate date) const {
const auto shown = _month.current();
return (shown.year() == date.year()) && (shown.month() == date.month());
}
void CalendarBox::Context::applyMonth(const QDate &month, bool forced) {
_daysCount = month.daysInMonth();
_daysShift = DaysShiftForMonth(month, _min);
@ -167,7 +173,7 @@ int CalendarBox::Context::DaysShiftForMonth(QDate month, QDate min) {
if (min.day() != 1) {
min = QDate(min.year(), min.month(), 1);
}
const auto add = min.daysTo(month) + inWeekIndex + (min.dayOfWeek() - 1);
const auto add = min.daysTo(month) - inWeekIndex + (min.dayOfWeek() - 1);
return from + add;
}
@ -565,6 +571,13 @@ CalendarBox::CalendarBox(QWidget*, CalendarBoxArgs &&args)
_context->setBeginningButton(args.hasBeginningButton);
_context->setMinDate(args.minDate);
_context->setMaxDate(args.maxDate);
_scroll->scrolls(
) | rpl::filter([=] {
return _watchScroll;
}) | rpl::start_with_next([=] {
processScroll();
}, lifetime());
}
void CalendarBox::prepare() {
@ -579,6 +592,7 @@ void CalendarBox::prepare() {
) | rpl::start_with_next([=](QDate month) {
monthChanged(month);
}, lifetime());
setExactScroll();
if (_finalize) {
_finalize(this);
@ -601,15 +615,46 @@ bool CalendarBox::isNextEnabled() const {
void CalendarBox::goPreviousMonth() {
if (isPreviousEnabled()) {
_context->skipMonth(-1);
setExactScroll();
}
}
void CalendarBox::goNextMonth() {
if (isNextEnabled()) {
_context->skipMonth(1);
setExactScroll();
}
}
void CalendarBox::setExactScroll() {
const auto top = _st.padding.top()
+ (_context->daysShift() / kDaysInWeek) * _st.cellSize.height();
_scroll->scrollToY(top);
_watchScroll = true;
}
void CalendarBox::processScroll() {
const auto wasTop = _scroll->scrollTop();
const auto wasShift = _context->daysShift();
const auto point = _scroll->rect().center() + QPoint(0, wasTop);
const auto row = (point.y() - _st.padding.top()) / _st.cellSize.height();
const auto col = (point.x() - _st.padding.left()) / _st.cellSize.width();
const auto index = row * kDaysInWeek + col;
const auto date = _context->dateFromIndex(index - wasShift);
if (_context->showsMonthOf(date)) {
return;
}
const auto wasFirst = _context->dateFromIndex(-wasShift);
const auto month = QDate(date.year(), date.month(), 1);
_watchScroll = false;
_context->showMonth(month);
const auto nowShift = _context->daysShift();
const auto nowFirst = _context->dateFromIndex(-nowShift);
const auto delta = nowFirst.daysTo(wasFirst) / kDaysInWeek;
_scroll->scrollToY(wasTop + delta * _st.cellSize.height());
_watchScroll = true;
}
void CalendarBox::monthChanged(QDate month) {
setDimensions(_st.width, st::calendarTitleHeight + _st.daysHeight + _inner->countMaxHeight());
auto previousEnabled = isPreviousEnabled();

View File

@ -58,6 +58,8 @@ private:
void goPreviousMonth();
void goNextMonth();
void setExactScroll();
void processScroll();
const style::CalendarSizes &_st;
@ -76,6 +78,7 @@ private:
Fn<void(QDate date)> _callback;
FnMut<void(not_null<CalendarBox*>)> _finalize;
bool _watchScroll = false;
};