84 lines
3.3 KiB
C++
84 lines
3.3 KiB
C++
#include "axistag.h"
|
|
|
|
AxisTag::AxisTag(QCPAxis* parentAxis) :
|
|
QObject(parentAxis),
|
|
mAxis(parentAxis)
|
|
{
|
|
// The dummy tracer serves here as an invisible anchor which always sticks to the right side of
|
|
// the axis rect
|
|
mDummyTracer = new QCPItemTracer(mAxis->parentPlot());
|
|
mDummyTracer->setVisible(false);
|
|
mDummyTracer->position->setTypeX(QCPItemPosition::ptAxisRectRatio);
|
|
mDummyTracer->position->setTypeY(QCPItemPosition::ptPlotCoords);
|
|
mDummyTracer->position->setAxisRect(mAxis->axisRect());
|
|
mDummyTracer->position->setAxes(0, mAxis);
|
|
mDummyTracer->position->setCoords(1, 0);
|
|
|
|
// the arrow end (head) is set to move along with the dummy tracer by setting it as its parent
|
|
// anchor. Its coordinate system (setCoords) is thus pixels, and this is how the needed horizontal
|
|
// offset for the tag of the second y axis is achieved. This horizontal offset gets dynamically
|
|
// updated in AxisTag::updatePosition. the arrow "start" is simply set to have the "end" as parent
|
|
// anchor. It is given a horizontal offset to the right, which results in a 15 pixel long arrow.
|
|
mArrow = new QCPItemLine(mAxis->parentPlot());
|
|
mArrow->setLayer("overlay");
|
|
mArrow->setClipToAxisRect(false);
|
|
mArrow->setHead(QCPLineEnding::esSpikeArrow);
|
|
mArrow->end->setParentAnchor(mDummyTracer->position);
|
|
mArrow->start->setParentAnchor(mArrow->end);
|
|
mArrow->start->setCoords(15, 0);
|
|
|
|
// The text label is anchored at the arrow start (tail) and has its "position" aligned at the
|
|
// left, and vertically centered to the text label box.
|
|
mLabel = new QCPItemText(mAxis->parentPlot());
|
|
mLabel->setLayer("overlay");
|
|
mLabel->setClipToAxisRect(false);
|
|
mLabel->setPadding(QMargins(3, 0, 3, 0));
|
|
mLabel->setBrush(QBrush(Qt::white));
|
|
mLabel->setPen(QPen(Qt::blue));
|
|
mLabel->setPositionAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
|
mLabel->position->setParentAnchor(mArrow->start);
|
|
}
|
|
|
|
AxisTag::~AxisTag()
|
|
{
|
|
if (mDummyTracer)
|
|
mDummyTracer->parentPlot()->removeItem(mDummyTracer);
|
|
if (mArrow)
|
|
mArrow->parentPlot()->removeItem(mArrow);
|
|
if (mLabel)
|
|
mLabel->parentPlot()->removeItem(mLabel);
|
|
}
|
|
|
|
void AxisTag::setPen(const QPen& pen)
|
|
{
|
|
mArrow->setPen(pen);
|
|
mLabel->setPen(pen);
|
|
}
|
|
|
|
void AxisTag::setBrush(const QBrush& brush)
|
|
{
|
|
mLabel->setBrush(brush);
|
|
}
|
|
|
|
void AxisTag::setText(const QString& text)
|
|
{
|
|
mLabel->setText(text);
|
|
}
|
|
|
|
void AxisTag::updatePosition(double value)
|
|
{
|
|
// since both the arrow and the text label are chained to the dummy tracer (via anchor
|
|
// parent-child relationships) it is sufficient to update the dummy tracer coordinates. The
|
|
// Horizontal coordinate type was set to ptAxisRectRatio so to keep it aligned at the right side
|
|
// of the axis rect, it is always kept at 1. The vertical coordinate type was set to
|
|
// ptPlotCoordinates of the passed parent axis, so the vertical coordinate is set to the new
|
|
// value.
|
|
mDummyTracer->position->setCoords(1, value);
|
|
|
|
// We want the arrow head to be at the same horizontal position as the axis backbone, even if
|
|
// the axis has a certain offset from the axis rect border (like the added second y axis). Thus we
|
|
// set the horizontal pixel position of the arrow end (head) to the axis offset (the pixel
|
|
// distance to the axis rect border). This works because the parent anchor of the arrow end is
|
|
// the dummy tracer, which, as described earlier, is tied to the right axis rect border.
|
|
mArrow->end->setCoords(mAxis->offset(), 0);
|
|
} |