summaryrefslogtreecommitdiffstats
path: root/stats/statsaxis.h
blob: 02662ddd94bbb3ea2bc1a5e8b9705837e6094776 (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
117
118
119
120
121
122
123
124
// SPDX-License-Identifier: GPL-2.0
#ifndef STATS_AXIS_H
#define STATS_AXIS_H

#include "chartitem.h"
#include "statshelper.h"

#include <memory>
#include <vector>
#include <QFont>

class StatsView;
class ChartLineItem;
class QFontMetrics;

// The labels and the title of the axis are rendered into a pixmap.
// The ticks and the baseline are realized as individual ChartLineItems.
class StatsAxis : public ChartPixmapItem {
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(StatsView &view, const QString &title, bool horizontal, bool labelsBetweenTicks);

	ChartItemPtr<ChartLineItem> line;
	QString title;
	double titleWidth;

	struct Label {
		QString label;
		int width;
		double pos;
	};
	std::vector<Label> labels;
	void addLabel(const QFontMetrics &fm, const QString &label, double pos);
	virtual void updateLabels() = 0;
	virtual std::pair<QString, QString> getFirstLastLabel() const = 0;

	struct Tick {
		ChartItemPtr<ChartLineItem> item;
		double pos;
	};
	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;
	double size;			// width for horizontal, height for vertical
	double zeroOnScreen;
	QPointF offset;			// Offset of the label and title pixmap with respect to the (0,0) position.
	double min, max;
	double labelWidth;		// Maximum width of labels
private:
	double titleSpace() const;	// Space needed for title
};

class ValueAxis : public StatsAxis {
public:
	ValueAxis(StatsView &view, 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(StatsView &view, 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(StatsView &view, 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(StatsView &view, 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(StatsView &view, const QString &title, double from, double to, bool horizontal);
};

#endif