默认暗色模式,添加值显示开关
This commit is contained in:
@@ -100,21 +100,21 @@ set(TOUCHSENSOR_HEADERS
|
|||||||
|
|
||||||
qt6_add_resources(APP_RESOURCES resources.qrc)
|
qt6_add_resources(APP_RESOURCES resources.qrc)
|
||||||
|
|
||||||
# add_executable(${PROJECT_NAME} WIN32
|
add_executable(${PROJECT_NAME} WIN32
|
||||||
# ${COMPONENT_SOURCES}
|
${COMPONENT_SOURCES}
|
||||||
# ${UTILITY_SOURCES}
|
${UTILITY_SOURCES}
|
||||||
# ${TOUCHSENSOR_HEADERS}
|
${TOUCHSENSOR_HEADERS}
|
||||||
# ${BASE_SOURCES}
|
${BASE_SOURCES}
|
||||||
# main.cc
|
main.cc
|
||||||
# )
|
)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME}
|
#add_executable(${PROJECT_NAME}
|
||||||
${COMPONENT_SOURCES}
|
# ${COMPONENT_SOURCES}
|
||||||
${UTILITY_SOURCES}
|
# ${UTILITY_SOURCES}
|
||||||
${TOUCHSENSOR_HEADERS}
|
# ${TOUCHSENSOR_HEADERS}
|
||||||
${BASE_SOURCES}
|
# ${BASE_SOURCES}
|
||||||
main.cc
|
# main.cc
|
||||||
)
|
#)
|
||||||
target_sources(${PROJECT_NAME} PRIVATE ${APP_RESOURCES})
|
target_sources(${PROJECT_NAME} PRIVATE ${APP_RESOURCES})
|
||||||
target_include_directories(${PROJECT_NAME}
|
target_include_directories(${PROJECT_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <creeper-qt/utility/theme/theme.hh>
|
#include <creeper-qt/utility/theme/theme.hh>
|
||||||
|
#include <creeper-qt/utility/wrapper/mutable-value.hh>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
#include <qwidget.h>
|
#include <qwidget.h>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <tuple>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using raw_pointer = T*;
|
using raw_pointer = T*;
|
||||||
@@ -12,6 +17,7 @@ struct NavComponentState {
|
|||||||
std::function<void(int, const std::string_view&)> switch_callback;
|
std::function<void(int, const std::string_view&)> switch_callback;
|
||||||
std::vector<std::tuple<std::string_view, std::string_view>> buttons_context;
|
std::vector<std::tuple<std::string_view, std::string_view>> buttons_context;
|
||||||
std::function<void(int)> stacked_callback;
|
std::function<void(int)> stacked_callback;
|
||||||
|
std::shared_ptr<creeper::MutableValue<bool>> heatmap_show_numbers;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto NavComponent(NavComponentState&) noexcept -> raw_pointer<QWidget>;
|
auto NavComponent(NavComponentState&) noexcept -> raw_pointer<QWidget>;
|
||||||
@@ -33,3 +39,4 @@ auto HandViewComponent(HandViewComponentState&) noexcept -> raw_pointer<QWidget>
|
|||||||
|
|
||||||
// 让其他模块可触发视图层的串口/配置刷新
|
// 让其他模块可触发视图层的串口/配置刷新
|
||||||
void RefreshProfilesForView();
|
void RefreshProfilesForView();
|
||||||
|
std::shared_ptr<creeper::MutableValue<bool>> HeatmapNumberVisibilityContext();
|
||||||
|
|||||||
@@ -52,6 +52,14 @@ void BasicPlot::set_data(const QVector<PointData>& data)const {
|
|||||||
pimpl->set_data(data);
|
pimpl->set_data(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BasicPlot::set_labels_visible(bool visible) const {
|
||||||
|
pimpl->set_labels_visible(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicPlot::labels_visible() const {
|
||||||
|
return pimpl->labels_visible();
|
||||||
|
}
|
||||||
|
|
||||||
bool BasicPlot::is_initialized() const {
|
bool BasicPlot::is_initialized() const {
|
||||||
return pimpl->is_plot_initialized();
|
return pimpl->is_plot_initialized();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,9 @@ public:
|
|||||||
void set_matrix_size(const int& w, const int& h)const;
|
void set_matrix_size(const int& w, const int& h)const;
|
||||||
void set_data(const QVector<PointData>& data)const;
|
void set_data(const QVector<PointData>& data)const;
|
||||||
void set_color_gradient_range(const double& min, const double& max)const;
|
void set_color_gradient_range(const double& min, const double& max)const;
|
||||||
|
void set_labels_visible(bool visible) const;
|
||||||
QSize get_matrix_size() const;
|
QSize get_matrix_size() const;
|
||||||
|
bool labels_visible() const;
|
||||||
bool is_initialized() const;
|
bool is_initialized() const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|||||||
@@ -19,7 +19,13 @@
|
|||||||
using namespace creeper::plot_widget::internal;
|
using namespace creeper::plot_widget::internal;
|
||||||
|
|
||||||
struct BasicPlot::Impl {
|
struct BasicPlot::Impl {
|
||||||
explicit Impl(BasicPlot& self) noexcept : self{self}, initialized(false), matrix_size(QSize{3, 4}) {}
|
explicit Impl(BasicPlot& self) noexcept
|
||||||
|
: matrix_size(QSize{3, 4})
|
||||||
|
, color_min(0.0)
|
||||||
|
, color_max(800.0)
|
||||||
|
, show_labels(false)
|
||||||
|
, initialized(false)
|
||||||
|
, self{self} { }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::optional<creeper::ColorScheme> scheme;
|
std::optional<creeper::ColorScheme> scheme;
|
||||||
@@ -41,10 +47,15 @@ public:
|
|||||||
|
|
||||||
auto set_matrix_size(const QSize& size) -> void {
|
auto set_matrix_size(const QSize& size) -> void {
|
||||||
matrix_size = size;
|
matrix_size = size;
|
||||||
|
const int expected = std::max(0, matrix_size.width() * matrix_size.height());
|
||||||
|
last_values.assign(static_cast<std::size_t>(expected), 0.0);
|
||||||
if (initialized) {
|
if (initialized) {
|
||||||
reset_plot();
|
reset_plot();
|
||||||
if (!data_points.isEmpty()) {
|
if (!data_points.isEmpty()) {
|
||||||
set_data(data_points);
|
set_data(data_points);
|
||||||
|
} else if (show_labels) {
|
||||||
|
sync_labels(last_values);
|
||||||
|
self.replot();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,6 +86,18 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto set_labels_visible(bool visible) -> void {
|
||||||
|
show_labels = visible;
|
||||||
|
if (initialized) {
|
||||||
|
sync_labels(last_values);
|
||||||
|
self.replot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto labels_visible() const -> bool {
|
||||||
|
return show_labels;
|
||||||
|
}
|
||||||
|
|
||||||
auto initialize_plot() -> void {
|
auto initialize_plot() -> void {
|
||||||
if (initialized) return;
|
if (initialized) return;
|
||||||
|
|
||||||
@@ -149,12 +172,12 @@ public:
|
|||||||
|
|
||||||
auto reset_plot() -> void {
|
auto reset_plot() -> void {
|
||||||
// 清除所有绘图元素
|
// 清除所有绘图元素
|
||||||
|
clear_labels();
|
||||||
self.clearPlottables();
|
self.clearPlottables();
|
||||||
self.clearGraphs();
|
self.clearGraphs();
|
||||||
self.clearItems();
|
self.clearItems();
|
||||||
self.clearFocus();
|
self.clearFocus();
|
||||||
color_map = nullptr;
|
color_map = nullptr;
|
||||||
cell_labels.clear();
|
|
||||||
|
|
||||||
// 重新初始化
|
// 重新初始化
|
||||||
initialized = false;
|
initialized = false;
|
||||||
@@ -163,7 +186,7 @@ public:
|
|||||||
auto update_plot_data() -> void {
|
auto update_plot_data() -> void {
|
||||||
if (!initialized || !color_map) return;
|
if (!initialized || !color_map) return;
|
||||||
|
|
||||||
ensure_labels();
|
// ensure_labels();
|
||||||
|
|
||||||
const int width = matrix_size.width();
|
const int width = matrix_size.width();
|
||||||
const int height = matrix_size.height();
|
const int height = matrix_size.height();
|
||||||
@@ -182,7 +205,8 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update_label_values(values);
|
last_values = values;
|
||||||
|
sync_labels(last_values);
|
||||||
|
|
||||||
// 重绘
|
// 重绘
|
||||||
self.replot();
|
self.replot();
|
||||||
@@ -201,8 +225,10 @@ private:
|
|||||||
QString ylabel;
|
QString ylabel;
|
||||||
QSize matrix_size;
|
QSize matrix_size;
|
||||||
QVector<PointData> data_points;
|
QVector<PointData> data_points;
|
||||||
|
std::vector<double> last_values;
|
||||||
double color_min = 0.0;
|
double color_min = 0.0;
|
||||||
double color_max = 800.0;
|
double color_max = 800.0;
|
||||||
|
bool show_labels = false;
|
||||||
bool initialized;
|
bool initialized;
|
||||||
BasicPlot& self;
|
BasicPlot& self;
|
||||||
QCPColorScale* color_scale = nullptr;
|
QCPColorScale* color_scale = nullptr;
|
||||||
@@ -217,7 +243,7 @@ private:
|
|||||||
text_color = scheme->on_surface;
|
text_color = scheme->on_surface;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
label_text_color = QColor(0, 0, 0); // 固定黑色
|
label_text_color = text_color;
|
||||||
|
|
||||||
const auto pen = QPen(text_color);
|
const auto pen = QPen(text_color);
|
||||||
|
|
||||||
@@ -293,7 +319,6 @@ private:
|
|||||||
void update_label_values(const std::vector<double>& values) {
|
void update_label_values(const std::vector<double>& values) {
|
||||||
const int width = matrix_size.width();
|
const int width = matrix_size.width();
|
||||||
const int height = matrix_size.height();
|
const int height = matrix_size.height();
|
||||||
const double range = std::max(color_max - color_min, 1.0);
|
|
||||||
const int expected = width * height;
|
const int expected = width * height;
|
||||||
for (int idx = 0; idx < expected && idx < cell_labels.size(); ++idx) {
|
for (int idx = 0; idx < expected && idx < cell_labels.size(); ++idx) {
|
||||||
auto* label = cell_labels[idx];
|
auto* label = cell_labels[idx];
|
||||||
@@ -309,6 +334,18 @@ private:
|
|||||||
label->position->setCoords(x + 0.5, y + 0.5);
|
label->position->setCoords(x + 0.5, y + 0.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sync_labels(const std::vector<double>& values) {
|
||||||
|
if (!initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (show_labels) {
|
||||||
|
ensure_labels();
|
||||||
|
update_label_values(values);
|
||||||
|
} else if (!cell_labels.isEmpty()) {
|
||||||
|
clear_labels();
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TOUCHSENSOR_HEATMAP_IMPL_HH
|
#endif // TOUCHSENSOR_HEATMAP_IMPL_HH
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "line_chart.hh"
|
#include "line_chart.hh"
|
||||||
#include <QLinearGradient>
|
#include <QLinearGradient>
|
||||||
|
#include <QMargins>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@@ -86,6 +87,16 @@ void LinePlot::initialize_plot() {
|
|||||||
graph_->setAntialiased(true);
|
graph_->setAntialiased(true);
|
||||||
graph_->setAdaptiveSampling(true);
|
graph_->setAdaptiveSampling(true);
|
||||||
|
|
||||||
|
current_label_ = new QCPItemText(this);
|
||||||
|
current_label_->position->setType(QCPItemPosition::ptAxisRectRatio);
|
||||||
|
current_label_->setPositionAlignment(Qt::AlignRight | Qt::AlignTop);
|
||||||
|
current_label_->position->setCoords(0.98, 0.04);
|
||||||
|
current_label_->setPadding(QMargins(6, 3, 6, 3));
|
||||||
|
current_label_->setBrush(QColor(0, 0, 0, 50));
|
||||||
|
current_label_->setPen(Qt::NoPen);
|
||||||
|
current_label_->setLayer("overlay");
|
||||||
|
current_label_->setClipToAxisRect(true);
|
||||||
|
|
||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
apply_theme();
|
apply_theme();
|
||||||
update_graph();
|
update_graph();
|
||||||
@@ -100,6 +111,7 @@ void LinePlot::apply_theme() {
|
|||||||
QColor line_color{ 16, 54, 128 };
|
QColor line_color{ 16, 54, 128 };
|
||||||
QColor text_color{ 30, 30, 30 };
|
QColor text_color{ 30, 30, 30 };
|
||||||
QColor bg_color{ 232, 238, 248 };
|
QColor bg_color{ 232, 238, 248 };
|
||||||
|
QColor label_bg = QColor(0, 0, 0, 50);
|
||||||
if (scheme_.has_value()) {
|
if (scheme_.has_value()) {
|
||||||
if (scheme_->primary.isValid()) {
|
if (scheme_->primary.isValid()) {
|
||||||
line_color = scheme_->primary;
|
line_color = scheme_->primary;
|
||||||
@@ -116,6 +128,11 @@ void LinePlot::apply_theme() {
|
|||||||
else if (scheme_->surface.isValid()) {
|
else if (scheme_->surface.isValid()) {
|
||||||
bg_color = scheme_->surface;
|
bg_color = scheme_->surface;
|
||||||
}
|
}
|
||||||
|
if (scheme_->surface_container.isValid()) {
|
||||||
|
label_bg = QColor(scheme_->surface_container.red(),
|
||||||
|
scheme_->surface_container.green(),
|
||||||
|
scheme_->surface_container.blue(), 90);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor grid_color = bg_color;
|
QColor grid_color = bg_color;
|
||||||
@@ -150,6 +167,14 @@ void LinePlot::apply_theme() {
|
|||||||
scatter.setSize(7);
|
scatter.setSize(7);
|
||||||
graph_->setScatterStyle(scatter);
|
graph_->setScatterStyle(scatter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (current_label_) {
|
||||||
|
current_label_->setColor(text_color);
|
||||||
|
current_label_->setBrush(label_bg);
|
||||||
|
QFont f = current_label_->font();
|
||||||
|
f.setBold(true);
|
||||||
|
current_label_->setFont(f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinePlot::update_graph() {
|
void LinePlot::update_graph() {
|
||||||
@@ -164,6 +189,9 @@ void LinePlot::update_graph() {
|
|||||||
if (points_.isEmpty()) {
|
if (points_.isEmpty()) {
|
||||||
graph_->data()->clear();
|
graph_->data()->clear();
|
||||||
reset_graph_range();
|
reset_graph_range();
|
||||||
|
if (current_label_) {
|
||||||
|
current_label_->setText(QStringLiteral("--"));
|
||||||
|
}
|
||||||
replot();
|
replot();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -203,6 +231,11 @@ void LinePlot::update_graph() {
|
|||||||
yAxis->setRange(min_val - padding, max_val + padding);
|
yAxis->setRange(min_val - padding, max_val + padding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (current_label_) {
|
||||||
|
const double last_val = points_.back().y();
|
||||||
|
current_label_->setText(QString::number(last_val, 'f', 1));
|
||||||
|
}
|
||||||
|
|
||||||
replot();
|
replot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "qcustomplot/qcustomplot.h"
|
#include "qcustomplot/qcustomplot.h"
|
||||||
#include <QPaintEvent>
|
#include <QPaintEvent>
|
||||||
#include <QPointF>
|
#include <QPointF>
|
||||||
|
#include <QString>
|
||||||
#include <concepts>
|
#include <concepts>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <qsize.h>
|
#include <qsize.h>
|
||||||
@@ -43,6 +44,7 @@ class LinePlot: public QCustomPlot {
|
|||||||
bool initialized_ = false;
|
bool initialized_ = false;
|
||||||
std::optional<ColorScheme> scheme_;
|
std::optional<ColorScheme> scheme_;
|
||||||
QCPGraph* graph_ = nullptr;
|
QCPGraph* graph_ = nullptr;
|
||||||
|
QCPItemText* current_label_ = nullptr;
|
||||||
int max_points_ = 240;
|
int max_points_ = 240;
|
||||||
double default_y_range_ = 100.0;
|
double default_y_range_ = 100.0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,6 +6,10 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <QLinearGradient>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QPainterPath>
|
||||||
|
#include <QPointF>
|
||||||
|
|
||||||
using creeper::vector_widget::internal::VectorPlot;
|
using creeper::vector_widget::internal::VectorPlot;
|
||||||
|
|
||||||
@@ -45,6 +49,116 @@ void VectorPlot::paintEvent(QPaintEvent* event) {
|
|||||||
initialize_plot();
|
initialize_plot();
|
||||||
}
|
}
|
||||||
QCustomPlot::paintEvent(event);
|
QCustomPlot::paintEvent(event);
|
||||||
|
|
||||||
|
// Custom glossy arrow rendering
|
||||||
|
const auto rect = axisRect();
|
||||||
|
if (!rect) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPainter painter(this);
|
||||||
|
painter.setRenderHint(QPainter::Antialiasing, true);
|
||||||
|
|
||||||
|
const QRectF plot_rect = rect->rect();
|
||||||
|
const double side_pad = plot_rect.width() * 0.24;
|
||||||
|
QRectF area = plot_rect.adjusted(side_pad, 8.0, -side_pad, -8.0);
|
||||||
|
const double cx_canvas = area.center().x();
|
||||||
|
const double cy_canvas = area.center().y();
|
||||||
|
const double scale = 0.72; // overall shrink to make it slimmer
|
||||||
|
area.setWidth(area.width() * scale);
|
||||||
|
area.setHeight(area.height() * scale);
|
||||||
|
area.moveCenter(QPointF(cx_canvas, cy_canvas));
|
||||||
|
if (area.width() <= 0.0 || area.height() <= 0.0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const double w = area.width();
|
||||||
|
const double h = area.height();
|
||||||
|
const double cx = area.center().x();
|
||||||
|
const double shaft_w = w * 0.18;
|
||||||
|
const double shaft_r = shaft_w * 0.25;
|
||||||
|
const double head_h = h * 0.36;
|
||||||
|
const double head_w = w * 0.52;
|
||||||
|
const double shaft_h = h - head_h;
|
||||||
|
const double shaft_x = cx - shaft_w * 0.5;
|
||||||
|
const double shaft_y = area.top();
|
||||||
|
const double head_base_y = shaft_y + shaft_h - shaft_r * 0.4; // overlap slightly to avoid seam
|
||||||
|
|
||||||
|
QPainterPath shaft;
|
||||||
|
shaft.addRoundedRect(QRectF(shaft_x, shaft_y, shaft_w, shaft_h), shaft_r, shaft_r);
|
||||||
|
|
||||||
|
QPainterPath head;
|
||||||
|
head.moveTo(cx - head_w * 0.5, head_base_y);
|
||||||
|
head.lineTo(cx + head_w * 0.5, head_base_y);
|
||||||
|
head.lineTo(cx, area.bottom());
|
||||||
|
head.closeSubpath();
|
||||||
|
|
||||||
|
QPainterPath arrow = shaft.united(head);
|
||||||
|
|
||||||
|
// Vibrant orange palette (fixed)
|
||||||
|
QColor base_color(255, 140, 0);
|
||||||
|
QColor highlight = base_color.lighter(165);
|
||||||
|
QColor mid = base_color;
|
||||||
|
QColor shadow = base_color.darker(180);
|
||||||
|
|
||||||
|
QLinearGradient body_grad(area.topLeft(), QPointF(area.left(), area.bottom()));
|
||||||
|
body_grad.setColorAt(0.0, highlight);
|
||||||
|
body_grad.setColorAt(0.28, mid);
|
||||||
|
body_grad.setColorAt(0.72, base_color.darker(110));
|
||||||
|
body_grad.setColorAt(1.0, shadow);
|
||||||
|
|
||||||
|
const double angle_deg = std::atan2(arrow_dir_.y(), arrow_dir_.x()) * 180.0 / 3.14159265358979323846 - 90.0;
|
||||||
|
QTransform transform;
|
||||||
|
transform.translate(cx, (shaft_y + head_base_y + area.bottom()) / 3.0); // approximate center
|
||||||
|
transform.rotate(angle_deg);
|
||||||
|
transform.translate(-cx, -(shaft_y + head_base_y + area.bottom()) / 3.0);
|
||||||
|
|
||||||
|
auto draw_with_transform = [&](const QPainterPath& path, const QBrush& brush, const QPen* pen = nullptr) {
|
||||||
|
const QPainterPath rotated = transform.map(path);
|
||||||
|
painter.setBrush(brush);
|
||||||
|
if (pen) {
|
||||||
|
painter.setPen(*pen);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
painter.setPen(Qt::NoPen);
|
||||||
|
}
|
||||||
|
painter.drawPath(rotated);
|
||||||
|
};
|
||||||
|
|
||||||
|
draw_with_transform(arrow, QBrush(body_grad));
|
||||||
|
|
||||||
|
// Gloss highlight
|
||||||
|
QPainterPath gloss;
|
||||||
|
const double gloss_w = shaft_w * 0.42;
|
||||||
|
QRectF gloss_rect(cx - gloss_w * 0.5, shaft_y + h * 0.04, gloss_w, shaft_h * 0.5);
|
||||||
|
gloss.addRoundedRect(gloss_rect, gloss_w * 0.4, gloss_w * 0.4);
|
||||||
|
QLinearGradient gloss_grad(gloss_rect.topLeft(), gloss_rect.bottomLeft());
|
||||||
|
QColor gloss_hi = Qt::white;
|
||||||
|
gloss_hi.setAlpha(190);
|
||||||
|
QColor gloss_lo = Qt::white;
|
||||||
|
gloss_lo.setAlpha(40);
|
||||||
|
gloss_grad.setColorAt(0.0, gloss_hi);
|
||||||
|
gloss_grad.setColorAt(1.0, gloss_lo);
|
||||||
|
draw_with_transform(gloss, QBrush(gloss_grad));
|
||||||
|
|
||||||
|
// Head specular highlights
|
||||||
|
const double spec_w = head_w * 0.18;
|
||||||
|
QRectF spec_left(cx - head_w * 0.32, head_base_y + head_h * 0.08, spec_w, head_h * 0.2);
|
||||||
|
QRectF spec_right(cx + head_w * 0.14, head_base_y + head_h * 0.1, spec_w * 0.8, head_h * 0.2);
|
||||||
|
auto paint_spec = [&](const QRectF& r) {
|
||||||
|
QPainterPath p;
|
||||||
|
p.addRoundedRect(r, r.width() * 0.4, r.height() * 0.6);
|
||||||
|
QLinearGradient g(r.topLeft(), r.bottomLeft());
|
||||||
|
QColor hi = Qt::white;
|
||||||
|
hi.setAlpha(180);
|
||||||
|
QColor lo = Qt::white;
|
||||||
|
lo.setAlpha(30);
|
||||||
|
g.setColorAt(0.0, hi);
|
||||||
|
g.setColorAt(1.0, lo);
|
||||||
|
draw_with_transform(p, QBrush(g));
|
||||||
|
};
|
||||||
|
paint_spec(spec_left);
|
||||||
|
paint_spec(spec_right);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VectorPlot::initialize_plot() {
|
void VectorPlot::initialize_plot() {
|
||||||
@@ -109,6 +223,7 @@ void VectorPlot::apply_color_scheme() {
|
|||||||
strong_pen.setJoinStyle(Qt::MiterJoin);
|
strong_pen.setJoinStyle(Qt::MiterJoin);
|
||||||
if (primary_arrow_) {
|
if (primary_arrow_) {
|
||||||
primary_arrow_->setPen(strong_pen);
|
primary_arrow_->setPen(strong_pen);
|
||||||
|
primary_arrow_->setVisible(false); // 使用自绘 3D 箭头
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,6 +293,7 @@ void VectorPlot::update_vectors() {
|
|||||||
}
|
}
|
||||||
dir_x /= dir_len;
|
dir_x /= dir_len;
|
||||||
dir_y /= dir_len;
|
dir_y /= dir_len;
|
||||||
|
arrow_dir_ = QPointF(dir_x, dir_y);
|
||||||
const double arrow_len = 0.48 * std::min(width, height); // 稍长的指针
|
const double arrow_len = 0.48 * std::min(width, height); // 稍长的指针
|
||||||
const double tail_ratio = 0.25; // 穿过中心的尾巴略长
|
const double tail_ratio = 0.25; // 穿过中心的尾巴略长
|
||||||
const double tail_len = arrow_len * tail_ratio;
|
const double tail_len = arrow_len * tail_ratio;
|
||||||
@@ -189,7 +305,7 @@ void VectorPlot::update_vectors() {
|
|||||||
if (primary_arrow_) {
|
if (primary_arrow_) {
|
||||||
primary_arrow_->start->setCoords(cx - dir_x * tail_len, cy - dir_y * tail_len);
|
primary_arrow_->start->setCoords(cx - dir_x * tail_len, cy - dir_y * tail_len);
|
||||||
primary_arrow_->end->setCoords(cx + dir_x * head_base, cy + dir_y * head_base);
|
primary_arrow_->end->setCoords(cx + dir_x * head_base, cy + dir_y * head_base);
|
||||||
primary_arrow_->setVisible(true);
|
primary_arrow_->setVisible(false); // 位置保留以备需要,但当前使用自绘 3D 箭头
|
||||||
}
|
}
|
||||||
|
|
||||||
replot();
|
replot();
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <QPaintEvent>
|
#include <QPaintEvent>
|
||||||
#include <concepts>
|
#include <concepts>
|
||||||
#include <qsize.h>
|
#include <qsize.h>
|
||||||
|
#include <qpoint.h>
|
||||||
#include <qvector.h>
|
#include <qvector.h>
|
||||||
|
|
||||||
namespace creeper {
|
namespace creeper {
|
||||||
@@ -39,12 +40,13 @@ class VectorPlot : public QCustomPlot {
|
|||||||
void ensure_arrows();
|
void ensure_arrows();
|
||||||
void apply_color_scheme();
|
void apply_color_scheme();
|
||||||
|
|
||||||
QSize matrix_size_{ 3, 4 };
|
QSize matrix_size_{ 3, 4 };
|
||||||
QVector<PointData> data_points_;
|
QVector<PointData> data_points_;
|
||||||
bool initialized_ = false;
|
bool initialized_ = false;
|
||||||
std::optional<ColorScheme> scheme_;
|
std::optional<ColorScheme> scheme_;
|
||||||
QColor arrow_color_{ 16, 54, 128 }; // 深蓝色
|
QColor arrow_color_{ 16, 54, 128 }; // 深蓝色
|
||||||
QCPItemLine* primary_arrow_ = nullptr;
|
QPointF arrow_dir_{ 0.0, 1.0 };
|
||||||
|
QCPItemLine* primary_arrow_ = nullptr;
|
||||||
|
|
||||||
void ensure_primary_arrow();
|
void ensure_primary_arrow();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,10 +27,12 @@ using nlohmann::json;
|
|||||||
// void dump_compact_json(...)
|
// void dump_compact_json(...)
|
||||||
// json serialize_tactile_frame(const DecodedFrame& frame) { ... }
|
// json serialize_tactile_frame(const DecodedFrame& frame) { ... }
|
||||||
|
|
||||||
std::string payload_to_csv_row(const std::vector<std::uint8_t>& payload) {
|
std::string payload_to_csv_row(const std::string& timestamp,
|
||||||
// Combine every 2 bytes (little-endian) into one 16-bit value, output in decimal.
|
const std::vector<std::uint8_t>& payload) {
|
||||||
|
// First column: receive local time (YYYYMMDDHHMMSS). Then payload every 2 bytes -> uint16.
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
bool first = true;
|
oss << timestamp;
|
||||||
|
bool first = false; // timestamp already placed
|
||||||
for (std::size_t idx = 0; idx + 1U < payload.size(); idx += 2U) {
|
for (std::size_t idx = 0; idx + 1U < payload.size(); idx += 2U) {
|
||||||
const auto value =
|
const auto value =
|
||||||
static_cast<std::uint16_t>(payload[idx]) | static_cast<std::uint16_t>(payload[idx + 1U] << 8U);
|
static_cast<std::uint16_t>(payload[idx]) | static_cast<std::uint16_t>(payload[idx + 1U] << 8U);
|
||||||
@@ -49,6 +51,28 @@ std::string payload_to_csv_row(const std::vector<std::uint8_t>& payload) {
|
|||||||
namespace {
|
namespace {
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
|
|
||||||
|
std::string format_receive_time(const std::chrono::steady_clock::time_point& received) {
|
||||||
|
// Map steady_clock timestamp to system_clock using the current offset, then format as YYYYMMDDHHMMSS.
|
||||||
|
const auto now_sys = std::chrono::system_clock::now();
|
||||||
|
const auto now_steady = std::chrono::steady_clock::now();
|
||||||
|
const auto steady_delta = received - now_steady;
|
||||||
|
const auto sys_tp = now_sys + steady_delta;
|
||||||
|
const auto sys_ms_tp = std::chrono::time_point_cast<std::chrono::milliseconds>(sys_tp);
|
||||||
|
const auto ms_part = std::chrono::duration_cast<std::chrono::milliseconds>(sys_ms_tp.time_since_epoch()) % 1000;
|
||||||
|
const auto sys_sec_tp = std::chrono::time_point_cast<std::chrono::seconds>(sys_ms_tp);
|
||||||
|
const std::time_t tt = std::chrono::system_clock::to_time_t(sys_sec_tp);
|
||||||
|
std::tm tm{};
|
||||||
|
#if defined(_WIN32)
|
||||||
|
localtime_s(&tm, &tt);
|
||||||
|
#else
|
||||||
|
localtime_r(&tt, &tm);
|
||||||
|
#endif
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << std::put_time(&tm, "%Y%m%d%H%M%S")
|
||||||
|
<< std::setw(3) << std::setfill('0') << ms_part.count();
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
bool is_simple_array(const json& value) {
|
bool is_simple_array(const json& value) {
|
||||||
if (!value.is_array()) {
|
if (!value.is_array()) {
|
||||||
return false;
|
return false;
|
||||||
@@ -261,7 +285,8 @@ std::deque<std::shared_ptr<DecodedFrame>> frames) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto row = payload_to_csv_row(payload);
|
const auto timestamp = format_receive_time(frame->received_at);
|
||||||
|
const auto row = payload_to_csv_row(timestamp, payload);
|
||||||
stream << row << '\n';
|
stream << row << '\n';
|
||||||
wrote_any = true;
|
wrote_any = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,6 +92,23 @@ auto NavComponent(NavComponentState& state) noexcept -> raw_pointer<QWidget> {
|
|||||||
ic::FontIcon {material::icon::kLogout},
|
ic::FontIcon {material::icon::kLogout},
|
||||||
ic::Clickable {&app::quit},
|
ic::Clickable {&app::quit},
|
||||||
},
|
},
|
||||||
|
ln::Item<IconButton> {
|
||||||
|
{0, Qt::AlignHCenter},
|
||||||
|
navigation_icons_config,
|
||||||
|
ic::ColorFilled,
|
||||||
|
ic::FontIcon {material::icon::k123},
|
||||||
|
MutableTransform{ [](auto& self, bool show_numbers) {
|
||||||
|
self.set_types(show_numbers
|
||||||
|
? icon_button::internal::IconButton::Types::TOGGLE_SELECTED
|
||||||
|
: icon_button::internal::IconButton::Types::TOGGLE_UNSELECTED);
|
||||||
|
},
|
||||||
|
state.heatmap_show_numbers },
|
||||||
|
ic::Clickable{ [ctx = state.heatmap_show_numbers] {
|
||||||
|
if (ctx) {
|
||||||
|
ctx->set(!ctx->get());
|
||||||
|
}
|
||||||
|
} },
|
||||||
|
},
|
||||||
ln::Item<IconButton> {
|
ln::Item<IconButton> {
|
||||||
{0, Qt::AlignHCenter},
|
{0, Qt::AlignHCenter},
|
||||||
navigation_icons_config,
|
navigation_icons_config,
|
||||||
@@ -102,4 +119,3 @@ auto NavComponent(NavComponentState& state) noexcept -> raw_pointer<QWidget> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -171,11 +171,14 @@ class SensorStreamController: public QObject {
|
|||||||
std::shared_ptr<MutableValue<QVector<PointData>>> heatmap_data,
|
std::shared_ptr<MutableValue<QVector<PointData>>> heatmap_data,
|
||||||
std::shared_ptr<MutableValue<QSize>> matrix_context,
|
std::shared_ptr<MutableValue<QSize>> matrix_context,
|
||||||
std::shared_ptr<MutableValue<QVector<QPointF>>> line_series,
|
std::shared_ptr<MutableValue<QVector<QPointF>>> line_series,
|
||||||
|
std::shared_ptr<MutableValue<QVector<QPointF>>> line_series_max,
|
||||||
int line_capacity = 240,
|
int line_capacity = 240,
|
||||||
QObject* parent = nullptr): QObject(parent), heatmap_data_(std::move(heatmap_data)),
|
QObject* parent = nullptr): QObject(parent), heatmap_data_(std::move(heatmap_data)),
|
||||||
matrix_context_(std::move(matrix_context)),
|
matrix_context_(std::move(matrix_context)),
|
||||||
line_series_(std::move(line_series)),
|
line_series_(std::move(line_series)),
|
||||||
line_series_capacity_(std::max(1, line_capacity)) {
|
line_series_max_(std::move(line_series_max)),
|
||||||
|
line_series_capacity_(std::max(1, line_capacity)),
|
||||||
|
line_series_half_capacity_(std::max(1, line_capacity / 2)) {
|
||||||
std::call_once(codec_registration_flag(),
|
std::call_once(codec_registration_flag(),
|
||||||
[] {
|
[] {
|
||||||
ffmsep::tactile::register_tactile_codec();
|
ffmsep::tactile::register_tactile_codec();
|
||||||
@@ -197,6 +200,9 @@ class SensorStreamController: public QObject {
|
|||||||
if (line_series_) {
|
if (line_series_) {
|
||||||
line_series_->set(QVector<QPointF>{});
|
line_series_->set(QVector<QPointF>{});
|
||||||
}
|
}
|
||||||
|
if (line_series_max_) {
|
||||||
|
line_series_max_->set(QVector<QPointF>{});
|
||||||
|
}
|
||||||
|
|
||||||
const auto ports = ffmsep::CPStreamCore::list_available_ports();
|
const auto ports = ffmsep::CPStreamCore::list_available_ports();
|
||||||
std::string port_utf8;
|
std::string port_utf8;
|
||||||
@@ -335,6 +341,9 @@ class SensorStreamController: public QObject {
|
|||||||
if (line_series_) {
|
if (line_series_) {
|
||||||
line_series_->set(QVector<QPointF>{});
|
line_series_->set(QVector<QPointF>{});
|
||||||
}
|
}
|
||||||
|
if (line_series_max_) {
|
||||||
|
line_series_max_->set(QVector<QPointF>{});
|
||||||
|
}
|
||||||
sample_counter_ = 0;
|
sample_counter_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,8 +453,13 @@ class SensorStreamController: public QObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double total = 0.0;
|
double total = 0.0;
|
||||||
|
double max_v = 0.0;
|
||||||
for (const auto value: pressures) {
|
for (const auto value: pressures) {
|
||||||
total += static_cast<double>(value);
|
const double v = static_cast<double>(value);
|
||||||
|
total += v;
|
||||||
|
if (v > max_v) {
|
||||||
|
max_v = v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line_series_) {
|
if (line_series_) {
|
||||||
@@ -456,9 +470,19 @@ class SensorStreamController: public QObject {
|
|||||||
const int start = series.size() - line_series_capacity_;
|
const int start = series.size() - line_series_capacity_;
|
||||||
series = series.mid(start);
|
series = series.mid(start);
|
||||||
}
|
}
|
||||||
++sample_counter_;
|
|
||||||
line_series_->set(std::move(series));
|
line_series_->set(std::move(series));
|
||||||
}
|
}
|
||||||
|
if (line_series_max_) {
|
||||||
|
auto series = line_series_max_->get();
|
||||||
|
series.append(QPointF(static_cast<double>(sample_counter_), max_v));
|
||||||
|
const int cap = std::max(1, line_series_half_capacity_);
|
||||||
|
if (series.size() > cap) {
|
||||||
|
const int start = series.size() - cap;
|
||||||
|
series = series.mid(start);
|
||||||
|
}
|
||||||
|
line_series_max_->set(std::move(series));
|
||||||
|
}
|
||||||
|
++sample_counter_;
|
||||||
|
|
||||||
QVector<PointData> points;
|
QVector<PointData> points;
|
||||||
points.reserve(matrix.width() * matrix.height());
|
points.reserve(matrix.width() * matrix.height());
|
||||||
@@ -546,11 +570,13 @@ class SensorStreamController: public QObject {
|
|||||||
std::shared_ptr<MutableValue<QVector<PointData>>> heatmap_data_;
|
std::shared_ptr<MutableValue<QVector<PointData>>> heatmap_data_;
|
||||||
std::shared_ptr<MutableValue<QSize>> matrix_context_;
|
std::shared_ptr<MutableValue<QSize>> matrix_context_;
|
||||||
std::shared_ptr<MutableValue<QVector<QPointF>>> line_series_;
|
std::shared_ptr<MutableValue<QVector<QPointF>>> line_series_;
|
||||||
|
std::shared_ptr<MutableValue<QVector<QPointF>>> line_series_max_;
|
||||||
std::unique_ptr<ffmsep::CPStreamCore> core_;
|
std::unique_ptr<ffmsep::CPStreamCore> core_;
|
||||||
QString active_port_;
|
QString active_port_;
|
||||||
QString last_error_;
|
QString last_error_;
|
||||||
std::uint64_t sample_counter_ = 0;
|
std::uint64_t sample_counter_ = 0;
|
||||||
int line_series_capacity_ = 240;
|
int line_series_capacity_ = 240;
|
||||||
|
int line_series_half_capacity_ = 120;
|
||||||
bool connected_ = false;
|
bool connected_ = false;
|
||||||
|
|
||||||
static std::future<ffmsep::persist::WriteResult>
|
static std::future<ffmsep::persist::WriteResult>
|
||||||
@@ -573,8 +599,12 @@ struct SensorUiState {
|
|||||||
std::make_shared<MutableValue<QSize>>();
|
std::make_shared<MutableValue<QSize>>();
|
||||||
std::shared_ptr<MutableValue<QPair<int, int>>> heatmap_range =
|
std::shared_ptr<MutableValue<QPair<int, int>>> heatmap_range =
|
||||||
std::make_shared<MutableValue<QPair<int, int>>>(QPair<int, int>{ 0, 300 });
|
std::make_shared<MutableValue<QPair<int, int>>>(QPair<int, int>{ 0, 300 });
|
||||||
|
std::shared_ptr<MutableValue<bool>> heatmap_show_numbers =
|
||||||
|
std::make_shared<MutableValue<bool>>(false);
|
||||||
std::shared_ptr<MutableValue<QVector<QPointF>>> line_series =
|
std::shared_ptr<MutableValue<QVector<QPointF>>> line_series =
|
||||||
std::make_shared<MutableValue<QVector<QPointF>>>();
|
std::make_shared<MutableValue<QVector<QPointF>>>();
|
||||||
|
std::shared_ptr<MutableValue<QVector<QPointF>>> line_series_max =
|
||||||
|
std::make_shared<MutableValue<QVector<QPointF>>>();
|
||||||
int line_series_capacity = 240;
|
int line_series_capacity = 240;
|
||||||
std::shared_ptr<MutableValue<QStringList>> port_items =
|
std::shared_ptr<MutableValue<QStringList>> port_items =
|
||||||
std::make_shared<MutableValue<QStringList>>();
|
std::make_shared<MutableValue<QStringList>>();
|
||||||
@@ -631,7 +661,7 @@ struct SensorUiState {
|
|||||||
|
|
||||||
controller =
|
controller =
|
||||||
std::make_unique<SensorStreamController>(
|
std::make_unique<SensorStreamController>(
|
||||||
heatmap_data, heatmap_matrix, line_series, line_series_capacity);
|
heatmap_data, heatmap_matrix, line_series, line_series_max, line_series_capacity);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -674,6 +704,10 @@ class PortHoverRefreshFilter final: public QObject {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
std::shared_ptr<MutableValue<bool>> HeatmapNumberVisibilityContext() {
|
||||||
|
return sensor_state().heatmap_show_numbers;
|
||||||
|
}
|
||||||
|
|
||||||
void RefreshProfilesForView() {
|
void RefreshProfilesForView() {
|
||||||
auto& sensor = sensor_state();
|
auto& sensor = sensor_state();
|
||||||
|
|
||||||
@@ -912,9 +946,10 @@ int /*index*/ = 0) noexcept {
|
|||||||
auto& sensor = sensor_state();
|
auto& sensor = sensor_state();
|
||||||
const auto row = new Row{
|
const auto row = new Row{
|
||||||
lnpro::Item<HeatMapPlot>{
|
lnpro::Item<HeatMapPlot>{
|
||||||
plot_widget::pro::SizePolicy{
|
widget::pro::FixedSize {600, 600},
|
||||||
QSizePolicy::Expanding,
|
// plot_widget::pro::SizePolicy{
|
||||||
},
|
// // QSizePolicy::Fixed,
|
||||||
|
// },
|
||||||
plot_widget::pro::ThemeManager{ manager },
|
plot_widget::pro::ThemeManager{ manager },
|
||||||
MutableForward{
|
MutableForward{
|
||||||
plot_widget::pro::PlotData{},
|
plot_widget::pro::PlotData{},
|
||||||
@@ -933,6 +968,10 @@ int /*index*/ = 0) noexcept {
|
|||||||
widget.set_color_gradient_range(min, max);
|
widget.set_color_gradient_range(min, max);
|
||||||
},
|
},
|
||||||
sensor.heatmap_range },
|
sensor.heatmap_range },
|
||||||
|
MutableTransform{ [](auto& widget, bool show_numbers) {
|
||||||
|
widget.set_labels_visible(show_numbers);
|
||||||
|
},
|
||||||
|
sensor.heatmap_show_numbers },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return new Widget{
|
return new Widget{
|
||||||
@@ -966,21 +1005,29 @@ static auto DisplayVectorComponent(ThemeManager& manager) noexcept {
|
|||||||
|
|
||||||
static auto DisplayLineComponent(ThemeManager& manager) noexcept {
|
static auto DisplayLineComponent(ThemeManager& manager) noexcept {
|
||||||
auto& sensor = sensor_state();
|
auto& sensor = sensor_state();
|
||||||
const auto row = new Row{
|
const int half_cap = std::max(1, sensor.line_series_capacity / 2);
|
||||||
|
const auto col = new Col{
|
||||||
lnpro::Item<SumLinePlot>{
|
lnpro::Item<SumLinePlot>{
|
||||||
lcpro::SizePolicy{
|
lcpro::SizePolicy{ QSizePolicy::Expanding },
|
||||||
QSizePolicy::Expanding,
|
|
||||||
},
|
|
||||||
lcpro::ThemeManager{ manager },
|
lcpro::ThemeManager{ manager },
|
||||||
lcpro::MaxPoints{ sensor.line_series_capacity },
|
lcpro::MaxPoints{ half_cap },
|
||||||
MutableForward{
|
MutableForward{
|
||||||
lcpro::PlotData{},
|
lcpro::PlotData{},
|
||||||
sensor.line_series,
|
sensor.line_series,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
lnpro::Item<SumLinePlot>{
|
||||||
|
lcpro::SizePolicy{ QSizePolicy::Expanding },
|
||||||
|
lcpro::ThemeManager{ manager },
|
||||||
|
lcpro::MaxPoints{ half_cap },
|
||||||
|
MutableForward{
|
||||||
|
lcpro::PlotData{},
|
||||||
|
sensor.line_series_max,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
return new Widget{
|
return new Widget{
|
||||||
widget::pro::Layout{ row },
|
widget::pro::Layout{ col },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ namespace material {
|
|||||||
constexpr auto kCancel = "cancel";
|
constexpr auto kCancel = "cancel";
|
||||||
constexpr auto kOpenInNew = "open_in_new";
|
constexpr auto kOpenInNew = "open_in_new";
|
||||||
constexpr auto kLogout = "logout";
|
constexpr auto kLogout = "logout";
|
||||||
|
constexpr auto k123 = "123";
|
||||||
constexpr auto kRoutine = "routine";
|
constexpr auto kRoutine = "routine";
|
||||||
constexpr auto kDarkMode = "dark_mode";
|
constexpr auto kDarkMode = "dark_mode";
|
||||||
constexpr auto kFileExport = "file_export";
|
constexpr auto kFileExport = "file_export";
|
||||||
|
|||||||
5
main.cc
5
main.cc
@@ -33,7 +33,7 @@ auto main(int argc, char *argv[]) -> int {
|
|||||||
auto stack_index = std::make_shared<MutableValue<int>>();
|
auto stack_index = std::make_shared<MutableValue<int>>();
|
||||||
stack_index->set_silent(0);
|
stack_index->set_silent(0);
|
||||||
|
|
||||||
auto manager = ThemeManager {kBlueMikuThemePack};
|
auto manager = ThemeManager {kBlueMikuThemePack, ColorMode::DARK};
|
||||||
creeper::material::FontLoader::load_font();
|
creeper::material::FontLoader::load_font();
|
||||||
auto nav_component_state = NavComponentState {
|
auto nav_component_state = NavComponentState {
|
||||||
.manager = manager,
|
.manager = manager,
|
||||||
@@ -51,7 +51,8 @@ auto main(int argc, char *argv[]) -> int {
|
|||||||
},
|
},
|
||||||
.stacked_callback = [&](int index) {
|
.stacked_callback = [&](int index) {
|
||||||
*stack_index = index;
|
*stack_index = index;
|
||||||
}
|
},
|
||||||
|
.heatmap_show_numbers = HeatmapNumberVisibilityContext(),
|
||||||
};
|
};
|
||||||
auto setting_component_state = SettingComponentState {
|
auto setting_component_state = SettingComponentState {
|
||||||
.manager = manager,
|
.manager = manager,
|
||||||
|
|||||||
Reference in New Issue
Block a user