diff options
-rw-r--r-- | stats/legend.cpp | 41 | ||||
-rw-r--r-- | stats/legend.h | 5 | ||||
-rw-r--r-- | stats/statsview.cpp | 9 |
3 files changed, 43 insertions, 12 deletions
diff --git a/stats/legend.cpp b/stats/legend.cpp index 590de21b0..d0a5c19b1 100644 --- a/stats/legend.cpp +++ b/stats/legend.cpp @@ -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()); } diff --git a/stats/legend.h b/stats/legend.h index 1e38f705a..fb88920bd 100644 --- a/stats/legend.h +++ b/stats/legend.h @@ -15,6 +15,7 @@ class Legend : public ChartRectItem { public: Legend(StatsView &view, const std::vector<QString> &names); void resize(); // called when the chart size changes. + void setPos(QPointF pos); // Attention: not virtual - always call on this class. private: // Each entry is a text besides a rectangle showing the color struct Entry { @@ -28,6 +29,10 @@ private: double width; double height; 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; std::vector<Entry> entries; void hide(); diff --git a/stats/statsview.cpp b/stats/statsview.cpp index 983b128fe..f07b00896 100644 --- a/stats/statsview.cpp +++ b/stats/statsview.cpp @@ -236,14 +236,7 @@ void StatsView::mouseMoveEvent(QMouseEvent *event) QSizeF sceneSize = size(); if (sceneSize.width() <= 1.0 || sceneSize.height() <= 1.0) return; - QPointF pos = 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); + draggedItem->setPos(event->pos() - dragStartMouse + dragStartItem); update(); } |