Fixed smooth paint of stack linear chart on move of footer slider.

This commit is contained in:
23rd 2023-09-26 19:24:10 +03:00 committed by John Preston
parent cee833f102
commit d9a08bb6a6
2 changed files with 65 additions and 29 deletions

View file

@ -46,6 +46,45 @@ inline float64 InterpolationRatio(float64 from, float64 to, float64 result) {
return (result - from) / (to - from); return (result - from) / (to - from);
}; };
[[nodiscard]] Limits FindAdditionalZoomedOutXIndices(const PaintContext &c) {
constexpr auto kOffset = int(1);
auto &xPercentage = c.chartData.xPercentage;
auto leftResult = 0.;
{
auto i = std::max(int(c.xIndices.min) - kOffset, 0);
if (xPercentage[i] > c.xPercentageLimits.min) {
while (true) {
i--;
if (i < 0) {
leftResult = 0;
break;
} else if (!(xPercentage[i] > c.xPercentageLimits.min)) {
leftResult = i;
break;
}
}
} else {
leftResult = i;
}
}
{
const auto lastIndex = float64(xPercentage.size() - 1);
auto i = std::min(lastIndex, float64(c.xIndices.max) + kOffset);
if (xPercentage[i] < c.xPercentageLimits.max) {
while (true) {
i++;
if (i > lastIndex) {
return { leftResult, lastIndex };
} else if (!(xPercentage[i] < c.xPercentageLimits.max)) {
return { leftResult, i };
}
}
} else {
return { leftResult, i };
}
}
}
} // namespace } // namespace
StackLinearChartView::StackLinearChartView() = default; StackLinearChartView::StackLinearChartView() = default;
@ -68,13 +107,10 @@ void StackLinearChartView::prepareZoom(
const PaintContext &c, const PaintContext &c,
TransitionStep step) { TransitionStep step) {
if (step == TransitionStep::ZoomedOut) { if (step == TransitionStep::ZoomedOut) {
constexpr auto kOffset = float64(2); _transition.zoomedOutXIndicesAdditional
_transition.zoomedOutXIndices = { = FindAdditionalZoomedOutXIndices(c);
float64(std::max(0., c.xIndices.min - kOffset)), _transition.zoomedOutXIndices = c.xIndices;
float64(std::min( _transition.zoomedOutXPercentage = c.xPercentageLimits;
float64(c.chartData.xPercentage.size() - 1),
c.xIndices.max + kOffset)),
};
} else if (step == TransitionStep::PrepareToZoomIn) { } else if (step == TransitionStep::PrepareToZoomIn) {
const auto &[zoomedStart, zoomedEnd] = const auto &[zoomedStart, zoomedEnd] =
_transition.zoomedOutXIndices; _transition.zoomedOutXIndices;
@ -82,10 +118,7 @@ void StackLinearChartView::prepareZoom(
c.chartData.lines.size(), c.chartData.lines.size(),
Transition::TransitionLine()); Transition::TransitionLine());
const auto xPercentageLimits = Limits{ const auto xPercentageLimits = _transition.zoomedOutXPercentage;
c.chartData.xPercentage[_transition.zoomedOutXIndices.min],
c.chartData.xPercentage[_transition.zoomedOutXIndices.max],
};
for (auto j = 0; j < 2; j++) { for (auto j = 0; j < 2; j++) {
const auto i = int((j == 1) ? zoomedEnd : zoomedStart); const auto i = int((j == 1) ? zoomedEnd : zoomedStart);
@ -230,7 +263,7 @@ void StackLinearChartView::paintChartOrZoomAnimation(
const auto hasTransitionAnimation = _transition.progress && !c.footer; const auto hasTransitionAnimation = _transition.progress && !c.footer;
const auto &[localStart, localEnd] = c.footer const auto &[localStart, localEnd] = c.footer
? Limits{ 0., float64(c.chartData.xPercentage.size() - 1) } ? Limits{ 0., float64(c.chartData.xPercentage.size() - 1) }
: _transition.zoomedOutXIndices; : _transition.zoomedOutXIndicesAdditional;
_skipPoints = std::vector<bool>(c.chartData.lines.size(), false); _skipPoints = std::vector<bool>(c.chartData.lines.size(), false);
auto paths = std::vector<QPainterPath>( auto paths = std::vector<QPainterPath>(
c.chartData.lines.size(), c.chartData.lines.size(),
@ -246,10 +279,12 @@ void StackLinearChartView::paintChartOrZoomAnimation(
.map(p); .map(p);
}; };
const auto xPercentageLimits = Limits{ const auto xPercentageLimits = !c.footer
c.chartData.xPercentage[localStart], ? _transition.zoomedOutXPercentage
c.chartData.xPercentage[localEnd], : Limits{
}; c.chartData.xPercentage[localStart],
c.chartData.xPercentage[localEnd],
};
auto straightLineProgress = 0.; auto straightLineProgress = 0.;
auto hasEmptyPoint = false; auto hasEmptyPoint = false;
@ -283,6 +318,10 @@ void StackLinearChartView::paintChartOrZoomAnimation(
auto drawingLinesCount = int(0); auto drawingLinesCount = int(0);
const auto xPoint = c.rect.width()
* ((c.chartData.xPercentage[i] - xPercentageLimits.min)
/ (xPercentageLimits.max - xPercentageLimits.min));
for (auto k = 0; k < c.chartData.lines.size(); k++) { for (auto k = 0; k < c.chartData.lines.size(); k++) {
const auto &line = c.chartData.lines[k]; const auto &line = c.chartData.lines[k];
if (!isEnabled(line.id)) { if (!isEnabled(line.id)) {
@ -311,10 +350,6 @@ void StackLinearChartView::paintChartOrZoomAnimation(
? float64(y[i] ? lineAlpha : 0.) ? float64(y[i] ? lineAlpha : 0.)
: float64(sum ? (y[i] * lineAlpha / sum) : 0.); : float64(sum ? (y[i] * lineAlpha / sum) : 0.);
const auto xPoint = c.rect.width()
* ((c.chartData.xPercentage[i] - xPercentageLimits.min)
/ (xPercentageLimits.max - xPercentageLimits.min));
if (!yPercentage && isLastLine) { if (!yPercentage && isLastLine) {
hasEmptyPoint = true; hasEmptyPoint = true;
} }
@ -803,10 +838,7 @@ void StackLinearChartView::paintSelectedXIndex(
return; return;
} }
const auto &[localStart, localEnd] = _transition.zoomedOutXIndices; const auto &[localStart, localEnd] = _transition.zoomedOutXIndices;
const auto xPercentageLimits = Limits{ const auto xPercentageLimits = _transition.zoomedOutXPercentage;
c.chartData.xPercentage[localStart],
c.chartData.xPercentage[localEnd],
};
p.setBrush(st::boxBg); p.setBrush(st::boxBg);
const auto r = st::statisticsDetailsDotRadius; const auto r = st::statisticsDetailsDotRadius;
const auto i = selectedXIndex; const auto i = selectedXIndex;
@ -858,9 +890,10 @@ int StackLinearChartView::findXIndexByPosition(
(x - rect.x()) / rect.width(), (x - rect.x()) / rect.width(),
0., 0.,
1.); 1.);
const auto &[localStart, localEnd] = _transition.zoomedOutXIndices;
const auto rawXPercentage = anim::interpolateF( const auto rawXPercentage = anim::interpolateF(
xPercentageLimits.min, _transition.zoomedOutXPercentage.min,
xPercentageLimits.max, _transition.zoomedOutXPercentage.max,
pointerRatio); pointerRatio);
const auto it = ranges::lower_bound( const auto it = ranges::lower_bound(
chartData.xPercentage, chartData.xPercentage,
@ -868,9 +901,10 @@ int StackLinearChartView::findXIndexByPosition(
const auto left = rawXPercentage - (*(it - 1)); const auto left = rawXPercentage - (*(it - 1));
const auto right = (*it) - rawXPercentage; const auto right = (*it) - rawXPercentage;
const auto nearestXPercentageIt = ((right) > (left)) ? (it - 1) : it; const auto nearestXPercentageIt = ((right) > (left)) ? (it - 1) : it;
return std::distance( return std::clamp(
begin(chartData.xPercentage), std::distance(begin(chartData.xPercentage), nearestXPercentageIt),
nearestXPercentageIt); long(localStart),
long(localEnd));
} }
void StackLinearChartView::setEnabled(int id, bool enabled, crl::time now) { void StackLinearChartView::setEnabled(int id, bool enabled, crl::time now) {

View file

@ -120,6 +120,8 @@ private:
bool pendingPrepareToZoomIn = false; bool pendingPrepareToZoomIn = false;
Limits zoomedOutXIndices; Limits zoomedOutXIndices;
Limits zoomedOutXIndicesAdditional;
Limits zoomedOutXPercentage;
Limits zoomedInLimit; Limits zoomedInLimit;
Limits zoomedInLimitXIndices; Limits zoomedInLimitXIndices;
Limits zoomedInRange; Limits zoomedInRange;