Merge remote-tracking branch 'weblate/master'
[GPXSee.git] / src / GUI / axisitem.cpp
bloba6ed930f20e7a3b8fae1a51153c4c8bc549c6928
1 #include <cmath>
2 #include <QPainter>
3 #include "common/util.h"
4 #include "font.h"
5 #include "axisitem.h"
8 #define AXIS_WIDTH 1
9 #define TICK 6
10 #define PADDING 6
11 #define XTICKS 15
12 #define YTICKS 10
14 class Ticks
16 public:
17 Ticks(double minValue, double maxValue, int maxCount);
19 int count() const {return ((int)((_max - _min) / _d)) + 1;}
20 double val(int i) const {return _min + i * _d;}
21 double min() const {return _min;}
22 double max() const {return _max;}
24 private:
25 double _min;
26 double _max;
27 double _d;
30 Ticks::Ticks(double minValue, double maxValue, int maxCount)
32 double range = Util::niceNum(maxValue - minValue, false);
33 _d = Util::niceNum(range / maxCount, false);
34 _min = ceil(minValue / _d) * _d;
35 _max = floor(maxValue / _d) * _d;
39 AxisItem::AxisItem(Type type, QGraphicsItem *parent)
40 : QGraphicsItem(parent), _locale(QLocale::system())
42 _type = type;
43 _size = 0;
44 _zoom = 1.0;
46 _font.setPixelSize(FONT_SIZE);
47 _font.setFamily(FONT_FAMILY);
50 void AxisItem::setRange(const RangeF &range)
52 prepareGeometryChange();
53 _range = range;
55 QFontMetrics fm(_font);
56 Ticks ticks(_range.min(), _range.max(),
57 (_type == X) ? XTICKS * _zoom : YTICKS * _zoom);
58 _ticks = QVector<Tick>(ticks.count());
60 for (int i = 0; i < ticks.count(); i++) {
61 Tick &t = _ticks[i];
62 t.value = ticks.val(i);
63 t.boundingBox = fm.tightBoundingRect(_locale.toString(t.value));
66 updateBoundingRect();
67 update();
70 void AxisItem::setSize(qreal size)
72 prepareGeometryChange();
73 _size = size;
74 updateBoundingRect();
75 update();
78 void AxisItem::updateBoundingRect()
80 QFontMetrics fm(_font);
81 QRect es = _ticks.isEmpty() ? QRect() : _ticks.last().boundingBox;
82 QRect ss = _ticks.isEmpty() ? QRect() : _ticks.first().boundingBox;
84 if (_type == X) {
85 _boundingRect = QRectF(-ss.width()/2, -TICK/2, _size + es.width()/2
86 + ss.width()/2, es.height() - 2*fm.descent() + TICK + 2*PADDING);
87 } else {
88 int mtw = 0;
89 for (int i = 0; i < _ticks.count(); i++)
90 mtw = qMax(_ticks.at(i).boundingBox.width(), mtw);
91 _boundingRect = QRectF(-(mtw + 2*PADDING + TICK/2 - fm.descent()),
92 -(_size + es.height()/2 + fm.descent()), mtw + 2*PADDING
93 + TICK - fm.descent(), _size + es.height()/2 + fm.descent()
94 + ss.height()/2);
98 void AxisItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
99 QWidget *widget)
101 Q_UNUSED(option);
102 Q_UNUSED(widget);
103 QRect ts;
105 painter->setRenderHint(QPainter::Antialiasing, false);
106 painter->setFont(_font);
107 QPen pen(painter->pen());
108 pen.setWidth(AXIS_WIDTH);
109 painter->setPen(pen);
111 if (_type == X) {
112 painter->drawLine(0, 0, _size, 0);
114 for (int i = 0; i < _ticks.count(); i++) {
115 qreal val = _ticks.at(i).value;
116 ts = _ticks.at(i).boundingBox;
118 painter->drawLine((_size/_range.size()) * (val - _range.min()),
119 TICK/2, (_size/_range.size()) * (val - _range.min()), -TICK/2);
120 painter->drawText(((_size/_range.size()) * (val - _range.min()))
121 - (ts.width()/2), ts.height() + TICK/2 + PADDING,
122 _locale.toString(val));
124 } else {
125 painter->drawLine(0, 0, 0, -_size);
127 int mtw = 0;
128 for (int i = 0; i < _ticks.count(); i++) {
129 qreal val = _ticks.at(i).value;
130 ts = _ticks.at(i).boundingBox;
131 mtw = qMax(ts.width(), mtw);
133 painter->drawLine(TICK/2, -((_size/_range.size())
134 * (val - _range.min())), -TICK/2, -((_size/_range.size())
135 * (val - _range.min())));
136 painter->drawText(-(ts.width() + PADDING + TICK/2),
137 -((_size/_range.size()) * (val - _range.min())) + (ts.height()/2),
138 _locale.toString(val));
142 //painter->setPen(Qt::red);
143 //painter->drawRect(boundingRect());
146 QSizeF AxisItem::margin() const
148 QFontMetrics fm(_font);
149 QRect es = _ticks.isEmpty() ? QRect() : _ticks.last().boundingBox;
151 if (_type == X) {
152 return QSizeF(es.width()/2, es.height() - 2*fm.descent() + TICK/2
153 + 2*PADDING);
154 } else {
155 int mtw = 0;
156 for (int i = 0; i < _ticks.count(); i++)
157 mtw = qMax(_ticks.at(i).boundingBox.width(), mtw);
159 return QSizeF(mtw + 2*PADDING + TICK/2 - fm.descent(),
160 es.height()/2 + fm.descent());
164 QList<qreal> AxisItem::ticks() const
166 QList<qreal> list;
168 for (int i = 0; i < _ticks.count(); i++)
169 list.append(((_size/_range.size()) * (_ticks.at(i).value
170 - _range.min())));
172 return list;