From 69d0d3345107ee0e26d767a236825465338a8310 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 25 Sep 2017 22:45:10 +0200 Subject: [PATCH 1/6] Exposed PushMultiItemsWidths() to imgui_internal.h --- imgui.cpp | 7 +++---- imgui_internal.h | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1e5f9c16..f392fc1c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -592,7 +592,6 @@ static void LogRenderedText(const ImVec2& ref_pos, const char* text, const char* text_end = NULL); -static void PushMultiItemsWidths(int components, float w_full = 0.0f); static float GetDraggedColumnOffset(int column_index); static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true); @@ -4676,12 +4675,12 @@ void ImGui::PushItemWidth(float item_width) window->DC.ItemWidthStack.push_back(window->DC.ItemWidth); } -static void PushMultiItemsWidths(int components, float w_full) +void ImGui::PushMultiItemsWidths(int components, float w_full) { - ImGuiWindow* window = ImGui::GetCurrentWindow(); + ImGuiWindow* window = GetCurrentWindow(); const ImGuiStyle& style = GImGui->Style; if (w_full <= 0.0f) - w_full = ImGui::CalcItemWidth(); + w_full = CalcItemWidth(); const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); window->DC.ItemWidthStack.push_back(w_item_last); diff --git a/imgui_internal.h b/imgui_internal.h index 63bbb043..cd78dbbd 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -772,6 +772,7 @@ namespace ImGui IMGUI_API void FocusableItemUnregister(ImGuiWindow* window); IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y); IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); + IMGUI_API void PushMultiItemsWidths(int components, float width_full = 0.0f); IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); IMGUI_API void PopItemFlag(); From 82748df71af117605768c121652da90406e052bb Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 26 Sep 2017 01:12:09 +0200 Subject: [PATCH 2/6] WantCaptureMouse: Tweaked logic so WantCaptureMouse can stay false when e.g. hovering over void while an InputText() is active. (#621) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index f392fc1c..f212e76e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2295,7 +2295,7 @@ void ImGui::NewFrame() if (g.WantCaptureMouseNextFrame != -1) g.IO.WantCaptureMouse = (g.WantCaptureMouseNextFrame != 0); else - g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (g.ActiveId != 0) || (!g.OpenPopupStack.empty()); + g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (!g.OpenPopupStack.empty()); g.IO.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != -1) ? (g.WantCaptureKeyboardNextFrame != 0) : (g.ActiveId != 0); g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : 0; g.MouseCursor = ImGuiMouseCursor_Arrow; From 99b9f1c93c4fd8ae6edb707bd8e22c7ca58e3d7a Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 26 Sep 2017 11:23:06 +0200 Subject: [PATCH 3/6] Fix static misusage error with decent compilers. Error introduced in 4b82759598e34aed179177ecaa00e774c0d23484 --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 4bfa9430..c6008ff6 100644 --- a/imgui.h +++ b/imgui.h @@ -488,7 +488,7 @@ namespace ImGui // Obsolete functions (Will be removed! Also see 'API BREAKING CHANGES' section in imgui.cpp) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - static void SetNextWindowPosCenter(ImGuiCond cond = 0); // OBSOLETE 1.52+ + void SetNextWindowPosCenter(ImGuiCond cond = 0); // OBSOLETE 1.52+ static inline bool IsItemHoveredRect() { return IsItemRectHovered(); } // OBSOLETE 1.51+ static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // OBSOLETE 1.51+. This was partly broken. You probably wanted to use ImGui::GetIO().WantCaptureMouse instead. static inline bool IsMouseHoveringAnyWindow() { return IsAnyWindowHovered(); } // OBSOLETE 1.51+ From 728deff56c68baf06125bd0074bcda2095b92a00 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 26 Sep 2017 15:33:57 +0200 Subject: [PATCH 4/6] Comments, debug code (commented), todo list --- TODO.txt | 5 +++-- imgui.cpp | 8 ++++++-- imgui.h | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/TODO.txt b/TODO.txt index 0369c637..92535d08 100644 --- a/TODO.txt +++ b/TODO.txt @@ -169,7 +169,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - tree node: tweak color scheme to distinguish headers from selected tree node (#581) !- settings: expose enough to save/load .ini from RAM instead of fopen - - settings: write more decent code to allow saving/loading new fields + - settings: write more decent code to allow saving/loading new fields: columns, selected tree nodes? - settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file (#437) - stb: add defines to disable stb implementations @@ -231,7 +231,8 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - misc: fix for compilation settings where stdcall isn't the default (e.g. vectorcall) (#1230) - remote: make a system like RemoteImGui first-class citizen/project (#75) - - demo: demo: add a virtual scrolling example? + - demo: add vertical separator demo + - demo: add a virtual scrolling example? - examples: directx9: save/restore device state more thoroughly. - examples: window minimize, maximize (#583) - examples: provide a zero-framerate/idle example. diff --git a/imgui.cpp b/imgui.cpp index f212e76e..621f763a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1912,12 +1912,12 @@ void ImGui::ItemSize(const ImVec2& size, float text_offset_y) ImGuiContext& g = *GImGui; const float line_height = ImMax(window->DC.CurrentLineHeight, size.y); const float text_base_offset = ImMax(window->DC.CurrentLineTextBaseOffset, text_offset_y); + //if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG] window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y); window->DC.CursorPos = ImVec2((float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX), (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y)); window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x); window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y); - - //window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // Debug + //if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG] window->DC.PrevLineHeight = line_height; window->DC.PrevLineTextBaseOffset = text_base_offset; @@ -1941,6 +1941,7 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false; if (IsClippedEx(bb, id, false)) return false; + //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] // Setting LastItemHoveredAndUsable for IsItemHovered(). This is a sensible default, but widgets are free to override it. if (IsMouseHoveringRect(bb.Min, bb.Max)) @@ -9053,6 +9054,8 @@ bool ImGui::BeginMenu(const char* label, bool enabled) ImVec2 popup_pos, pos = window->DC.CursorPos; if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) { + // Menu inside an horizontal menu bar + // Selectable extend their highlight by half ItemSpacing in each direction. popup_pos = ImVec2(pos.x - window->WindowPadding.x, pos.y - style.FramePadding.y + window->MenuBarHeight()); window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f); PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing * 2.0f); @@ -9064,6 +9067,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) } else { + // Menu inside a menu popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y); float w = window->MenuColumns.DeclColumns(label_size.x, 0.0f, (float)(int)(g.FontSize * 1.20f)); // Feedback to next frame float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); diff --git a/imgui.h b/imgui.h index c6008ff6..081cf8e4 100644 --- a/imgui.h +++ b/imgui.h @@ -381,7 +381,7 @@ namespace ImGui // Menus IMGUI_API bool BeginMainMenuBar(); // create and append to a full screen menu-bar. only call EndMainMenuBar() if this returns true! IMGUI_API void EndMainMenuBar(); - IMGUI_API bool BeginMenuBar(); // append to menu-bar of current window (requires ImGuiWindowFlags_MenuBar flag set). only call EndMenuBar() if this returns true! + IMGUI_API bool BeginMenuBar(); // append to menu-bar of current window (requires ImGuiWindowFlags_MenuBar flag set on parent window). only call EndMenuBar() if this returns true! IMGUI_API void EndMenuBar(); IMGUI_API bool BeginMenu(const char* label, bool enabled = true); // create a sub-menu entry. only call EndMenu() if this returns true! IMGUI_API void EndMenu(); From c7a606ab7ee67f01f49ee93084d03ea72d3d52b3 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 26 Sep 2017 15:42:55 +0200 Subject: [PATCH 5/6] Horizontal layout does the minimum job to be usable internally - not exposed (#97) --- imgui.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 621f763a..7668c88a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1922,6 +1922,10 @@ void ImGui::ItemSize(const ImVec2& size, float text_offset_y) window->DC.PrevLineHeight = line_height; window->DC.PrevLineTextBaseOffset = text_base_offset; window->DC.CurrentLineHeight = window->DC.CurrentLineTextBaseOffset = 0.0f; + + // Horizontal layout mode + if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) + SameLine(); } void ImGui::ItemSize(const ImRect& bb, float text_offset_y) @@ -9062,8 +9066,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) float w = label_size.x; pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); PopStyleVar(); - SameLine(); - window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f); + window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). } else { @@ -10053,10 +10056,15 @@ void ImGui::NewLine() ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; + + ImGuiContext& g = *GImGui; + const ImGuiLayoutType backup_layout_type = window->DC.LayoutType; + window->DC.LayoutType = ImGuiLayoutType_Vertical; if (window->DC.CurrentLineHeight > 0.0f) // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height. ItemSize(ImVec2(0,0)); else - ItemSize(ImVec2(0.0f, GImGui->FontSize)); + ItemSize(ImVec2(0.0f, g.FontSize)); + window->DC.LayoutType = backup_layout_type; } void ImGui::NextColumn() From be03882a15b0a785dffba08a95fb265db23ffc14 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 26 Sep 2017 15:43:48 +0200 Subject: [PATCH 6/6] Separator(): output vertical separator when used in horizontal layout mode, so it works in menu bars. --- imgui.cpp | 67 +++++++++++++++++++++++++++++++++--------------- imgui_internal.h | 7 +++++ 2 files changed, 53 insertions(+), 21 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7668c88a..4aafd884 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9893,37 +9893,62 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl // Horizontal separating line. void ImGui::Separator() { + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; - if (window->DC.ColumnsCount > 1) - PopClipRect(); + ImGuiWindowFlags flags = 0; + if ((flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical)) == 0) + { + if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) + flags |= ImGuiSeparatorFlags_Vertical; + else + flags |= ImGuiSeparatorFlags_Horizontal; + } + IM_ASSERT(ImIsPowerOfTwo((int)(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical)))); // Check that only 1 option is selected - float x1 = window->Pos.x; - float x2 = window->Pos.x + window->Size.x; - if (!window->DC.GroupStack.empty()) - x1 += window->DC.IndentX; - - const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y+1.0f)); - ItemSize(ImVec2(0.0f, 0.0f)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit, we don't provide height to not alter layout. - if (!ItemAdd(bb, NULL)) + if (flags & ImGuiSeparatorFlags_Horizontal) { if (window->DC.ColumnsCount > 1) + PopClipRect(); + + float x1 = window->Pos.x; + float x2 = window->Pos.x + window->Size.x; + if (!window->DC.GroupStack.empty()) + x1 += window->DC.IndentX; + + const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y+1.0f)); + ItemSize(ImVec2(0.0f, 0.0f)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit, we don't provide height to not alter layout. + if (!ItemAdd(bb, NULL)) + { + if (window->DC.ColumnsCount > 1) + PushColumnClipRect(); + return; + } + + window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x,bb.Min.y), GetColorU32(ImGuiCol_Separator)); + + if (g.LogEnabled) + LogText(IM_NEWLINE "--------------------------------"); + + if (window->DC.ColumnsCount > 1) + { PushColumnClipRect(); - return; + window->DC.ColumnsCellMinY = window->DC.CursorPos.y; + } } - - window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x,bb.Min.y), GetColorU32(ImGuiCol_Separator)); - - ImGuiContext& g = *GImGui; - if (g.LogEnabled) - LogText(IM_NEWLINE "--------------------------------"); - - if (window->DC.ColumnsCount > 1) + else if (flags & ImGuiSeparatorFlags_Vertical) { - PushColumnClipRect(); - window->DC.ColumnsCellMinY = window->DC.CursorPos.y; + const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(1.0f, window->DC.CurrentLineHeight)); + ItemSize(ImVec2(bb.GetWidth(), 0.0f)); + if (!ItemAdd(bb, NULL)) + return; + + window->DrawList->AddLine(ImVec2(bb.Min.x, bb.Min.y), ImVec2(bb.Min.x, bb.Max.y), GetColorU32(ImGuiCol_Separator)); + + if (g.LogEnabled) + LogText("|"); } } diff --git a/imgui_internal.h b/imgui_internal.h index cd78dbbd..0e779a2a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -48,6 +48,7 @@ typedef int ImGuiLayoutType; // enum ImGuiLayoutType_ typedef int ImGuiButtonFlags; // enum ImGuiButtonFlags_ typedef int ImGuiTreeNodeFlags; // enum ImGuiTreeNodeFlags_ typedef int ImGuiSliderFlags; // enum ImGuiSliderFlags_ +typedef int ImGuiSeparatorFlags; // enum ImGuiSeparatorFlags_ typedef int ImGuiItemFlags; // enum ImGuiItemFlags_ //------------------------------------------------------------------------- @@ -203,6 +204,12 @@ enum ImGuiSelectableFlagsPrivate_ ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 6 }; +enum ImGuiSeparatorFlags_ +{ + ImGuiSeparatorFlags_Horizontal = 1 << 0, // Axis default to current layout type, so generally Horizontal unless e.g. in a menu bar + ImGuiSeparatorFlags_Vertical = 1 << 1 +}; + // FIXME: this is in development, not exposed/functional as a generic feature yet. enum ImGuiLayoutType_ {