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