LCOV - code coverage report
Current view: top level - src - GuiWidgets.h (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 85.5 % 62 53
Test Date: 2026-03-01 21:30:38 Functions: 100.0 % 3 3
Branches: 59.4 % 128 76

             Branch data     Line data    Source code
       1                 :             : #ifndef GUIWIDGETS_H
       2                 :             : #define GUIWIDGETS_H
       3                 :             : 
       4                 :             : #ifdef ENABLE_IMGUI
       5                 :             : #include "imgui.h"
       6                 :             : #include "Tooltips.h"
       7                 :             : #include <string>
       8                 :             : #include <algorithm>
       9                 :             : #include <functional>
      10                 :             : #include <cstring>
      11                 :             : 
      12                 :             : namespace GuiWidgets {
      13                 :             : 
      14                 :             :     /**
      15                 :             :      * Represents the result of a widget interaction.
      16                 :             :      * Use this to trigger higher-level logic like auto-save or preset dirtying.
      17                 :             :      */
      18                 :             :     struct Result {
      19                 :             :         bool changed = false;     // True if value was modified this frame
      20                 :             :         bool deactivated = false; // True if interaction finished (mouse release, enter key, or discrete change)
      21                 :             :     };
      22                 :             : 
      23                 :             :     /**
      24                 :             :      * A standardized float slider with label, adaptive arrow-key support, and decorators.
      25                 :             :      */
      26                 :       18671 :     inline Result Float(const char* label, float* v, float min, float max, const char* fmt = "%.2f", const char* tooltip = nullptr, std::function<void()> decorator = nullptr) {
      27                 :       18671 :         Result res;
      28         [ +  - ]:       18671 :         ImGui::Text("%s", label);
      29         [ +  - ]:       18671 :         bool labelHovered = ImGui::IsItemHovered();
      30         [ +  - ]:       18671 :         ImGui::NextColumn();
      31                 :             : 
      32                 :             :         // Render decorator (e.g., latency indicator) above the slider
      33         [ +  + ]:       18671 :         if (decorator) {
      34         [ +  - ]:        2263 :             decorator();
      35                 :             :         }
      36                 :             : 
      37         [ +  - ]:       18671 :         ImGui::SetNextItemWidth(-1);
      38   [ +  -  +  - ]:       18671 :         std::string id = "##" + std::string(label);
      39                 :             : 
      40                 :             :         // Core Slider
      41   [ +  -  -  + ]:       18671 :         if (ImGui::SliderFloat(id.c_str(), v, min, max, fmt)) {
      42                 :           0 :             res.changed = true;
      43                 :             :         }
      44                 :             : 
      45                 :             :         // Detect mouse release or Enter key after a series of edits
      46   [ +  -  -  + ]:       18671 :         if (ImGui::IsItemDeactivatedAfterEdit()) {
      47                 :           0 :             res.deactivated = true;
      48                 :             :         }
      49                 :             : 
      50                 :             :         // Unified Interaction Logic (Arrow Keys & Tooltips)
      51   [ +  -  +  +  :       18671 :         if (ImGui::IsItemHovered() || labelHovered) {
             +  +  +  + ]
      52                 :          59 :             float range = max - min;
      53                 :             :             // Adaptive step size: finer steps for smaller ranges
      54   [ +  +  +  + ]:          59 :             float step = (range > 50.0f) ? 0.5f : (range < 1.0f) ? 0.001f : 0.01f; 
      55                 :             :             
      56                 :          59 :             bool keyChanged = false;
      57                 :             :             // Note: We use IsKeyPressed which supports repeats
      58   [ +  -  -  + ]:          59 :             if (ImGui::IsKeyPressed(ImGuiKey_LeftArrow)) { *v -= step; keyChanged = true; }
      59   [ +  -  -  + ]:          59 :             if (ImGui::IsKeyPressed(ImGuiKey_RightArrow)) { *v += step; keyChanged = true; }
      60                 :             : 
      61         [ -  + ]:          59 :             if (keyChanged) {
      62                 :           0 :                 *v = (std::max)(min, (std::min)(max, *v));
      63                 :           0 :                 res.changed = true;
      64                 :           0 :                 res.deactivated = true; // Arrow keys are discrete adjustments, save immediately
      65                 :             :             }
      66                 :             : 
      67                 :             :             // Show tooltip only if not actively interacting
      68   [ +  -  +  -  :          59 :             if (!keyChanged && !ImGui::IsItemActive()) {
             +  -  +  - ]
      69         [ +  - ]:          59 :                 ImGui::BeginTooltip();
      70   [ +  -  +  - ]:          59 :                 if (tooltip && strlen(tooltip) > 0) {
      71         [ +  - ]:          59 :                     ImGui::Text("%s", tooltip);
      72         [ +  - ]:          59 :                     ImGui::Separator();
      73                 :             :                 }
      74         [ +  - ]:          59 :                 ImGui::Text("%s", Tooltips::FINE_TUNE);
      75         [ +  - ]:          59 :                 ImGui::EndTooltip();
      76                 :             :             }
      77                 :             :         }
      78                 :             : 
      79         [ +  - ]:       18671 :         ImGui::NextColumn();
      80                 :       18671 :         return res;
      81                 :       18671 :     }
      82                 :             : 
      83                 :             :     /**
      84                 :             :      * A standardized checkbox with label and tooltip.
      85                 :             :      */
      86                 :        5282 :     inline Result Checkbox(const char* label, bool* v, const char* tooltip = nullptr) {
      87                 :        5282 :         Result res;
      88         [ +  - ]:        5282 :         ImGui::Text("%s", label);
      89         [ +  - ]:        5282 :         bool labelHovered = ImGui::IsItemHovered();
      90         [ +  - ]:        5282 :         ImGui::NextColumn();
      91   [ +  -  +  - ]:        5282 :         std::string id = "##" + std::string(label);
      92                 :             :         
      93   [ +  -  -  + ]:        5282 :         if (ImGui::Checkbox(id.c_str(), v)) {
      94                 :           0 :             res.changed = true;
      95                 :           0 :             res.deactivated = true; // Checkboxes are immediate
      96                 :             :         }
      97                 :             : 
      98   [ +  +  +  -  :        5282 :         if (tooltip && (ImGui::IsItemHovered() || labelHovered)) {
          +  -  +  +  +  
                      + ]
      99         [ +  - ]:          10 :             ImGui::SetTooltip("%s", tooltip);
     100                 :             :         }
     101                 :             : 
     102         [ +  - ]:        5282 :         ImGui::NextColumn();
     103                 :        5282 :         return res;
     104                 :        5282 :     }
     105                 :             : 
     106                 :             :     /**
     107                 :             :      * A standardized combo box with label and tooltip.
     108                 :             :      */
     109                 :         756 :     inline Result Combo(const char* label, int* v, const char* const items[], int items_count, const char* tooltip = nullptr) {
     110                 :         756 :         Result res;
     111         [ +  - ]:         756 :         ImGui::Text("%s", label);
     112         [ +  - ]:         756 :         bool labelHovered = ImGui::IsItemHovered();
     113         [ +  - ]:         756 :         ImGui::NextColumn();
     114         [ +  - ]:         756 :         ImGui::SetNextItemWidth(-1);
     115   [ +  -  +  - ]:         756 :         std::string id = "##" + std::string(label);
     116                 :             : 
     117   [ +  -  -  + ]:         756 :         if (ImGui::Combo(id.c_str(), v, items, items_count)) {
     118                 :           0 :             res.changed = true;
     119                 :           0 :             res.deactivated = true; // Selection changes are immediate
     120                 :             :         }
     121                 :             : 
     122   [ +  -  +  -  :         756 :         if (tooltip && (ImGui::IsItemHovered() || labelHovered)) {
          +  +  +  +  +  
                      + ]
     123         [ +  - ]:           3 :             ImGui::SetTooltip("%s", tooltip);
     124                 :             :         }
     125                 :             : 
     126         [ +  - ]:         756 :         ImGui::NextColumn();
     127                 :         756 :         return res;
     128                 :         756 :     }
     129                 :             : }
     130                 :             : 
     131                 :             : #endif // ENABLE_IMGUI
     132                 :             : 
     133                 :             : #endif // GUIWIDGETS_H
        

Generated by: LCOV version 2.0-1