diff options
-rw-r--r-- | stats/CMakeLists.txt | 2 | ||||
-rw-r--r-- | stats/informationbox.cpp | 75 | ||||
-rw-r--r-- | stats/informationbox.h | 31 |
3 files changed, 108 insertions, 0 deletions
diff --git a/stats/CMakeLists.txt b/stats/CMakeLists.txt index bf11d06fd..e8f49e35f 100644 --- a/stats/CMakeLists.txt +++ b/stats/CMakeLists.txt @@ -5,6 +5,8 @@ include_directories(. ) set(SUBSURFACE_STATS_SRCS + informationbox.h + informationbox.cpp legend.h legend.cpp statsaxis.h diff --git a/stats/informationbox.cpp b/stats/informationbox.cpp new file mode 100644 index 000000000..015f821be --- /dev/null +++ b/stats/informationbox.cpp @@ -0,0 +1,75 @@ +#include "informationbox.h" +#include "statscolors.h" +#include "zvalues.h" + +#include <QChart> +#include <QFontMetrics> + +static const QColor informationBorderColor(Qt::black); +static const QColor informationColor(0xff, 0xff, 0x00, 192); // Note: fourth argument is opacity +static const int informationBorder = 2; +static const int distanceFromPointer = 10; // Distance to place box from mouse pointer or scatter item + +InformationBox::InformationBox(QtCharts::QChart *chart) : QGraphicsRectItem(chart), chart(chart) +{ + setPen(QPen(informationBorderColor, informationBorder)); + setBrush(informationColor); + setZValue(ZValues::informationBox); +} + +void InformationBox::setText(const std::vector<QString> &text, QPointF pos) +{ + width = height = 0.0; + textItems.clear(); + + for (const QString &s: text) { + if (!s.isEmpty()) + addLine(s); + } + + width += 4.0 * informationBorder; + height += 4.0 * informationBorder; + + // Setting the position will also set the proper size + setPos(pos); +} + +void InformationBox::setPos(QPointF pos) +{ + QRectF plotArea = chart->plotArea(); + + double x = pos.x() + distanceFromPointer; + if (x + width >= plotArea.right() && pos.x() - width >= plotArea.x()) + x = pos.x() - width; + double y = pos.y() + distanceFromPointer; + if (y + height >= plotArea.bottom() && pos.y() - height >= plotArea.y()) + y = pos.y() - height; + + setRect(x, y, width, height); + double actY = y + 2.0 * informationBorder; + for (auto &item: textItems) { + item->setPos(QPointF(x + 2.0 * informationBorder, actY)); + actY += item->boundingRect().height(); + } +} + +void InformationBox::addLine(const QString &s) +{ + textItems.emplace_back(new QGraphicsSimpleTextItem(s, this)); + QGraphicsSimpleTextItem &item = *textItems.back(); + item.setBrush(QBrush(darkLabelColor)); + item.setPos(QPointF(0.0, height)); + item.setFont(font); + item.setZValue(ZValues::informationBox); + QRectF rect = item.boundingRect(); + width = std::max(width, rect.width()); + height += rect.height(); +} + +// Try to stay within three-thirds of the chart height +int InformationBox::recommendedMaxLines() const +{ + QFontMetrics fm(font); + int maxHeight = static_cast<int>(chart->plotArea().height()); + return maxHeight * 2 / fm.height() / 3; +} diff --git a/stats/informationbox.h b/stats/informationbox.h new file mode 100644 index 000000000..7e9253dc7 --- /dev/null +++ b/stats/informationbox.h @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0 +// A small box displaying statistics information, notably +// for a scatter-plot item or a bar in a bar chart. +#ifndef INFORMATION_BOX_H +#define INFORMATION_BOX_H + +#include <vector> +#include <memory> +#include <QGraphicsRectItem> +#include <QFont> + +namespace QtCharts { + class QChart; +} +struct dive; + +// Information window showing data of highlighted dive +struct InformationBox : QGraphicsRectItem { + InformationBox(QtCharts::QChart *chart); + void setText(const std::vector<QString> &text, QPointF pos); + void setPos(QPointF pos); + int recommendedMaxLines() const; +private: + QtCharts::QChart *chart; + QFont font; // For future specialization. + double width, height; + void addLine(const QString &s); + std::vector<std::unique_ptr<QGraphicsSimpleTextItem>> textItems; +}; + +#endif |