Fixed position of selected X in linear chart animations.
This commit is contained in:
parent
20c2250abb
commit
54d5358b75
|
@ -830,20 +830,6 @@ Limits ChartWidget::ChartAnimationController::finalHeightLimits() const {
|
||||||
return _finalHeightLimits;
|
return _finalHeightLimits;
|
||||||
}
|
}
|
||||||
|
|
||||||
float64 ChartWidget::ChartAnimationController::detailsProgress(
|
|
||||||
crl::time now,
|
|
||||||
const Limits &appearedOnXLimits) const {
|
|
||||||
const auto xLimitsChanged = false
|
|
||||||
|| (appearedOnXLimits.min != _animationValueXMin.to())
|
|
||||||
|| (appearedOnXLimits.max != _animationValueXMax.to());
|
|
||||||
return (_animation.animating() && xLimitsChanged)
|
|
||||||
? std::clamp(
|
|
||||||
(now - _animation.started()) / float64(kExpandingDelay),
|
|
||||||
0.,
|
|
||||||
1.)
|
|
||||||
: 0.;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChartWidget::ChartAnimationController::animating() const {
|
bool ChartWidget::ChartAnimationController::animating() const {
|
||||||
return _animation.animating();
|
return _animation.animating();
|
||||||
}
|
}
|
||||||
|
@ -964,35 +950,6 @@ void ChartWidget::setupChartArea() {
|
||||||
PaintHorizontalLines(p, horizontalLine, chartRect);
|
PaintHorizontalLines(p, horizontalLine, chartRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto detailsAlpha = 1.
|
|
||||||
- _animationController.detailsProgress(
|
|
||||||
now,
|
|
||||||
_details.appearedOnXLimits);
|
|
||||||
|
|
||||||
if (_details.widget) {
|
|
||||||
if (!detailsAlpha && _details.currentX) {
|
|
||||||
_details.widget->hide();
|
|
||||||
_details.widget->setXIndex(-1);
|
|
||||||
_details.currentX = 0;
|
|
||||||
_details.appearedOnXLimits = {};
|
|
||||||
}
|
|
||||||
if (_details.currentX) {
|
|
||||||
const auto lineRect = QRectF(
|
|
||||||
_details.currentX - (st::lineWidth / 2.),
|
|
||||||
0,
|
|
||||||
st::lineWidth,
|
|
||||||
_chartArea->height());
|
|
||||||
const auto opacity = ScopedPainterOpacity(p, detailsAlpha);
|
|
||||||
p.fillRect(lineRect, st::windowSubTextFg);
|
|
||||||
_details.widget->setAlpha(detailsAlpha);
|
|
||||||
for (const auto &line : _chartData.lines) {
|
|
||||||
_details.widget->setLineAlpha(
|
|
||||||
line.id,
|
|
||||||
_chartView->alpha(line.id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_chartData) {
|
if (_chartData) {
|
||||||
// p.setRenderHint(
|
// p.setRenderHint(
|
||||||
// QPainter::Antialiasing,
|
// QPainter::Antialiasing,
|
||||||
|
@ -1020,16 +977,22 @@ void ChartWidget::setupChartArea() {
|
||||||
QRect(bottom.x(), bottom.y(), bottom.width(), st::lineWidth),
|
QRect(bottom.x(), bottom.y(), bottom.width(), st::lineWidth),
|
||||||
st::windowSubTextFg);
|
st::windowSubTextFg);
|
||||||
}
|
}
|
||||||
if (_details.widget && (detailsAlpha > 0.)) {
|
if (_details.widget) {
|
||||||
auto hq = PainterHighQualityEnabler(p);
|
const auto detailsAlpha = _details.widget->alpha();
|
||||||
auto o = ScopedPainterOpacity(p, detailsAlpha);
|
|
||||||
|
for (const auto &line : _chartData.lines) {
|
||||||
|
_details.widget->setLineAlpha(
|
||||||
|
line.id,
|
||||||
|
_chartView->alpha(line.id));
|
||||||
|
}
|
||||||
_chartView->paintSelectedXIndex(
|
_chartView->paintSelectedXIndex(
|
||||||
p,
|
p,
|
||||||
_chartData,
|
_chartData,
|
||||||
_animationController.currentXLimits(),
|
_animationController.currentXLimits(),
|
||||||
_animationController.currentHeightLimits(),
|
_animationController.currentHeightLimits(),
|
||||||
chartRect,
|
chartRect,
|
||||||
_details.widget->xIndex());
|
_details.widget->xIndex(),
|
||||||
|
detailsAlpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
p.setPen(st::windowSubTextFg);
|
p.setPen(st::windowSubTextFg);
|
||||||
|
@ -1158,6 +1121,12 @@ void ChartWidget::setupFooter() {
|
||||||
_footer->xPercentageLimitsChange(
|
_footer->xPercentageLimitsChange(
|
||||||
) | rpl::start_with_next([=](Limits xPercentageLimits) {
|
) | rpl::start_with_next([=](Limits xPercentageLimits) {
|
||||||
const auto now = crl::now();
|
const auto now = crl::now();
|
||||||
|
if (_details.widget
|
||||||
|
&& (_details.widget->xIndex() >= 0)
|
||||||
|
&& !_details.animation.animating()) {
|
||||||
|
_details.hideOnAnimationEnd = true;
|
||||||
|
_details.animation.start();
|
||||||
|
}
|
||||||
_animationController.setXPercentageLimits(
|
_animationController.setXPercentageLimits(
|
||||||
_chartData,
|
_chartData,
|
||||||
xPercentageLimits,
|
xPercentageLimits,
|
||||||
|
@ -1176,7 +1145,7 @@ void ChartWidget::setupFooter() {
|
||||||
|
|
||||||
void ChartWidget::setupDetails() {
|
void ChartWidget::setupDetails() {
|
||||||
if (!_chartData) {
|
if (!_chartData) {
|
||||||
_details = {};
|
_details.widget = nullptr;
|
||||||
_chartArea->update();
|
_chartArea->update();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1229,23 +1198,26 @@ void ChartWidget::setupDetails() {
|
||||||
const auto nearestXIndex = std::distance(
|
const auto nearestXIndex = std::distance(
|
||||||
begin(_chartData.xPercentage),
|
begin(_chartData.xPercentage),
|
||||||
nearestXPercentageIt);
|
nearestXPercentageIt);
|
||||||
_details.currentX = 0
|
const auto currentX = 0
|
||||||
+ chartRect.width() * InterpolationRatio(
|
+ chartRect.width() * InterpolationRatio(
|
||||||
currentXLimits.min,
|
currentXLimits.min,
|
||||||
currentXLimits.max,
|
currentXLimits.max,
|
||||||
*nearestXPercentageIt);
|
*nearestXPercentageIt);
|
||||||
_details.appearedOnXLimits = currentXLimits;
|
const auto xLeft = currentX
|
||||||
const auto xLeft = _details.currentX
|
|
||||||
- _details.widget->width();
|
- _details.widget->width();
|
||||||
const auto x = (xLeft >= 0)
|
const auto x = (xLeft >= 0)
|
||||||
? xLeft
|
? xLeft
|
||||||
: ((_details.currentX
|
: ((currentX
|
||||||
+ _details.widget->width()
|
+ _details.widget->width()
|
||||||
- _chartArea->width()) > 0)
|
- _chartArea->width()) > 0)
|
||||||
? 0
|
? 0
|
||||||
: _details.currentX;
|
: currentX;
|
||||||
_details.widget->moveToLeft(x, _chartArea->y());
|
_details.widget->moveToLeft(x, _chartArea->y());
|
||||||
_details.widget->setXIndex(nearestXIndex);
|
_details.widget->setXIndex(nearestXIndex);
|
||||||
|
if (_details.widget->isHidden()) {
|
||||||
|
_details.hideOnAnimationEnd = false;
|
||||||
|
_details.animation.start();
|
||||||
|
}
|
||||||
_details.widget->show();
|
_details.widget->show();
|
||||||
_chartArea->update();
|
_chartArea->update();
|
||||||
} break;
|
} break;
|
||||||
|
@ -1253,6 +1225,26 @@ void ChartWidget::setupDetails() {
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}, _details.widget->lifetime());
|
}, _details.widget->lifetime());
|
||||||
|
|
||||||
|
_details.animation.init([=](crl::time now) {
|
||||||
|
const auto value = std::clamp(
|
||||||
|
(now - _details.animation.started()) / float64(200),
|
||||||
|
0.,
|
||||||
|
1.);
|
||||||
|
const auto alpha = _details.hideOnAnimationEnd ? (1. - value) : value;
|
||||||
|
_chartArea->update();
|
||||||
|
if (_details.widget) {
|
||||||
|
_details.widget->setAlpha(alpha);
|
||||||
|
_details.widget->update();
|
||||||
|
}
|
||||||
|
if (value >= 1.) {
|
||||||
|
if (_details.hideOnAnimationEnd && _details.widget) {
|
||||||
|
_details.widget->hide();
|
||||||
|
_details.widget->setXIndex(-1);
|
||||||
|
}
|
||||||
|
_details.animation.stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChartWidget::setupFilterButtons() {
|
void ChartWidget::setupFilterButtons() {
|
||||||
|
|
|
@ -75,9 +75,6 @@ private:
|
||||||
[[nodiscard]] Limits currentHeightLimits() const;
|
[[nodiscard]] Limits currentHeightLimits() const;
|
||||||
[[nodiscard]] Limits currentFooterHeightLimits() const;
|
[[nodiscard]] Limits currentFooterHeightLimits() const;
|
||||||
[[nodiscard]] Limits finalHeightLimits() const;
|
[[nodiscard]] Limits finalHeightLimits() const;
|
||||||
[[nodiscard]] float64 detailsProgress(
|
|
||||||
crl::time now,
|
|
||||||
const Limits &appearedOnXLimits) const;
|
|
||||||
[[nodiscard]] bool animating() const;
|
[[nodiscard]] bool animating() const;
|
||||||
[[nodiscard]] bool footerAnimating() const;
|
[[nodiscard]] bool footerAnimating() const;
|
||||||
[[nodiscard]] bool isFPSSlow() const;
|
[[nodiscard]] bool isFPSSlow() const;
|
||||||
|
@ -146,8 +143,8 @@ private:
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
base::unique_qptr<PointDetailsWidget> widget;
|
base::unique_qptr<PointDetailsWidget> widget;
|
||||||
float64 currentX = 0;
|
Ui::Animations::Basic animation;
|
||||||
Limits appearedOnXLimits;
|
bool hideOnAnimationEnd = false;
|
||||||
} _details;
|
} _details;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -143,6 +143,10 @@ void PointDetailsWidget::setAlpha(float64 alpha) {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float64 PointDetailsWidget::alpha() const {
|
||||||
|
return _alpha;
|
||||||
|
}
|
||||||
|
|
||||||
int PointDetailsWidget::lineYAt(int index) const {
|
int PointDetailsWidget::lineYAt(int index) const {
|
||||||
auto linesHeight = 0.;
|
auto linesHeight = 0.;
|
||||||
for (auto i = 0; i < index; i++) {
|
for (auto i = 0; i < index; i++) {
|
||||||
|
@ -186,7 +190,7 @@ void PointDetailsWidget::paintEvent(QPaintEvent *e) {
|
||||||
.outerWidth = _textRect.width() - valueWidth,
|
.outerWidth = _textRect.width() - valueWidth,
|
||||||
.availableWidth = _textRect.width(),
|
.availableWidth = _textRect.width(),
|
||||||
};
|
};
|
||||||
p.setOpacity(line.alpha * line.alpha);
|
p.setOpacity(line.alpha * line.alpha * _alpha);
|
||||||
p.setPen(st::boxTextFg);
|
p.setPen(st::boxTextFg);
|
||||||
line.name.draw(p, nameContext);
|
line.name.draw(p, nameContext);
|
||||||
p.setPen(line.valueColor);
|
p.setPen(line.valueColor);
|
||||||
|
|
|
@ -23,6 +23,7 @@ public:
|
||||||
[[nodiscard]] int xIndex() const;
|
[[nodiscard]] int xIndex() const;
|
||||||
void setXIndex(int xIndex);
|
void setXIndex(int xIndex);
|
||||||
void setAlpha(float64 alpha);
|
void setAlpha(float64 alpha);
|
||||||
|
[[nodiscard]] float64 alpha() const;
|
||||||
void setLineAlpha(int lineId, float64 alpha);
|
void setLineAlpha(int lineId, float64 alpha);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -34,7 +34,8 @@ public:
|
||||||
const Limits &xPercentageLimits,
|
const Limits &xPercentageLimits,
|
||||||
const Limits &heightLimits,
|
const Limits &heightLimits,
|
||||||
const QRect &rect,
|
const QRect &rect,
|
||||||
int selectedXIndex) = 0;
|
int selectedXIndex,
|
||||||
|
float64 progress) = 0;
|
||||||
|
|
||||||
virtual void setEnabled(int id, bool enabled, crl::time now) = 0;
|
virtual void setEnabled(int id, bool enabled, crl::time now) = 0;
|
||||||
[[nodiscard]] virtual bool isEnabled(int id) const = 0;
|
[[nodiscard]] virtual bool isEnabled(int id) const = 0;
|
||||||
|
|
|
@ -135,16 +135,22 @@ void LinearChartView::paintSelectedXIndex(
|
||||||
const Limits &xPercentageLimits,
|
const Limits &xPercentageLimits,
|
||||||
const Limits &heightLimits,
|
const Limits &heightLimits,
|
||||||
const QRect &rect,
|
const QRect &rect,
|
||||||
int selectedXIndex) {
|
int selectedXIndex,
|
||||||
|
float64 progress) {
|
||||||
if (selectedXIndex < 0) {
|
if (selectedXIndex < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
auto hq = PainterHighQualityEnabler(p);
|
||||||
|
auto o = ScopedPainterOpacity(p, progress);
|
||||||
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;
|
||||||
const auto isSameToken = (_selectedPoints.lastXIndex == selectedXIndex)
|
const auto isSameToken = (_selectedPoints.lastXIndex == selectedXIndex)
|
||||||
&& (_selectedPoints.lastHeightLimits.min == heightLimits.min)
|
&& (_selectedPoints.lastHeightLimits.min == heightLimits.min)
|
||||||
&& (_selectedPoints.lastHeightLimits.max == heightLimits.max);
|
&& (_selectedPoints.lastHeightLimits.max == heightLimits.max)
|
||||||
|
&& (_selectedPoints.lastXLimits.min == xPercentageLimits.min)
|
||||||
|
&& (_selectedPoints.lastXLimits.max == xPercentageLimits.max);
|
||||||
|
auto linePainted = false;
|
||||||
for (const auto &line : chartData.lines) {
|
for (const auto &line : chartData.lines) {
|
||||||
const auto lineAlpha = alpha(line.id);
|
const auto lineAlpha = alpha(line.id);
|
||||||
const auto useCache = isSameToken
|
const auto useCache = isSameToken
|
||||||
|
@ -161,6 +167,18 @@ void LinearChartView::paintSelectedXIndex(
|
||||||
+ rect.topLeft();
|
+ rect.topLeft();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!linePainted) {
|
||||||
|
const auto lineRect = QRectF(
|
||||||
|
rect.x()
|
||||||
|
+ begin(_selectedPoints.points)->second.x()
|
||||||
|
- (st::lineWidth / 2.),
|
||||||
|
rect.y(),
|
||||||
|
st::lineWidth,
|
||||||
|
rect.height());
|
||||||
|
p.fillRect(lineRect, st::windowSubTextFg);
|
||||||
|
linePainted = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Paint.
|
// Paint.
|
||||||
auto o = ScopedPainterOpacity(p, lineAlpha * p.opacity());
|
auto o = ScopedPainterOpacity(p, lineAlpha * p.opacity());
|
||||||
p.setPen(QPen(line.color, st::statisticsChartLineWidth));
|
p.setPen(QPen(line.color, st::statisticsChartLineWidth));
|
||||||
|
@ -168,6 +186,7 @@ void LinearChartView::paintSelectedXIndex(
|
||||||
}
|
}
|
||||||
_selectedPoints.lastXIndex = selectedXIndex;
|
_selectedPoints.lastXIndex = selectedXIndex;
|
||||||
_selectedPoints.lastHeightLimits = heightLimits;
|
_selectedPoints.lastHeightLimits = heightLimits;
|
||||||
|
_selectedPoints.lastXLimits = xPercentageLimits;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinearChartView::setEnabled(int id, bool enabled, crl::time now) {
|
void LinearChartView::setEnabled(int id, bool enabled, crl::time now) {
|
||||||
|
|
|
@ -38,7 +38,8 @@ public:
|
||||||
const Limits &xPercentageLimits,
|
const Limits &xPercentageLimits,
|
||||||
const Limits &heightLimits,
|
const Limits &heightLimits,
|
||||||
const QRect &rect,
|
const QRect &rect,
|
||||||
int selectedXIndex) override;
|
int selectedXIndex,
|
||||||
|
float64 progress) override;
|
||||||
|
|
||||||
void setEnabled(int id, bool enabled, crl::time now) override;
|
void setEnabled(int id, bool enabled, crl::time now) override;
|
||||||
[[nodiscard]] bool isEnabled(int id) const override;
|
[[nodiscard]] bool isEnabled(int id) const override;
|
||||||
|
@ -97,6 +98,7 @@ private:
|
||||||
struct SelectedPoints final {
|
struct SelectedPoints final {
|
||||||
int lastXIndex = -1;
|
int lastXIndex = -1;
|
||||||
Limits lastHeightLimits;
|
Limits lastHeightLimits;
|
||||||
|
Limits lastXLimits;
|
||||||
base::flat_map<int, QPointF> points;
|
base::flat_map<int, QPointF> points;
|
||||||
};
|
};
|
||||||
SelectedPoints _selectedPoints;
|
SelectedPoints _selectedPoints;
|
||||||
|
|
|
@ -94,7 +94,8 @@ void StackChartView::paintSelectedXIndex(
|
||||||
const Limits &xPercentageLimits,
|
const Limits &xPercentageLimits,
|
||||||
const Limits &heightLimits,
|
const Limits &heightLimits,
|
||||||
const QRect &rect,
|
const QRect &rect,
|
||||||
int selectedXIndex) {
|
int selectedXIndex,
|
||||||
|
float64 progress) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void StackChartView::setEnabled(int id, bool enabled, crl::time now) {
|
void StackChartView::setEnabled(int id, bool enabled, crl::time now) {
|
||||||
|
|
|
@ -39,7 +39,8 @@ public:
|
||||||
const Limits &xPercentageLimits,
|
const Limits &xPercentageLimits,
|
||||||
const Limits &heightLimits,
|
const Limits &heightLimits,
|
||||||
const QRect &rect,
|
const QRect &rect,
|
||||||
int selectedXIndex) override;
|
int selectedXIndex,
|
||||||
|
float64 progress) override;
|
||||||
|
|
||||||
void setEnabled(int id, bool enabled, crl::time now) override;
|
void setEnabled(int id, bool enabled, crl::time now) override;
|
||||||
[[nodiscard]] bool isEnabled(int id) const override;
|
[[nodiscard]] bool isEnabled(int id) const override;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user