Ver Fonte

Disabled: nested tooltips or other non-child window within a BeginDisabled() block disable the disabled state. (#211, #7640)

ocornut há 1 ano atrás
pai
commit
f953ebf9ca
4 ficheiros alterados com 44 adições e 3 exclusões
  1. 2 0
      docs/CHANGELOG.txt
  2. 38 2
      imgui.cpp
  3. 1 1
      imgui.h
  4. 3 0
      imgui_internal.h

+ 2 - 0
docs/CHANGELOG.txt

@@ -49,6 +49,8 @@ Other changes:
   grab scrolls by one page, holding mouse button repeats scrolling. (#7328, #150)
 - Combo: simplified Combo() API uses a list clipper (due to its api it wasn't
   previously trivial before we added clipper.IncludeItemByIndex() function).
+- Disabled: nested tooltips or other non-child window within a BeginDisabled()
+  block disable the disabled state. (#211, #7640)
 - Misc: made ImGuiDir and ImGuiSortDirection stronger-typed enums.
 
 

+ 38 - 2
imgui.cpp

@@ -6648,6 +6648,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
     // [EXPERIMENTAL] Skip Refresh mode
     UpdateWindowSkipRefresh(window);
 
+    // Nested root windows (typically tooltips) override disabled state
+    if (window->RootWindow == window)
+        if ((window->DC.BackupItemDisabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0))
+            BeginDisabledOverrideReenable();
+
     // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
     g.CurrentWindow = NULL;
 
@@ -7259,6 +7264,8 @@ void ImGui::End()
     if (!window->SkipRefresh)
         PopClipRect();   // Inner window clip rectangle
     PopFocusScope();
+    if (window->RootWindow == window && window->DC.BackupItemDisabled)
+        EndDisabledOverrideReenable();
 
     if (window->SkipRefresh)
     {
@@ -7523,7 +7530,7 @@ void ImGui::BeginDisabled(bool disabled)
     }
     if (was_disabled || disabled)
         g.CurrentItemFlags |= ImGuiItemFlags_Disabled;
-    g.ItemFlagsStack.push_back(g.CurrentItemFlags);
+    g.ItemFlagsStack.push_back(g.CurrentItemFlags); // FIXME-OPT: can we simply skip this and use DisabledStackSize?
     g.DisabledStackSize++;
 }
 
@@ -7540,6 +7547,29 @@ void ImGui::EndDisabled()
         g.Style.Alpha = g.DisabledAlphaBackup; //PopStyleVar();
 }
 
+// Could have been called BeginDisabledDisable() but it didn't want to be award nominated for most awkward function name.
+// Ideally we would use a shared e.g. BeginDisabled()->BeginDisabledEx() but earlier needs to be optimal.
+// The whole code for this is awkward, will reevaluate if we find a way to implement SetNextItemDisabled().
+void ImGui::BeginDisabledOverrideReenable()
+{
+    ImGuiContext& g = *GImGui;
+    IM_ASSERT(g.CurrentItemFlags & ImGuiItemFlags_Disabled);
+    g.Style.Alpha = g.DisabledAlphaBackup;
+    g.CurrentItemFlags &= ~ImGuiItemFlags_Disabled;
+    g.ItemFlagsStack.push_back(g.CurrentItemFlags);
+    g.DisabledStackSize++;
+}
+
+void ImGui::EndDisabledOverrideReenable()
+{
+    ImGuiContext& g = *GImGui;
+    g.DisabledStackSize--;
+    IM_ASSERT(g.DisabledStackSize > 0);
+    g.ItemFlagsStack.pop_back();
+    g.CurrentItemFlags = g.ItemFlagsStack.back();
+    g.Style.Alpha = g.DisabledAlphaBackup * g.Style.DisabledAlpha;
+}
+
 void ImGui::PushTabStop(bool tab_stop)
 {
     PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop);
@@ -9995,7 +10025,13 @@ void    ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo
     while (g.DisabledStackSize > stack_sizes->SizeOfDisabledStack) //-V1044
     {
         if (log_callback) log_callback(user_data, "Recovered from missing EndDisabled() in '%s'", window->Name);
-        EndDisabled();
+        if (g.CurrentItemFlags & ImGuiItemFlags_Disabled)
+            EndDisabled();
+        else
+        {
+            EndDisabledOverrideReenable();
+            window->DC.BackupItemDisabled = false;
+        }
     }
     while (g.ColorStack.Size > stack_sizes->SizeOfColorStack)
     {

+ 1 - 1
imgui.h

@@ -28,7 +28,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.90.8 WIP"
-#define IMGUI_VERSION_NUM   19072
+#define IMGUI_VERSION_NUM   19073
 #define IMGUI_HAS_TABLE
 
 /*

+ 3 - 0
imgui_internal.h

@@ -2472,6 +2472,7 @@ struct IMGUI_API ImGuiWindowTempData
     bool                    NavWindowHasScrollY;    // Set per window when scrolling can be used (== ScrollMax.y > 0.0f)
 
     // Miscellaneous
+    bool                    BackupItemDisabled;     // Non-child window override disabled flag
     bool                    MenuBarAppending;       // FIXME: Remove this
     ImVec2                  MenuBarOffset;          // MenuBarOffset.x is sort of equivalent of a per-layer CursorPos.x, saved/restored as we switch to the menu bar. The only situation when MenuBarOffset.y is > 0 if when (SafeAreaPadding.y > FramePadding.y), often used on TVs.
     ImGuiMenuColumns        MenuColumns;            // Simplified columns storage for menu items measurement
@@ -3127,6 +3128,8 @@ namespace ImGui
     IMGUI_API void          PushItemFlag(ImGuiItemFlags option, bool enabled);
     IMGUI_API void          PopItemFlag();
     IMGUI_API const ImGuiDataVarInfo* GetStyleVarInfo(ImGuiStyleVar idx);
+    IMGUI_API void          BeginDisabledOverrideReenable();
+    IMGUI_API void          EndDisabledOverrideReenable();
 
     // Logging/Capture
     IMGUI_API void          LogBegin(ImGuiLogType type, int auto_open_depth);           // -> BeginCapture() when we design v2 api, for now stay under the radar by using the old name.