diff options
Diffstat (limited to 'stats/scatterseries.cpp')
-rw-r--r-- | stats/scatterseries.cpp | 86 |
1 files changed, 17 insertions, 69 deletions
diff --git a/stats/scatterseries.cpp b/stats/scatterseries.cpp index 8e2399008..791bb81ca 100644 --- a/stats/scatterseries.cpp +++ b/stats/scatterseries.cpp @@ -1,24 +1,20 @@ // SPDX-License-Identifier: GPL-2.0 #include "scatterseries.h" +#include "chartitem.h" #include "informationbox.h" #include "statscolors.h" #include "statshelper.h" #include "statstranslations.h" #include "statsvariables.h" +#include "statsview.h" #include "zvalues.h" #include "core/dive.h" #include "core/divelist.h" #include "core/qthelper.h" -#include <QGraphicsPixmapItem> -#include <QPainter> - -static const int scatterItemDiameter = 10; -static const int scatterItemBorder = 1; - -ScatterSeries::ScatterSeries(QGraphicsScene *scene, StatsAxis *xAxis, StatsAxis *yAxis, +ScatterSeries::ScatterSeries(StatsView &view, StatsAxis *xAxis, StatsAxis *yAxis, const StatsVariable &varX, const StatsVariable &varY) : - StatsSeries(scene, xAxis, yAxis), + StatsSeries(view, xAxis, yAxis), varX(varX), varY(varY) { } @@ -27,62 +23,28 @@ ScatterSeries::~ScatterSeries() { } -static QPixmap createScatterPixmap(const QColor &color, const QColor &borderColor) -{ - QPixmap res(scatterItemDiameter, scatterItemDiameter); - res.fill(Qt::transparent); - QPainter painter(&res); - painter.setPen(Qt::NoPen); - painter.setRenderHint(QPainter::Antialiasing); - painter.setBrush(borderColor); - painter.drawEllipse(0, 0, scatterItemDiameter, scatterItemDiameter); - painter.setBrush(color); - painter.drawEllipse(scatterItemBorder, scatterItemBorder, - scatterItemDiameter - 2 * scatterItemBorder, - scatterItemDiameter - 2 * scatterItemBorder); - return res; -} - -// Annoying: we can create a QPixmap only after the application was initialized. -// Therefore, do this as a on-demand initialized pointer. A function local static -// variable does unnecesssary (in this case) thread synchronization. -static std::unique_ptr<QPixmap> scatterPixmapPtr; -static std::unique_ptr<QPixmap> scatterPixmapHighlightedPtr; - -static const QPixmap &scatterPixmap(bool highlight) -{ - if (!scatterPixmapPtr) { - scatterPixmapPtr.reset(new QPixmap(createScatterPixmap(fillColor, ::borderColor))); - scatterPixmapHighlightedPtr.reset(new QPixmap(createScatterPixmap(highlightedColor, highlightedBorderColor))); - } - return highlight ? *scatterPixmapHighlightedPtr : *scatterPixmapPtr; -} - -ScatterSeries::Item::Item(QGraphicsScene *scene, ScatterSeries *series, dive *d, double pos, double value) : - item(createItemPtr<QGraphicsPixmapItem>(scene, scatterPixmap(false))), +ScatterSeries::Item::Item(StatsView &view, ScatterSeries *series, dive *d, double pos, double value) : + item(view.createChartItem<ChartScatterItem>(ChartZValue::Series)), d(d), pos(pos), value(value) { - item->setZValue(ZValues::series); updatePosition(series); } void ScatterSeries::Item::updatePosition(ScatterSeries *series) { - QPointF center = series->toScreen(QPointF(pos, value)); - item->setPos(center.x() - scatterItemDiameter / 2.0, - center.y() - scatterItemDiameter / 2.0); + item->setPos(series->toScreen(QPointF(pos, value))); } void ScatterSeries::Item::highlight(bool highlight) { - item->setPixmap(scatterPixmap(highlight)); + item->setHighlight(highlight); } void ScatterSeries::append(dive *d, double pos, double value) { - items.emplace_back(scene, this, d, pos, value); + items.emplace_back(view, this, d, pos, value); } void ScatterSeries::updatePositions() @@ -91,35 +53,20 @@ void ScatterSeries::updatePositions() item.updatePosition(this); } -static double sq(double f) -{ - return f * f; -} - -static double squareDist(const QPointF &p1, const QPointF &p2) -{ - QPointF diff = p1 - p2; - return QPointF::dotProduct(diff, diff); -} - std::vector<int> ScatterSeries::getItemsUnderMouse(const QPointF &point) const { std::vector<int> res; double x = point.x(); - auto low = std::lower_bound(items.begin(), items.end(), x - scatterItemDiameter, - [] (const Item &item, double x) { return item.item->pos().x() < x; }); - auto high = std::upper_bound(low, items.end(), x + scatterItemDiameter, - [] (double x, const Item &item) { return x < item.item->pos().x(); }); + auto low = std::lower_bound(items.begin(), items.end(), x, + [] (const Item &item, double x) { return item.item->getRect().right() < x; }); + auto high = std::upper_bound(low, items.end(), x, + [] (double x, const Item &item) { return x < item.item->getRect().left(); }); // Hopefully that narrows it down enough. For discrete scatter plots, we could also partition // by equal x and do a binary search in these partitions. But that's probably not worth it. res.reserve(high - low); - double minSquare = sq(scatterItemDiameter / 2.0 + scatterItemBorder); for (auto it = low; it < high; ++it) { - QPointF pos = it->item->pos(); - pos.rx() += scatterItemDiameter / 2.0 + scatterItemBorder; - pos.ry() += scatterItemDiameter / 2.0 + scatterItemBorder; - if (squareDist(pos, point) <= minSquare) + if (it->item->contains(point)) res.push_back(it - items.begin()); } return res; @@ -169,11 +116,11 @@ bool ScatterSeries::hover(QPointF pos) highlighted = std::move(newHighlighted); if (highlighted.empty()) { - information.reset(); + information->setVisible(false); return false; } else { if (!information) - information = createItemPtr<InformationBox>(scene); + information = view.createChartItem<InformationBox>(); std::vector<QString> text; text.reserve(highlighted.size() * 5); @@ -201,6 +148,7 @@ bool ScatterSeries::hover(QPointF pos) } information->setText(text, pos); + information->setVisible(true); return true; } } |