profile: redo animation of labels and grid lines

The old animation was weird: it would reuse the labels
based on the index, not on the value. Thus, with the
new scaling code, sometimes there was no animation at all,
if the value, but not the position changed.

Consider the values instead and let labels appear/disappear.
This makes things slightly more complex.

While changing this code, create our own animation-class.
Thus, we can avoid having the dive axes being QObjects.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2021-12-02 23:53:17 +01:00 committed by Dirk Hohndel
parent afb0978460
commit 5c5c0c4880
4 changed files with 216 additions and 106 deletions

View file

@ -2,24 +2,18 @@
#ifndef DIVECARTESIANAXIS_H
#define DIVECARTESIANAXIS_H
#include <QObject>
#include <memory>
#include <QGraphicsLineItem>
#include <QPen>
#include "core/color.h"
#include "core/units.h"
class ProfileScene;
class QPropertyAnimation;
class DiveTextItem;
class DiveLineItem;
class DivePlotDataModel;
class DiveCartesianAxis : public QObject, public QGraphicsLineItem {
Q_OBJECT
Q_PROPERTY(QLineF line WRITE setLine READ line)
Q_PROPERTY(QPointF pos WRITE setPos READ pos)
Q_PROPERTY(qreal x WRITE setX READ x)
Q_PROPERTY(qreal y WRITE setY READ y)
class DiveCartesianAxis : public QGraphicsLineItem {
private:
bool printMode;
public:
@ -36,8 +30,8 @@ public:
double minimum() const;
double maximum() const;
std::pair<double, double> screenMinMax() const;
qreal valueAt(const QPointF &p) const;
qreal posAtValue(qreal value) const;
double valueAt(const QPointF &p) const;
double posAtValue(double value) const;
void setPosition(const QRectF &rect);
double screenPosition(double pos) const; // 0.0 = begin, 1.0 = end of axis, independent of represented values
double pointInRange(double pos) const; // Point on screen is in range of axis
@ -47,11 +41,23 @@ public:
double width() const; // only for vertical axes
double height() const; // only for horizontal axes
double horizontalOverhang() const; // space needed for labels of horizontal axes
void anim(double fraction);
// The minimum space between two labels on the plot in seconds
int getMinLabelDistance(const DiveCartesianAxis &timeAxis) const;
private:
struct Label {
double value;
double opacityStart;
double opacityEnd; // If 0.0, label will be removed at end of animation
QPointF labelPosStart;
QPointF labelPosEnd;
QLineF lineStart;
QLineF lineEnd;
std::unique_ptr<DiveTextItem> label;
std::unique_ptr<DiveLineItem> line;
};
Position position;
bool inverted; // Top-to-bottom or right-to-left axis.
int fractionalDigits;
@ -59,9 +65,13 @@ private:
QPen gridPen;
QColor textColor;
ProfileScene &scene;
double posAtValue(double value, double max, double min) const;
QPointF labelPos(double pos) const;
QLineF linePos(double pos) const;
void updateLabel(Label &label, double opacityEnd, double pos) const;
Label createLabel(double value, double pos, double dataMinOld, double dataMaxOld, int animSpeed);
QString textForValue(double value) const;
QList<DiveTextItem *> labels;
QList<DiveLineItem *> lines;
std::vector<Label> labels;
double dataMin, dataMax;
double min, max;
bool textVisibility;
@ -80,8 +90,8 @@ private:
double from(double y) const;
} transform;
void updateLabels(int numTicks, double firstPosScreen, double firstValue, double stepScreen, double stepValue, int animSpeed);
void updateLines(int numTicks, double firstPosScreen, double stepScreen, int animSpeed);
void updateLabels(int numTicks, double firstPosScreen, double firstValue, double stepScreen, double stepValue,
int animSpeed, double dataMinOld, double dataMaxOld);
};
#endif // DIVECARTESIANAXIS_H