#pragma once #include #include #include #include #include #include #include "imgui.h" #include "imgui_internal.h" #include "tools/cabana/core/observable.h" #include "tools/cabana/dbc/dbcmanager.h" #include "tools/cabana/streams/abstractstream.h" struct BinaryIndex { int row = -1; int column = -1; bool isValid() const { return row >= 0 && column >= 0; } bool operator==(const BinaryIndex &o) const { return row == o.row && column == o.column; } bool operator<(const BinaryIndex &o) const { return std::tie(row, column) < std::tie(o.row, o.column); } }; class BinaryView { public: static constexpr int COLUMN_COUNT = 9; static constexpr int HEX_COLUMN = 8; BinaryView(); void setMessage(const MessageId &message_id); void highlight(const cabana::Signal *sig); std::set getOverlappingSignals() const; void updateState(); void draw(); ImVec2 minimumSizeHint() const; void setHeatmapLiveMode(bool live) { heatmap_live_mode_ = live; updateState(); } std::string whatsThis() const; Observable signalClicked; Observable signalHovered; Observable editSignal; Observable showChart; private: struct Cell { CabanaColor bg_color = CabanaColor(102, 86, 169, 255); bool is_msb = false; bool is_lsb = false; uint8_t val; std::vector sigs; bool valid = false; }; void refresh(); void setCell(int row, int col, uint8_t val, const CabanaColor &color); const std::vector> &bitFlipChanges(size_t msg_size); Cell &cellAt(const BinaryIndex &index) { return cells_[index.row * COLUMN_COUNT + index.column]; } const Cell &cellAt(const BinaryIndex &index) const { return cells_[index.row * COLUMN_COUNT + index.column]; } void addShortcuts(); std::tuple getSelection(BinaryIndex index); void setSelection(); void handleMousePress(const ImVec2 &pos); void handleMouseMove(const ImVec2 &pos); void handleMouseRelease(const ImVec2 &pos); void highlightPosition(const ImVec2 &pt); BinaryIndex indexAt(const ImVec2 &pos) const; ImRect visualRect(const BinaryIndex &index) const; bool hasSelection() const { return !selection_.empty(); } bool isSelected(const BinaryIndex &index) const { return selection_.count(index) > 0; } void paintCell(ImDrawList *painter, const ImRect &rect, const BinaryIndex &index) const; bool hasSignal(const BinaryIndex &index, int dx, int dy, const cabana::Signal *sig) const; void drawSignalCell(ImDrawList *painter, const ImRect &rect, const BinaryIndex &index, const cabana::Signal *sig) const; MessageId msg_id_; std::vector cells_; int row_count_ = 0; bool heatmap_live_mode_ = true; struct BitFlipTracker { std::optional> time_range; std::vector> flip_counts; } bit_flip_tracker_; BinaryIndex anchor_index_; ImVec2 last_mouse_pos_{-1, -1}; bool is_message_active_ = false; const cabana::Signal *resize_sig_ = nullptr; const cabana::Signal *hovered_sig_ = nullptr; std::set selection_; ImVec2 grid_pos_; float column_width_ = 0; bool under_mouse_ = false; bool scroll_to_top_ = false; Connections connections_; };