mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-09-17 10:33:44 +08:00
cabana: contain tooltips and capture plot drags (#38896)
* cabana: contain chart tooltips within columns * cabana: refresh tooltip bounds after chart resize * cabana: capture plot drags to prevent window movement
This commit is contained in:
@@ -507,8 +507,10 @@ void ChartView::draw(float width) {
|
||||
}
|
||||
ImGui::EndChild();
|
||||
// a chart scrolled out of the viewport draws no tip
|
||||
const ImRect visible_rect = charts_widget_->chartVisibleRect(this);
|
||||
if (!drawing_ghost_ && visible_rect.GetWidth() > 0 && visible_rect.GetHeight() > 0) tip_label_.draw();
|
||||
ImRect visible_rect = charts_widget_->chartVisibleRect(this);
|
||||
visible_rect.ClipWith(ImRect(ImVec2(layout_.rect.Min.x, layout_.plot_area.Min.y),
|
||||
ImVec2(layout_.rect.Max.x, layout_.plot_area.Max.y)));
|
||||
if (!drawing_ghost_ && visible_rect.GetWidth() > 0 && visible_rect.GetHeight() > 0) tip_label_.draw(visible_rect);
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
@@ -575,6 +577,14 @@ void ChartView::drawAxes() {
|
||||
// ImPlotFlags_NoInputs disables implot's own hover tracking
|
||||
layout_.plot_hovered = layout_.plot_area.Contains(ImGui::GetMousePos()) && ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem);
|
||||
drawSeries();
|
||||
if (!drawing_ghost_) {
|
||||
// Own plot clicks so custom scrubbing/zooming cannot also move the floating window.
|
||||
const ImGuiID input_id = ImGui::GetID("plot_input");
|
||||
if (ImGui::ItemAdd(layout_.plot_area, input_id)) {
|
||||
bool hovered, held;
|
||||
ImGui::ButtonBehavior(layout_.plot_area, input_id, &hovered, &held);
|
||||
}
|
||||
}
|
||||
handleMousePress();
|
||||
handleMouseMove();
|
||||
handleMouseRelease();
|
||||
|
||||
@@ -19,6 +19,31 @@ ImVec2 TipLabel::layoutLines(ImDrawList *p, const ImVec2 &origin, ImU32 fg) cons
|
||||
};
|
||||
const char *heading = !text_.empty() && !text_[0].has_marker ? text_[0].name.c_str() : "Signal";
|
||||
const char *headers[] = {heading, "Value", "Min", "Max"};
|
||||
if (compact_) {
|
||||
const float right = origin.x + std::max(0.0f, area_.GetWidth() - MARGIN * 2 - 1);
|
||||
auto cell = [&](float left, const std::string &text, ImU32 color) {
|
||||
if (p) drawElidedText(p, ImRect(ImVec2(left, y), ImVec2(right, y + font_size)), text, color);
|
||||
};
|
||||
cell(origin.x, heading, muted);
|
||||
y += line_height;
|
||||
for (const auto &line : text_) {
|
||||
if (!line.has_marker) continue;
|
||||
if (p) p->AddRectFilled(ImVec2(origin.x, y + (font_size - marker) * 0.5f),
|
||||
ImVec2(origin.x + marker, y + (font_size + marker) * 0.5f), line.marker);
|
||||
cell(origin.x + marker + 6, line.name, fg);
|
||||
y += line_height;
|
||||
const std::string *values[] = {&line.value, &line.min, &line.max};
|
||||
const float label_width = ImGui::CalcTextSize("Value").x + gap;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
draw(origin.x, headers[i + 1], muted);
|
||||
pushMonoFont(font_size);
|
||||
cell(origin.x + label_width, *values[i], i == 0 ? fg : muted);
|
||||
popMonoFont();
|
||||
y += line_height;
|
||||
}
|
||||
}
|
||||
return ImVec2(right - origin.x, y - origin.y);
|
||||
}
|
||||
float x = origin.x;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
draw(i ? x + column_widths_[i] - ImGui::CalcTextSize(headers[i]).x : x, headers[i], muted);
|
||||
@@ -77,8 +102,15 @@ void TipLabel::updateLayout() {
|
||||
}
|
||||
popMonoFont();
|
||||
const ImGuiViewport *viewport = ImGui::GetWindowViewport();
|
||||
const ImRect bounds(viewport->WorkPos, viewport->WorkPos + viewport->WorkSize);
|
||||
ImRect bounds(viewport->WorkPos, viewport->WorkPos + viewport->WorkSize);
|
||||
bounds.ClipWith(area_);
|
||||
if (bounds.GetWidth() <= 0 || bounds.GetHeight() <= 0) {
|
||||
visible_ = false;
|
||||
return;
|
||||
}
|
||||
area_ = bounds;
|
||||
const float numeric_width = column_widths_[1] + column_widths_[2] + column_widths_[3] + 24 + MARGIN * 2 + 1;
|
||||
compact_ = bounds.GetWidth() < numeric_width + ImGui::GetFontSize() * 4;
|
||||
column_widths_[0] = std::min(column_widths_[0], std::max(40.0f, std::min(ImGui::GetFontSize() * 16, bounds.GetWidth() - numeric_width)));
|
||||
if (!text_.empty()) {
|
||||
ImVec2 extra(1, 1);
|
||||
@@ -96,13 +128,17 @@ void TipLabel::updateLayout() {
|
||||
visible_ = false;
|
||||
}
|
||||
|
||||
void TipLabel::draw() {
|
||||
void TipLabel::draw(const ImRect &rect) {
|
||||
if (!visible_) return;
|
||||
area_ = rect;
|
||||
updateLayout();
|
||||
if (!visible_) return;
|
||||
|
||||
ImDrawList *p = ImGui::GetForegroundDrawList();
|
||||
p->PushClipRect(area_.Min, area_.Max, true);
|
||||
// filled panel with a 1px frame
|
||||
p->AddRectFilled(pos_, pos_ + size_, ImGui::GetColorU32(ImGuiCol_PopupBg), ImGui::GetStyle().PopupRounding);
|
||||
p->AddRect(pos_, pos_ + size_, ImGui::GetColorU32(ImGuiCol_Border), ImGui::GetStyle().PopupRounding);
|
||||
layoutLines(p, pos_ + ImVec2(MARGIN, MARGIN), ImGui::GetColorU32(ImGuiCol_Text));
|
||||
p->PopClipRect();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ public:
|
||||
void showText(const ImVec2 &pt, const std::vector<TipLine> &text, const ImRect &rect);
|
||||
void hide() { visible_ = false; }
|
||||
bool isVisible() const { return visible_; }
|
||||
void draw(); // draws the tip on the foreground draw list; call once per frame
|
||||
void draw(const ImRect &rect); // draws the tip on the foreground draw list; call once per frame
|
||||
|
||||
private:
|
||||
// lays the lines out from origin, drawing them when p is given; returns the size of the text block
|
||||
@@ -35,5 +35,6 @@ private:
|
||||
ImRect area_;
|
||||
ImVec2 pos_;
|
||||
ImVec2 size_;
|
||||
bool compact_ = false;
|
||||
bool visible_ = false;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user