From af4adf53798c8cb0057289c0d1fe542654695bd5 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sun, 21 Feb 2021 16:38:06 -0800 Subject: [PATCH] [glass] Auto-size plots to fit window (#3193) Plots can still be set to have a fixed height, in which case the remaining space is distributed amongst the auto-sized plots. --- glass/src/lib/native/cpp/other/Plot.cpp | 70 ++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/glass/src/lib/native/cpp/other/Plot.cpp b/glass/src/lib/native/cpp/other/Plot.cpp index e1415f9185..d850b626dc 100644 --- a/glass/src/lib/native/cpp/other/Plot.cpp +++ b/glass/src/lib/native/cpp/other/Plot.cpp @@ -113,6 +113,15 @@ class Plot { std::vector> m_series; + // Returns base height; does not include actual plot height if auto-sized. + int GetAutoBaseHeight(bool* isAuto, size_t i); + + void SetAutoHeight(int height) { + if (m_autoHeight) { + m_height = height; + } + } + private: void EmitSettingsLimits(int axis); @@ -123,6 +132,7 @@ class Plot { bool m_lockPrevX = false; bool m_paused = false; float m_viewTime = 10; + bool m_autoHeight = true; int m_height = 300; struct PlotRange { double min = 0; @@ -527,6 +537,13 @@ bool Plot::ReadIni(wpi::StringRef name, wpi::StringRef value) { } m_viewTime = num / 1000.0; return true; + } else if (name == "autoHeight") { + int num; + if (value.getAsInteger(10, num)) { + return true; + } + m_autoHeight = num != 0; + return true; } else if (name == "height") { int num; if (value.getAsInteger(10, num)) { @@ -582,12 +599,12 @@ bool Plot::ReadIni(wpi::StringRef name, wpi::StringRef value) { void Plot::WriteIni(ImGuiTextBuffer* out) { out->appendf( "name=%s\nvisible=%d\nshowPause=%d\nlockPrevX=%d\nlegend=%d\n" - "yaxis2=%d\nyaxis3=%d\nviewTime=%d\nheight=%d\n", + "yaxis2=%d\nyaxis3=%d\nviewTime=%d\nautoHeight=%d\nheight=%d\n", m_name.c_str(), m_visible ? 1 : 0, m_showPause ? 1 : 0, m_lockPrevX ? 1 : 0, (m_plotFlags & ImPlotFlags_NoLegend) ? 0 : 1, (m_plotFlags & ImPlotFlags_YAxis2) ? 1 : 0, (m_plotFlags & ImPlotFlags_YAxis3) ? 1 : 0, - static_cast(m_viewTime * 1000), m_height); + static_cast(m_viewTime * 1000), m_autoHeight ? 1 : 0, m_height); for (int i = 0; i < 3; ++i) { out->appendf( "y%d_min=%d\ny%d_max=%d\ny%d_lockMin=%d\ny%d_lockMax=%d\n" @@ -761,14 +778,34 @@ void Plot::EmitSettings(size_t i) { } ImGui::SetNextItemWidth(ImGui::GetFontSize() * 6); ImGui::InputFloat("View Time (s)", &m_viewTime, 0.1f, 1.0f, "%.1f"); - ImGui::SetNextItemWidth(ImGui::GetFontSize() * 6); - if (ImGui::InputInt("Height", &m_height, 10)) { - if (m_height < 0) { - m_height = 0; + ImGui::Checkbox("Auto Height", &m_autoHeight); + if (!m_autoHeight) { + ImGui::SetNextItemWidth(ImGui::GetFontSize() * 6); + if (ImGui::InputInt("Height", &m_height, 10)) { + if (m_height < 0) { + m_height = 0; + } } } } +int Plot::GetAutoBaseHeight(bool* isAuto, size_t i) { + *isAuto = m_autoHeight; + + if (!m_visible) { + return 0; + } + + int height = m_autoHeight ? 0 : m_height; + + // Pause button + if ((i == 0 || !m_lockPrevX) && m_showPause) { + height += ImGui::GetFrameHeightWithSpacing(); + } + + return height; +} + void PlotView::Display() { if (ImGui::BeginPopupContextItem()) { if (ImGui::Button("Add plot")) { @@ -844,6 +881,27 @@ void PlotView::Display() { auto ref = static_cast(payload->Data); MovePlot(ref->view, ref->plotIndex, 0); } + return; + } + + // Auto-size plots. This requires two passes: the first pass to get the + // total height, the second to actually set the height after averaging it + // across all auto-sized heights. + int availHeight = ImGui::GetContentRegionAvail().y; + int numAuto = 0; + for (size_t i = 0; i < m_plots.size(); ++i) { + bool isAuto; + availHeight -= m_plots[i]->GetAutoBaseHeight(&isAuto, i); + availHeight -= ImGui::GetStyle().ItemSpacing.y; + if (isAuto) { + ++numAuto; + } + } + if (numAuto > 0) { + availHeight /= numAuto; + for (size_t i = 0; i < m_plots.size(); ++i) { + m_plots[i]->SetAutoHeight(availHeight); + } } double now = wpi::Now() * 1.0e-6;