statistics: remember position of legend when resizing

The position of the legend was reset when resizing. This was
OK as long as the legend wasn't movable.

To avoid resetting the position, store the center position
of the legend relatively to the size of the canvas. On
resize restore the center to the same relative size.

To avoid code duplication, move the sanitizing of the
coordinates from the StatsView to the Legend.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2021-01-13 21:15:11 +01:00 committed by bstoeger
parent e1c0cace95
commit b1c0d42408
3 changed files with 43 additions and 12 deletions

View file

@ -3,6 +3,7 @@
#include "statscolors.h"
#include "zvalues.h"
#include <cmath>
#include <QFontMetrics>
#include <QPen>
@ -18,7 +19,8 @@ Legend::Legend(StatsView &view, const std::vector<QString> &names) :
ChartRectItem(view, ChartZValue::Legend,
QPen(legendBorderColor, legendBorderSize), QBrush(legendColor), legendBoxBorderRadius),
displayedItems(0), width(0.0), height(0.0),
font(QFont()) // Make configurable
font(QFont()), // Make configurable
posInitialized(false)
{
entries.reserve(names.size());
QFontMetrics fm(font);
@ -103,7 +105,38 @@ void Legend::resize()
painter->drawText(rect, entries[i].name);
}
// For now, place the legend in the top right corner.
QPointF pos(size.width() - width - 10.0, 10.0);
setPos(pos);
if (!posInitialized) {
// At first, place in top right corner
setPos(QPointF(size.width() - width - 10.0, 10.0));
posInitialized = true;
} else {
// Try to keep relative position with what it was before
setPos(QPointF(size.width() * centerPos.x() - width / 2.0,
size.height() * centerPos.y() - height / 2.0));
}
}
void Legend::setPos(QPointF newPos)
{
// Round the position to integers or horrible artifacts appear (at least on desktop)
QPointF posInt(round(newPos.x()), round(newPos.y()));
// Make sure that the center is inside the drawing area,
// so that the user can't lose the legend.
QSizeF size = sceneSize();
if (size.width() < 1.0 || size.height() < 1.0)
return;
double widthHalf = floor(width / 2.0);
double heightHalf = floor(height / 2.0);
QPointF sanitizedPos(std::clamp(posInt.x(), -widthHalf, size.width() - widthHalf - 1.0),
std::clamp(posInt.y(), -heightHalf, size.height() - heightHalf - 1.0));
// Set position
ChartRectItem::setPos(sanitizedPos);
// Remember relative position of center for next time
QPointF centerPosAbsolute(sanitizedPos.x() + width / 2.0,
sanitizedPos.y() + height / 2.0);
centerPos = QPointF(centerPosAbsolute.x() / size.width(),
centerPosAbsolute.y() / size.height());
}