diff --git a/src/app.cpp b/src/app.cpp index 81c6459..716ada6 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -341,8 +341,8 @@ void App::render_settings_modal() { ImGui::SetNextWindowSize(ImVec2(800, 500), ImGuiCond_Appearing); if (ImGui::BeginPopupModal("Settings", &show_settings_)) { - const char* tab_labels[] = {"General", "Timeline", "Rendering", "Source", "Keyboard"}; - constexpr int kTabCount = 5; + const char* tab_labels[] = {"General", "Timeline", "Flamegraph", "Rendering", "Source", "Keyboard"}; + constexpr int kTabCount = 6; constexpr float kSidebarWidth = 140.0f; const float footer_height = ImGui::GetFrameHeightWithSpacing() + ImGui::GetStyle().ItemSpacing.y; @@ -437,7 +437,26 @@ void App::render_settings_modal() { } break; } - case 2: { // Rendering + case 2: { // Flamegraph + ImGui::SeparatorText("Layout"); + + constexpr auto fg_clamp = ImGuiSliderFlags_AlwaysClamp; + float fv = view_.flame_bar_height(); + if (ImGui::DragFloat("Bar Height", &fv, 1.0f, 10.0f, 100.0f, "%.0f px", fg_clamp)) + view_.set_flame_bar_height(fv); + fv = view_.flame_bar_gap(); + if (ImGui::DragFloat("Bar Gap", &fv, 0.5f, 0.0f, 10.0f, "%.0f px", fg_clamp)) + view_.set_flame_bar_gap(fv); + + ImGui::Spacing(); + ImGui::Spacing(); + if (ImGui::Button("Reset to Defaults")) { + view_.set_flame_bar_height(ViewState::kDefaultFlameBarHeight); + view_.set_flame_bar_gap(ViewState::kDefaultFlameBarGap); + } + break; + } + case 3: { // Rendering { bool show = view_.show_flows(); if (ImGui::Checkbox("Show Flow Arrows", &show)) view_.set_show_flows(show); @@ -456,7 +475,7 @@ void App::render_settings_modal() { } break; } - case 3: { // Source + case 4: { // Source source_.render_settings(); ImGui::Spacing(); @@ -466,7 +485,7 @@ void App::render_settings_modal() { } break; } - case 4: { // Keyboard + case 5: { // Keyboard view_.key_bindings().render_settings(); ImGui::Spacing(); @@ -537,6 +556,8 @@ void App::save_settings() { j["ruler_height"] = view_.ruler_height(); j["proc_header_height"] = view_.proc_header_height(); j["scrollbar_scale"] = view_.scrollbar_scale(); + j["flame_bar_height"] = view_.flame_bar_height(); + j["flame_bar_gap"] = view_.flame_bar_gap(); j["sel_border_color"] = {view_.sel_border_color()[0], view_.sel_border_color()[1], view_.sel_border_color()[2], view_.sel_border_color()[3]}; j["dark_theme"] = dark_theme_; @@ -572,6 +593,8 @@ void App::load_settings() { if (j.contains("ruler_height")) view_.set_ruler_height(j["ruler_height"].get()); if (j.contains("proc_header_height")) view_.set_proc_header_height(j["proc_header_height"].get()); if (j.contains("scrollbar_scale")) view_.set_scrollbar_scale(j["scrollbar_scale"].get()); + if (j.contains("flame_bar_height")) view_.set_flame_bar_height(j["flame_bar_height"].get()); + if (j.contains("flame_bar_gap")) view_.set_flame_bar_gap(j["flame_bar_gap"].get()); if (j.contains("sel_border_color")) { auto& arr = j["sel_border_color"]; std::array col; diff --git a/src/ui/INDEX.md b/src/ui/INDEX.md index c07d51d..5581535 100644 --- a/src/ui/INDEX.md +++ b/src/ui/INDEX.md @@ -27,6 +27,7 @@ int32_t search_current() const; void set_search_current(int32_t); // Layout defaults static constexpr float kDefaultTrackHeight, kDefaultTrackPadding, kDefaultCounterTrackHeight; static constexpr float kDefaultLabelWidth, kDefaultRulerHeight, kDefaultProcHeaderHeight, kDefaultScrollbarScale; +static constexpr float kDefaultFlameBarHeight, kDefaultFlameBarGap; // Layout float track_height() const; void set_track_height(float); float track_padding() const; void set_track_padding(float); @@ -35,6 +36,8 @@ float label_width() const; void set_label_width(float); float ruler_height() const; void set_ruler_height(float); float proc_header_height() const; void set_proc_header_height(float); float scrollbar_scale() const; void set_scrollbar_scale(float); +float flame_bar_height() const; void set_flame_bar_height(float); +float flame_bar_gap() const; void set_flame_bar_gap(float); void reset_layout_defaults(); // Rendering defaults static constexpr bool kDefaultShowFlows; static constexpr std::array kDefaultSelBorderColor; diff --git a/src/ui/flame_graph_panel.cpp b/src/ui/flame_graph_panel.cpp index e8be8f2..46cbdf6 100644 --- a/src/ui/flame_graph_panel.cpp +++ b/src/ui/flame_graph_panel.cpp @@ -355,7 +355,7 @@ void FlameGraphPanel::render_icicle(const TraceModel& model, ViewState& view, in ImGui::Separator(); } - constexpr float BAR_H = 20.0f, BAR_GAP = 1.0f; + const float BAR_H = view.flame_bar_height(), BAR_GAP = view.flame_bar_gap(); float canvas_w = ImGui::GetContentRegionAvail().x; if (canvas_w < 10.0f) return; diff --git a/src/ui/view_state.h b/src/ui/view_state.h index d7b3323..9231b9e 100644 --- a/src/ui/view_state.h +++ b/src/ui/view_state.h @@ -87,6 +87,8 @@ class ViewState { static constexpr float kDefaultRulerHeight = 37.0f; static constexpr float kDefaultProcHeaderHeight = 36.0f; static constexpr float kDefaultScrollbarScale = 1.3f; + static constexpr float kDefaultFlameBarHeight = 20.0f; + static constexpr float kDefaultFlameBarGap = 1.0f; // --- Layout --- float track_height() const { return track_height_; } @@ -103,6 +105,10 @@ class ViewState { void set_proc_header_height(float h) { proc_header_height_ = h; } float scrollbar_scale() const { return scrollbar_scale_; } void set_scrollbar_scale(float s) { scrollbar_scale_ = s; } + float flame_bar_height() const { return flame_bar_height_; } + void set_flame_bar_height(float h) { flame_bar_height_ = h; } + float flame_bar_gap() const { return flame_bar_gap_; } + void set_flame_bar_gap(float g) { flame_bar_gap_ = g; } void reset_layout_defaults() { track_height_ = kDefaultTrackHeight; @@ -112,6 +118,8 @@ class ViewState { ruler_height_ = kDefaultRulerHeight; proc_header_height_ = kDefaultProcHeaderHeight; scrollbar_scale_ = kDefaultScrollbarScale; + flame_bar_height_ = kDefaultFlameBarHeight; + flame_bar_gap_ = kDefaultFlameBarGap; } // --- Rendering defaults --- @@ -215,6 +223,8 @@ class ViewState { float ruler_height_ = kDefaultRulerHeight; float proc_header_height_ = kDefaultProcHeaderHeight; float scrollbar_scale_ = kDefaultScrollbarScale; + float flame_bar_height_ = kDefaultFlameBarHeight; + float flame_bar_gap_ = kDefaultFlameBarGap; std::array sel_border_color_ = kDefaultSelBorderColor; bool show_flows_ = kDefaultShowFlows; bool time_unit_ns_ = false; diff --git a/tests/test_view_state.cpp b/tests/test_view_state.cpp index 18d896b..77d6eed 100644 --- a/tests/test_view_state.cpp +++ b/tests/test_view_state.cpp @@ -9,6 +9,21 @@ TEST(ViewState, DefaultValues) { EXPECT_DOUBLE_EQ(vs.view_end_ts(), 1000.0); EXPECT_EQ(vs.selected_event_idx(), -1); EXPECT_TRUE(vs.show_flows()); + EXPECT_FLOAT_EQ(vs.flame_bar_height(), ViewState::kDefaultFlameBarHeight); + EXPECT_FLOAT_EQ(vs.flame_bar_gap(), ViewState::kDefaultFlameBarGap); +} + +TEST(ViewState, FlameBarHeightConfigurable) { + ViewState vs; + vs.set_flame_bar_height(30.0f); + EXPECT_FLOAT_EQ(vs.flame_bar_height(), 30.0f); + + vs.set_flame_bar_gap(3.0f); + EXPECT_FLOAT_EQ(vs.flame_bar_gap(), 3.0f); + + vs.reset_layout_defaults(); + EXPECT_FLOAT_EQ(vs.flame_bar_height(), ViewState::kDefaultFlameBarHeight); + EXPECT_FLOAT_EQ(vs.flame_bar_gap(), ViewState::kDefaultFlameBarGap); } TEST(ViewState, TimeToX) {