1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-10-07 07:13:21 +02:00
GPXSee/src/GUI/axisitem.cpp

193 lines
4.7 KiB
C++
Raw Normal View History

2015-10-05 01:43:48 +02:00
#include <cmath>
#include <QPainter>
2018-10-11 18:19:35 +02:00
#include "common/util.h"
#include "font.h"
2015-10-05 01:43:48 +02:00
#include "axisitem.h"
2016-09-25 18:08:39 +02:00
#define AXIS_WIDTH 1
2015-10-05 01:43:48 +02:00
#define TICK 6
#define PADDING 6
#define XTICKS 15
#define YTICKS 10
2018-05-18 20:08:52 +02:00
class Ticks
{
public:
2018-05-24 23:19:30 +02:00
Ticks(double minValue, double maxValue, int maxCount);
2018-05-18 20:08:52 +02:00
int count() const {return ((int)((_max - _min) / _d)) + 1;}
double val(int i) const {return _min + i * _d;}
double min() const {return _min;}
double max() const {return _max;}
private:
double _min;
double _max;
double _d;
2015-10-05 01:43:48 +02:00
};
2018-05-24 23:19:30 +02:00
Ticks::Ticks(double minValue, double maxValue, int maxCount)
2015-10-05 01:43:48 +02:00
{
double range = niceNum(maxValue - minValue, false);
_d = niceNum(range / maxCount, true);
2018-05-24 23:19:30 +02:00
_min = ceil(minValue / _d) * _d;
_max = floor(maxValue / _d) * _d;
2015-10-05 01:43:48 +02:00
}
AxisItem::AxisItem(Type type, QGraphicsItem *parent)
: QGraphicsItem(parent), _locale(QLocale::system())
2015-10-05 01:43:48 +02:00
{
_type = type;
_size = 0;
2016-09-11 17:15:23 +02:00
2018-05-18 01:38:33 +02:00
_font.setPixelSize(FONT_SIZE);
_font.setFamily(FONT_FAMILY);
2015-10-05 01:43:48 +02:00
}
2016-03-27 13:23:00 +02:00
void AxisItem::setRange(const RangeF &range)
2015-10-05 01:43:48 +02:00
{
2016-04-01 21:20:23 +02:00
prepareGeometryChange();
2015-10-05 01:43:48 +02:00
_range = range;
2018-05-18 20:08:52 +02:00
QFontMetrics fm(_font);
Ticks ticks(_range.min(), _range.max(), (_type == X) ? XTICKS : YTICKS);
_ticks = QVector<Tick>(ticks.count());
for (int i = 0; i < ticks.count(); i++) {
Tick &t = _ticks[i];
t.value = ticks.val(i);
t.boundingBox = fm.tightBoundingRect(_locale.toString(t.value));
2018-05-18 20:08:52 +02:00
}
2015-10-05 01:43:48 +02:00
updateBoundingRect();
2016-09-12 02:01:13 +02:00
update();
2015-10-05 01:43:48 +02:00
}
void AxisItem::setSize(qreal size)
{
2016-04-01 21:20:23 +02:00
prepareGeometryChange();
2015-10-05 01:43:48 +02:00
_size = size;
updateBoundingRect();
2016-09-12 02:01:13 +02:00
update();
2015-10-05 01:43:48 +02:00
}
void AxisItem::setLabel(const QString& label)
{
2016-04-01 21:20:23 +02:00
prepareGeometryChange();
2018-05-18 20:08:52 +02:00
QFontMetrics fm(_font);
2015-10-05 01:43:48 +02:00
_label = label;
2018-05-18 20:08:52 +02:00
_labelBB = fm.tightBoundingRect(label);
2015-10-05 01:43:48 +02:00
updateBoundingRect();
2016-09-12 02:01:13 +02:00
update();
2015-10-05 01:43:48 +02:00
}
void AxisItem::updateBoundingRect()
{
2018-05-18 01:38:33 +02:00
QFontMetrics fm(_font);
2018-05-18 20:08:52 +02:00
QRect es = _ticks.isEmpty() ? QRect() : _ticks.last().boundingBox;
QRect ss = _ticks.isEmpty() ? QRect() : _ticks.first().boundingBox;
QRect ls(_labelBB);
2015-10-05 01:43:48 +02:00
if (_type == X) {
2018-05-18 20:08:52 +02:00
_boundingRect = QRectF(-ss.width()/2, -TICK/2, _size + es.width()/2
+ ss.width()/2, ls.height() + es.height() - fm.descent() + TICK
+ 2*PADDING + 1);
2015-10-05 01:43:48 +02:00
} else {
2016-03-22 06:48:49 +01:00
int mtw = 0;
2018-05-18 20:08:52 +02:00
for (int i = 0; i < _ticks.count(); i++)
mtw = qMax(_ticks.at(i).boundingBox.width(), mtw);
2016-09-12 23:53:14 +02:00
_boundingRect = QRectF(-(ls.height() + mtw + 2*PADDING + TICK/2),
-(_size + es.height()/2 + fm.descent()), ls.height() + mtw + 2*PADDING
2015-10-05 01:43:48 +02:00
+ TICK, _size + es.height()/2 + fm.descent() + ss.height()/2);
}
}
void AxisItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
2018-05-18 01:38:33 +02:00
QFontMetrics fm(_font);
QRect ts;
2015-10-05 01:43:48 +02:00
2016-10-17 23:14:07 +02:00
painter->setRenderHint(QPainter::Antialiasing, false);
2018-05-18 01:38:33 +02:00
painter->setFont(_font);
2019-01-04 19:21:05 +01:00
QPen pen(painter->pen());
pen.setWidth(AXIS_WIDTH);
painter->setPen(pen);
2015-10-05 01:43:48 +02:00
if (_type == X) {
painter->drawLine(0, 0, _size, 0);
2018-05-18 20:08:52 +02:00
for (int i = 0; i < _ticks.count(); i++) {
qreal val = _ticks.at(i).value;
ts = _ticks.at(i).boundingBox;
2015-10-05 01:43:48 +02:00
2018-05-18 20:08:52 +02:00
painter->drawLine((_size/_range.size()) * (val - _range.min()),
TICK/2, (_size/_range.size()) * (val - _range.min()), -TICK/2);
painter->drawText(((_size/_range.size()) * (val - _range.min()))
- (ts.width()/2), ts.height() + TICK/2 + PADDING,
_locale.toString(val));
2015-10-05 01:43:48 +02:00
}
2018-05-18 20:08:52 +02:00
painter->drawText(_size/2 - _labelBB.width()/2, _labelBB.height()
+ ts.height() - 2*fm.descent() + TICK/2 + 2*PADDING, _label);
2015-10-05 01:43:48 +02:00
} else {
painter->drawLine(0, 0, 0, -_size);
2016-03-22 06:48:49 +01:00
int mtw = 0;
2018-05-18 20:08:52 +02:00
for (int i = 0; i < _ticks.count(); i++) {
qreal val = _ticks.at(i).value;
ts = _ticks.at(i).boundingBox;
2016-03-22 06:48:49 +01:00
mtw = qMax(ts.width(), mtw);
2018-05-18 20:08:52 +02:00
painter->drawLine(TICK/2, -((_size/_range.size())
* (val - _range.min())), -TICK/2, -((_size/_range.size())
* (val - _range.min())));
painter->drawText(-(ts.width() + PADDING + TICK/2),
-((_size/_range.size()) * (val - _range.min())) + (ts.height()/2),
_locale.toString(val));
2015-10-05 01:43:48 +02:00
}
painter->rotate(-90);
2018-05-18 20:08:52 +02:00
painter->drawText(_size/2 - _labelBB.width()/2, -(mtw + 2*PADDING
+ TICK/2), _label);
2015-10-05 01:43:48 +02:00
painter->rotate(90);
}
/*
painter->setPen(Qt::red);
painter->drawRect(boundingRect());
*/
}
2016-03-19 17:24:53 +01:00
QSizeF AxisItem::margin() const
2015-10-05 01:43:48 +02:00
{
2018-05-18 20:08:52 +02:00
QFontMetrics fm(_font);
QRect es = _ticks.isEmpty() ? QRect() : _ticks.last().boundingBox;
2015-10-05 01:43:48 +02:00
if (_type == X) {
2018-05-18 20:08:52 +02:00
return QSizeF(es.width()/2, _labelBB.height() + es.height()
- fm.descent() + TICK/2 + 2*PADDING);
2015-10-05 01:43:48 +02:00
} else {
2016-03-22 06:48:49 +01:00
int mtw = 0;
2018-05-18 20:08:52 +02:00
for (int i = 0; i < _ticks.count(); i++)
mtw = qMax(_ticks.at(i).boundingBox.width(), mtw);
2016-03-22 06:48:49 +01:00
2018-05-18 20:08:52 +02:00
return QSizeF(_labelBB.height() -fm.descent() + mtw + 2*PADDING
2015-10-05 01:43:48 +02:00
+ TICK/2, es.height()/2 + fm.descent());
}
}
2016-10-17 23:14:07 +02:00
QList<qreal> AxisItem::ticks() const
{
QList<qreal> list;
2018-05-18 20:08:52 +02:00
for (int i = 0; i < _ticks.count(); i++)
list.append(((_size/_range.size()) * (_ticks.at(i).value
2016-10-17 23:14:07 +02:00
- _range.min())));
return list;
}