Files
ts-qt/components/charts/heatmap.hh

132 lines
4.0 KiB
C++

//
// Created by Lenn on 2025/10/17.
//
#ifndef TOUCHSENSOR_HEATMAP_H
#define TOUCHSENSOR_HEATMAP_H
#include "modern-qt/utility/theme/theme.hh"
#include "modern-qt/utility/wrapper/common.hh"
#include "modern-qt/utility/wrapper/pimpl.hh"
#include "modern-qt/utility/wrapper/property.hh"
#include "qcustomplot/qcustomplot.h"
#include "modern-qt/utility/wrapper/widget.hh"
#include <concepts>
#include <qcontainerfwd.h>
#include <qvector.h>
struct point_data {
double x;
double y;
double z;
explicit point_data(double x, double y, double z) : x{x}, y{y}, z{z} {}
};
using PointData = struct point_data;
namespace creeper {
class HeatMapPlot;
namespace plot_widget::internal {
class BasicPlot : public QCustomPlot {
CREEPER_PIMPL_DEFINITION(BasicPlot)
friend class HeatMapPlot;
public:
// BasicPlot();
// ~BasicPlot();
// BasicPlot(const BasicPlot&) = delete;
// BasicPlot& operator=(const BasicPlot&) = delete;
void init_plot()const;
void load_theme_manager(ThemeManager&)const;
void set_xlabel_text(const QString&)const;
void set_ylabel_text(const QString&)const;
void set_matrix_size(const QSize&)const;
void set_matrix_size(const int& w, const int& h)const;
void set_data(const QVector<PointData>& data)const;
void set_color_gradient_range(const double& min, const double& max)const;
QSize get_matrix_size() const;
bool is_initialized() const;
public slots:
void update_dynamic_heatmap(const QVector<PointData>& map)const;
void dataChanged(const QVector<PointData>& map)const;
void dataRangeChanged(const double& min, const double& max)const;
protected:
void paintEvent(QPaintEvent*) override;
private:
friend struct Impl;
};
} // namespace plot_widget::internal
namespace plot_widget::pro {
using Token = common::Token<plot_widget::internal::BasicPlot>;
using XLabelText = common::pro::String<Token,
[](auto& self, const auto& string) {
self.set_xlabel_text(string);
}>;
using YLabelText = common::pro::String<Token,
[](auto& self, const auto& string) {
self.set_ylabel_text(string);
}>;
struct MatrixSize : Token {
QSize size;
explicit MatrixSize(const int& w, const int& h) : size{w, h} {}
explicit MatrixSize(const QSize& s) : size{s} {}
void apply(auto& self) const {
self.set_matrix_size(size);
}
};
using Data = common::pro::Vector<Token, PointData,
[](auto& self, const auto& data) {
self.set_data(data);
}>;
struct ColorRange : Token {
double min;
double max;
explicit ColorRange(double min, double max) : min{min}, max{max} {}
void apply(auto& self) const {
self.set_color_gradient_range(min, max);
}
};
template <typename F>
using OnDataChanged =
common::pro::SignalInjection<F, Token, &internal::BasicPlot::dataChanged>;
template <typename F>
using OnDataRangeChanged =
common::pro::SignalInjection<F, Token, &internal::BasicPlot::dataRangeChanged>;
template<class PlotWidget>
concept trait = std::derived_from<PlotWidget, Token>;
using PlotData = common::pro::Vector<Token, PointData, [](auto& self, const auto& vec) {
self.set_data(vec);
}>;
using DataRange = common::pro::Array<Token, int, 2, [](auto& self, const auto& arr) {
self.set_color_gradient_range(arr[0], arr[1]);
}>;
CREEPER_DEFINE_CHECKER(trait);
using namespace widget::pro;
using namespace theme::pro;
}
struct HeatMapPlot
: public Declarative<plot_widget::internal::BasicPlot,
CheckerOr<plot_widget::pro::checker, widget::pro::checker, theme::pro::checker>> {
using Declarative::Declarative;
void paintEvent(QPaintEvent*) override;
};
}
#endif // TOUCHSENSOR_HEATMAP_H