summaryrefslogtreecommitdiffstats
path: root/stats/statsaxis.h
blob: 9d46f753a73f5a96c0e0f9be5ceb4a162ce66ad3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// SPDX-License-Identifier: GPL-2.0
#ifndef STATS_AXIS_H
#define STATS_AXIS_H

#include <memory>
#include <vector>
#include <QFont>
#include <QGraphicsSimpleTextItem>
#include <QGraphicsLineItem>

class QGraphicsScene;

class StatsAxis : public QGraphicsLineItem {
public:
	virtual ~StatsAxis();
	// Returns minimum and maximum of shown range, not of data points.
	std::pair<double, double> minMax() const;
	std::pair<double, double> minMaxScreen() const; // minimum and maximum in screen coordinates
	std::pair<double, double> horizontalOverhang() const; // space that labels peak out in horizontal axes

	double width() const;		// Only supported by vertical axes. Only valid after setSize().
	double height() const;		// Only supported for horizontal axes. Always valid.
	void setSize(double size);	// Width for horizontal and height for vertical.
	void setPos(QPointF pos);	// Must be called after setSize().
	void setRange(double, double);

	// Map x (horizontal) or y (vertical) coordinate to or from screen coordinate
	double toScreen(double) const;
	double toValue(double) const;

	std::vector<double> ticksPositions() const; // Positions in screen coordinates
protected:
	StatsAxis(const QString &title, bool horizontal, bool labelsBetweenTicks);

	struct Label {
		std::unique_ptr<QGraphicsSimpleTextItem> label;
		double pos;
		Label(const QString &name, double pos, QGraphicsScene *scene, const QFont &font);
	};
	std::vector<Label> labels;
	void addLabel(const QString &label, double pos);
	virtual void updateLabels() = 0;
	virtual std::pair<QString, QString> getFirstLastLabel() const = 0;

	struct Tick {
		std::unique_ptr<QGraphicsLineItem> item;
		double pos;
		Tick(double pos, QGraphicsScene *scene);
	};
	std::vector<Tick> ticks;
	void addTick(double pos);

	int guessNumTicks(const std::vector<QString> &strings) const;
	bool horizontal;
	bool labelsBetweenTicks;	// When labels are between ticks, they can be moved closer to the axis

	QFont labelFont, titleFont;
	std::unique_ptr<QGraphicsSimpleTextItem> title;
	double size;			// width for horizontal, height for vertical
	double zeroOnScreen;
	double min, max;
	double labelWidth;		// Maximum width of labels
private:
	double titleSpace() const;	// Space needed for title
};

class ValueAxis : public StatsAxis {
public:
	ValueAxis(const QString &title, double min, double max, int decimals, bool horizontal);
private:
	double min, max;
	int decimals;
	void updateLabels() override;
	std::pair<QString, QString> getFirstLastLabel() const override;
};

class CountAxis : public ValueAxis {
public:
	CountAxis(const QString &title, int count, bool horizontal);
private:
	int count;
	void updateLabels() override;
	std::pair<QString, QString> getFirstLastLabel() const override;
};

class CategoryAxis : public StatsAxis {
public:
	CategoryAxis(const QString &title, const std::vector<QString> &labels, bool horizontal);
private:
	std::vector<QString> labelsText;
	void updateLabels();
	std::pair<QString, QString> getFirstLastLabel() const override;
};

struct HistogramAxisEntry {
	QString name;
	double value;
	bool recommended;
};

class HistogramAxis : public StatsAxis {
public:
	HistogramAxis(const QString &title, std::vector<HistogramAxisEntry> bin_values, bool horizontal);
private:
	void updateLabels() override;
	std::pair<QString, QString> getFirstLastLabel() const override;
	std::vector<HistogramAxisEntry> bin_values;
	int preferred_step;
};

class DateAxis : public HistogramAxis {
public:
	DateAxis(const QString &title, double from, double to, bool horizontal);
};

#endif