mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-30 22:20:21 +00:00
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:
parent
e1c0cace95
commit
b1c0d42408
3 changed files with 43 additions and 12 deletions
|
@ -3,6 +3,7 @@
|
||||||
#include "statscolors.h"
|
#include "statscolors.h"
|
||||||
#include "zvalues.h"
|
#include "zvalues.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <QFontMetrics>
|
#include <QFontMetrics>
|
||||||
#include <QPen>
|
#include <QPen>
|
||||||
|
|
||||||
|
@ -18,7 +19,8 @@ Legend::Legend(StatsView &view, const std::vector<QString> &names) :
|
||||||
ChartRectItem(view, ChartZValue::Legend,
|
ChartRectItem(view, ChartZValue::Legend,
|
||||||
QPen(legendBorderColor, legendBorderSize), QBrush(legendColor), legendBoxBorderRadius),
|
QPen(legendBorderColor, legendBorderSize), QBrush(legendColor), legendBoxBorderRadius),
|
||||||
displayedItems(0), width(0.0), height(0.0),
|
displayedItems(0), width(0.0), height(0.0),
|
||||||
font(QFont()) // Make configurable
|
font(QFont()), // Make configurable
|
||||||
|
posInitialized(false)
|
||||||
{
|
{
|
||||||
entries.reserve(names.size());
|
entries.reserve(names.size());
|
||||||
QFontMetrics fm(font);
|
QFontMetrics fm(font);
|
||||||
|
@ -103,7 +105,38 @@ void Legend::resize()
|
||||||
painter->drawText(rect, entries[i].name);
|
painter->drawText(rect, entries[i].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For now, place the legend in the top right corner.
|
if (!posInitialized) {
|
||||||
QPointF pos(size.width() - width - 10.0, 10.0);
|
// At first, place in top right corner
|
||||||
setPos(pos);
|
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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ class Legend : public ChartRectItem {
|
||||||
public:
|
public:
|
||||||
Legend(StatsView &view, const std::vector<QString> &names);
|
Legend(StatsView &view, const std::vector<QString> &names);
|
||||||
void resize(); // called when the chart size changes.
|
void resize(); // called when the chart size changes.
|
||||||
|
void setPos(QPointF pos); // Attention: not virtual - always call on this class.
|
||||||
private:
|
private:
|
||||||
// Each entry is a text besides a rectangle showing the color
|
// Each entry is a text besides a rectangle showing the color
|
||||||
struct Entry {
|
struct Entry {
|
||||||
|
@ -28,6 +29,10 @@ private:
|
||||||
double width;
|
double width;
|
||||||
double height;
|
double height;
|
||||||
QFont font;
|
QFont font;
|
||||||
|
// The position is specified with respect to the center and in relative terms
|
||||||
|
// with respect to the canvas.
|
||||||
|
QPointF centerPos;
|
||||||
|
bool posInitialized;
|
||||||
int fontHeight;
|
int fontHeight;
|
||||||
std::vector<Entry> entries;
|
std::vector<Entry> entries;
|
||||||
void hide();
|
void hide();
|
||||||
|
|
|
@ -236,14 +236,7 @@ void StatsView::mouseMoveEvent(QMouseEvent *event)
|
||||||
QSizeF sceneSize = size();
|
QSizeF sceneSize = size();
|
||||||
if (sceneSize.width() <= 1.0 || sceneSize.height() <= 1.0)
|
if (sceneSize.width() <= 1.0 || sceneSize.height() <= 1.0)
|
||||||
return;
|
return;
|
||||||
QPointF pos = event->pos() - dragStartMouse + dragStartItem;;
|
draggedItem->setPos(event->pos() - dragStartMouse + dragStartItem);
|
||||||
QSizeF itemSize = draggedItem->getRect().size();
|
|
||||||
double widthHalf = floor(itemSize.width() / 2);
|
|
||||||
double heightHalf = floor(itemSize.height() / 2);
|
|
||||||
QSizeF itemSizeHalf(floor(itemSize.width() / 2), floor(itemSize.height() / 2));
|
|
||||||
QPointF sanitizedPos(std::clamp(pos.x(), -widthHalf, sceneSize.width() - widthHalf - 1.0),
|
|
||||||
std::clamp(pos.y(), -heightHalf, sceneSize.height() - heightHalf - 1.0));
|
|
||||||
draggedItem->setPos(sanitizedPos);
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue