2015-10-05 01:43:48 +02:00
|
|
|
#include <cmath>
|
|
|
|
#include <QPainter>
|
2015-10-17 01:33:02 +02:00
|
|
|
#include "config.h"
|
2016-07-25 19:32:36 +02:00
|
|
|
#include "misc.h"
|
2015-10-05 01:43:48 +02:00
|
|
|
#include "axisitem.h"
|
|
|
|
|
|
|
|
|
|
|
|
#define TICK 6
|
|
|
|
#define PADDING 6
|
|
|
|
#define XTICKS 15
|
|
|
|
#define YTICKS 10
|
|
|
|
|
|
|
|
struct Label {
|
|
|
|
double min;
|
|
|
|
double max;
|
|
|
|
double d;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct Label label(double min, double max, int ticks)
|
|
|
|
{
|
|
|
|
double range;
|
|
|
|
struct Label l;
|
|
|
|
|
|
|
|
range = niceNum(max - min, 0);
|
|
|
|
l.d = niceNum(range / ticks, 1);
|
|
|
|
l.min = ceil(min / l.d) * l.d;
|
|
|
|
l.max = floor(max / l.d) * l.d;
|
|
|
|
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-10-17 01:33:02 +02:00
|
|
|
AxisItem::AxisItem(Type type, QGraphicsItem *parent) : QGraphicsItem(parent)
|
2015-10-05 01:43:48 +02:00
|
|
|
{
|
|
|
|
_type = type;
|
|
|
|
_size = 0;
|
2016-09-11 17:15:23 +02:00
|
|
|
|
|
|
|
setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
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;
|
|
|
|
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();
|
2015-10-05 01:43:48 +02:00
|
|
|
_label = label;
|
|
|
|
updateBoundingRect();
|
2016-09-12 02:01:13 +02:00
|
|
|
update();
|
2015-10-05 01:43:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void AxisItem::updateBoundingRect()
|
|
|
|
{
|
|
|
|
QFont font;
|
|
|
|
font.setPixelSize(FONT_SIZE);
|
|
|
|
font.setFamily(FONT_FAMILY);
|
|
|
|
QFontMetrics fm(font);
|
|
|
|
QRect ss, es, ls;
|
|
|
|
struct Label l;
|
|
|
|
|
|
|
|
|
2016-03-27 13:23:00 +02:00
|
|
|
l = label(_range.min(), _range.max(), (_type == X) ? XTICKS : YTICKS);
|
2015-10-05 01:43:48 +02:00
|
|
|
es = fm.tightBoundingRect(QString::number(l.max));
|
|
|
|
ss = fm.tightBoundingRect(QString::number(l.min));
|
|
|
|
ls = fm.tightBoundingRect(_label);
|
|
|
|
|
|
|
|
if (_type == X) {
|
|
|
|
_boundingRect = QRectF(-ss.width()/2, -TICK/2,
|
|
|
|
_size + es.width()/2 + ss.width()/2,
|
|
|
|
ls.height() + es.height() - fm.descent() + TICK + 2*PADDING);
|
|
|
|
} else {
|
2016-03-22 06:48:49 +01:00
|
|
|
int mtw = 0;
|
|
|
|
QRect ts;
|
|
|
|
qreal val;
|
|
|
|
|
|
|
|
for (int i = 0; i < ((l.max - l.min) / l.d) + 1; i++) {
|
|
|
|
val = l.min + i * l.d;
|
|
|
|
QString str = QString::number(val);
|
|
|
|
ts = fm.tightBoundingRect(str);
|
|
|
|
mtw = qMax(ts.width(), mtw);
|
|
|
|
}
|
|
|
|
|
|
|
|
_boundingRect = QRectF(-(ls.height() + mtw + 2*PADDING
|
2015-10-05 01:43:48 +02:00
|
|
|
- fm.descent() + TICK/2), -(_size + es.height()/2
|
2016-03-23 09:47:02 +01:00
|
|
|
+ fm.descent()), ls.height() -fm.descent() + 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);
|
|
|
|
QFont font;
|
|
|
|
font.setPixelSize(FONT_SIZE);
|
|
|
|
font.setFamily(FONT_FAMILY);
|
|
|
|
QFontMetrics fm(font);
|
|
|
|
QRect ts, ls;
|
|
|
|
struct Label l;
|
2016-03-27 13:23:00 +02:00
|
|
|
qreal range = _range.size();
|
2015-10-05 01:43:48 +02:00
|
|
|
qreal val;
|
|
|
|
|
|
|
|
|
2016-01-14 00:37:51 +01:00
|
|
|
painter->setFont(font);
|
|
|
|
|
2015-10-05 01:43:48 +02:00
|
|
|
ls = fm.tightBoundingRect(_label);
|
|
|
|
|
|
|
|
if (_type == X) {
|
|
|
|
painter->drawLine(0, 0, _size, 0);
|
|
|
|
|
2016-03-27 13:23:00 +02:00
|
|
|
l = label(_range.min(), _range.max(), XTICKS);
|
2015-10-05 01:43:48 +02:00
|
|
|
for (int i = 0; i < ((l.max - l.min) / l.d) + 1; i++) {
|
|
|
|
val = l.min + i * l.d;
|
|
|
|
QString str = QString::number(val);
|
|
|
|
|
2016-03-27 13:23:00 +02:00
|
|
|
painter->drawLine((_size/range) * (val - _range.min()), TICK/2,
|
|
|
|
(_size/range) * (val - _range.min()), -TICK/2);
|
2015-10-05 01:43:48 +02:00
|
|
|
ts = fm.tightBoundingRect(str);
|
2016-03-27 13:23:00 +02:00
|
|
|
painter->drawText(((_size/range) * (val - _range.min()))
|
2015-10-05 01:43:48 +02:00
|
|
|
- (ts.width()/2), ts.height() + TICK/2 + PADDING, str);
|
|
|
|
}
|
|
|
|
|
|
|
|
painter->drawText(_size/2 - ls.width()/2, ls.height() + ts.height()
|
|
|
|
- 2*fm.descent() + TICK/2 + 2*PADDING, _label);
|
|
|
|
} else {
|
|
|
|
painter->drawLine(0, 0, 0, -_size);
|
|
|
|
|
2016-03-27 13:23:00 +02:00
|
|
|
l = label(_range.min(), _range.max(), YTICKS);
|
2016-03-22 06:48:49 +01:00
|
|
|
int mtw = 0;
|
2015-10-05 01:43:48 +02:00
|
|
|
for (int i = 0; i < ((l.max - l.min) / l.d) + 1; i++) {
|
|
|
|
val = l.min + i * l.d;
|
|
|
|
QString str = QString::number(val);
|
|
|
|
|
2016-03-27 13:23:00 +02:00
|
|
|
painter->drawLine(TICK/2, -((_size/range) * (val - _range.min())),
|
|
|
|
-TICK/2, -((_size/range) * (val - _range.min())));
|
2015-10-05 01:43:48 +02:00
|
|
|
ts = fm.tightBoundingRect(str);
|
2016-03-22 06:48:49 +01:00
|
|
|
mtw = qMax(ts.width(), mtw);
|
2015-10-05 01:43:48 +02:00
|
|
|
painter->drawText(-(ts.width() + PADDING + TICK/2), -((_size/range)
|
2016-03-27 13:23:00 +02:00
|
|
|
* (val - _range.min())) + (ts.height()/2), str);
|
2015-10-05 01:43:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
painter->rotate(-90);
|
2016-03-22 06:48:49 +01:00
|
|
|
painter->drawText(_size/2 - ls.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
|
|
|
{
|
|
|
|
QFont font;
|
|
|
|
font.setPixelSize(FONT_SIZE);
|
|
|
|
QFontMetrics fm(font);
|
|
|
|
QRect ss, es, ls;
|
|
|
|
struct Label l;
|
|
|
|
|
|
|
|
|
2016-03-27 13:23:00 +02:00
|
|
|
l = label(_range.min(), _range.max(), (_type == X) ? XTICKS : YTICKS);
|
2015-10-05 01:43:48 +02:00
|
|
|
es = fm.tightBoundingRect(QString::number(l.max));
|
|
|
|
ss = fm.tightBoundingRect(QString::number(l.min));
|
|
|
|
ls = fm.tightBoundingRect(_label);
|
|
|
|
|
|
|
|
if (_type == X) {
|
|
|
|
return QSizeF(es.width()/2,
|
|
|
|
ls.height() + es.height() - fm.descent() + TICK/2 + 2*PADDING);
|
|
|
|
} else {
|
2016-03-22 06:48:49 +01:00
|
|
|
int mtw = 0;
|
|
|
|
QRect ts;
|
|
|
|
qreal val;
|
|
|
|
|
|
|
|
for (int i = 0; i < ((l.max - l.min) / l.d) + 1; i++) {
|
|
|
|
val = l.min + i * l.d;
|
|
|
|
QString str = QString::number(val);
|
|
|
|
ts = fm.tightBoundingRect(str);
|
|
|
|
mtw = qMax(ts.width(), mtw);
|
|
|
|
}
|
|
|
|
|
|
|
|
return QSizeF(ls.height() -fm.descent() + mtw + 2*PADDING
|
2015-10-05 01:43:48 +02:00
|
|
|
+ TICK/2, es.height()/2 + fm.descent());
|
|
|
|
}
|
|
|
|
}
|