Files
IQ.Pilot/iqpilot/tools/cabana/ui/chart/chartswidget.h
2026-09-02 16:46:45 -05:00

169 lines
4.9 KiB
C++

#pragma once
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include "imgui.h"
#include "imgui_internal.h"
#include "tools/cabana/ui/chart/signalselector.h"
#include "tools/cabana/ui/widgets/tabbar.h"
#include "tools/cabana/commands.h"
#include "tools/cabana/dbc/dbcmanager.h"
#include "tools/cabana/streams/abstractstream.h"
#include "tools/cabana/utils/util.h"
const int CHART_MIN_WIDTH = 300;
class LogSlider {
public:
LogSlider(double factor) : scale_(factor) {}
void setRange(double min, double max) {
scale_.setRange(min, max);
min_ = min;
max_ = max;
setValue(pos_);
}
int value() const { return scale_.value(pos_, minimum(), maximum()); }
void setValue(int v) { pos_ = scale_.position(v, minimum(), maximum()); }
int minimum() const { return min_; }
int maximum() const { return max_; }
bool draw(const char *label, float width);
private:
LogScale scale_;
int min_ = 0;
int max_ = 1;
int pos_ = 0;
};
class ChartView;
class ChartsWidget;
class ChartsContainer {
public:
ChartsContainer(ChartsWidget *parent) : charts_widget_(parent) {}
void setDropIndicator(const ImVec2 &pt) { drop_indicator_pos_ = pt; }
void draw();
ChartView *getDropAfter(const ImVec2 &pos) const;
ChartView *childAt(const ImVec2 &pos) const;
const ImRect &geometry() const { return geometry_; }
private:
void drawDropIndicator();
ImRect geometry_;
ChartsWidget *charts_widget_;
ImVec2 drop_indicator_pos_;
};
class ChartsWidget {
public:
ChartsWidget();
~ChartsWidget();
void draw();
void showChart(const MessageId &id, const cabana::Signal *sig, bool show, bool merge);
inline bool hasSignal(const MessageId &id, const cabana::Signal *sig) { return findChart(id, sig) != nullptr; }
std::vector<std::string> serializeChartIds() const;
void restoreChartsFromIds(const std::vector<std::string> &chart_ids);
std::string whatsThis() const;
void setColumnCount(int n);
void removeAll();
void setIsDocked(bool dock);
Observable<> toggleChartsDocking;
Observable<> seriesChanged;
Observable<double> showTip;
private:
void handleEvents();
void newChart();
ChartView *createChart(int pos = 0);
void removeChart(ChartView *chart);
void splitChart(ChartView *chart);
ImRect chartVisibleRect(ChartView *chart);
void eventsMerged(const MessageEventsMap &new_events);
void updateState();
void zoomReset();
void startChartDrag(ChartView *chart, const ImVec2 &global_pos);
void dragChartMove(const ImVec2 &global_pos);
void dragChartRelease(const ImVec2 &global_pos);
void cancelChartDrag();
bool chartDragActive() const { return drag_.source != nullptr; }
void startAutoScroll(const ImVec2 &global_pos);
void stopAutoScroll();
void doAutoScroll();
void drawToolBar();
void updateTabBar();
void setMaxChartRange(int value);
void updateLayout();
void settingChanged();
void showValueTip(double sec);
void newTab();
void removeTab(int index);
inline std::vector<ChartView *> &currentCharts() { return tab_charts_[tabbar_.tabData(tabbar_.currentIndex())]; }
ChartView *findChart(const MessageId &id, const cabana::Signal *sig);
void execSignalSelector(std::unique_ptr<SignalSelector> dlg, ChartView *owner, std::function<void(SignalSelector &)> accepted);
void drawDragPreview();
LogSlider range_slider_{1000};
bool is_docked_ = true;
bool float_window_init_ = false;
UndoStack zoom_undo_stack_;
std::vector<std::unique_ptr<ChartView>> charts_;
std::unordered_map<int, std::vector<ChartView *>> tab_charts_;
TabBar tabbar_;
ChartsContainer charts_container_{this};
ImGuiWindow *charts_scroll_ = nullptr;
ImRect charts_scroll_viewport_;
int max_chart_range_ = 0;
std::pair<double, double> display_range_;
bool columns_action_visible_ = false;
int column_count_ = 1;
int current_column_count_ = 0;
struct ChartDrag {
ChartView *source = nullptr;
ImVec2 press_pos;
bool active = false;
} drag_;
ImVec2 drag_preview_pos_;
ImVec2 drag_preview_size_;
bool drag_preview_visible_ = false;
ChartView *drop_target_ = nullptr;
int auto_scroll_count_ = 0;
ImVec2 auto_scroll_pos_;
bool auto_scroll_timer_active_ = false;
double auto_scroll_timer_next_ = 0;
bool value_tip_visible_ = false;
bool any_plot_hovered_ = false;
std::vector<std::unique_ptr<ChartView>> deleted_charts_;
std::unique_ptr<SignalSelector> signal_selector_;
ChartView *signal_selector_owner_ = nullptr;
std::function<void(SignalSelector &)> signal_selector_accepted_;
Connections connections_;
friend class ChartView;
friend class ChartsContainer;
};
class ZoomCommand : public UndoCommand {
public:
ZoomCommand(std::pair<double, double> range) : range(range) {
prev_range = can->timeRange();
}
void undo() override { can->setTimeRange(prev_range); }
void redo() override { can->setTimeRange(range); }
std::optional<std::pair<double, double>> prev_range, range;
};