From 027ffd91ead699e577dd294030158a4307d0b0df Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 23:49:04 +0100 Subject: [PATCH 01/11] IsWindowFocused(): oops, that was bound to happen with loosely typed enums (this is sort of why I made both values identical - no direct side effects). --- imgui.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b032d549..c20916ef 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5521,13 +5521,13 @@ bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags) ImGuiContext& g = *GImGui; IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() - switch (flags & (ImGuiFocusedFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) + switch (flags & (ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows)) { - case ImGuiFocusedFlags_RootWindow | ImGuiHoveredFlags_ChildWindows: + case ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows: return g.NavWindow && g.CurrentWindow->RootWindow == g.NavWindow->RootWindow; case ImGuiFocusedFlags_RootWindow: return g.CurrentWindow->RootWindow == g.NavWindow; - case ImGuiHoveredFlags_ChildWindows: + case ImGuiFocusedFlags_ChildWindows: return g.NavWindow && IsWindowChildOf(g.NavWindow, g.CurrentWindow); default: return g.CurrentWindow == g.NavWindow; From 78320aa633a2bb107d3da7925d7f4ab1cdd65704 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 18:37:58 +0100 Subject: [PATCH 02/11] Columns: Refactor: Moved columns data into their own data structure. Minimum changes now to ease diffing. (#125, #1499) --- imgui.cpp | 214 ++++++++++++++++++++++++++--------------------- imgui_internal.h | 70 +++++++++------- 2 files changed, 158 insertions(+), 126 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c20916ef..bc60f574 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -627,8 +627,6 @@ // Forward Declarations //------------------------------------------------------------------------- -static float GetDraggedColumnOffset(int column_index); - static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true); static ImFont* GetDefaultFont(); @@ -1744,8 +1742,8 @@ static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height) ImGuiWindow* window = ImGui::GetCurrentWindow(); window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHere() can properly function after the end of our clipper usage. window->DC.PrevLineHeight = (line_height - GImGui->Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list. - if (window->DC.ColumnsCount > 1) - window->DC.ColumnsCellMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly + if (window->DC.ColumnsSet) + window->DC.ColumnsSet->ColumnsCellMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly } // Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1 @@ -4833,11 +4831,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.ItemFlagsStack.resize(0); window->DC.ItemWidthStack.resize(0); window->DC.TextWrapPosStack.resize(0); - window->DC.ColumnsCurrent = 0; - window->DC.ColumnsCount = 1; - window->DC.ColumnsStartPosY = window->DC.CursorPos.y; - window->DC.ColumnsStartMaxPosX = window->DC.CursorMaxPos.x; - window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.ColumnsStartPosY; + window->DC.ColumnsSet = NULL; window->DC.TreeDepth = 0; window->DC.StateStorage = &window->StateStorage; window->DC.GroupStack.resize(0); @@ -4990,7 +4984,7 @@ void ImGui::End() ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - if (window->DC.ColumnsCount != 1) // close columns set if any is open + if (window->DC.ColumnsSet != NULL) EndColumns(); PopClipRect(); // inner window clip rectangle @@ -5736,8 +5730,8 @@ ImVec2 ImGui::GetContentRegionMax() { ImGuiWindow* window = GetCurrentWindowRead(); ImVec2 mx = window->ContentsRegionRect.Max; - if (window->DC.ColumnsCount != 1) - mx.x = GetColumnOffset(window->DC.ColumnsCurrent + 1) - window->WindowPadding.x; + if (window->DC.ColumnsSet) + mx.x = GetColumnOffset(window->DC.ColumnsSet->ColumnsCurrent + 1) - window->WindowPadding.x; return mx; } @@ -9347,7 +9341,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) // FIXME-OPT: Avoid if vertically clipped. + if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet) // FIXME-OPT: Avoid if vertically clipped. PopClipRect(); ImGuiID id = window->GetID(label); @@ -9378,7 +9372,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl bb_with_spacing.Max.y += spacing_D; if (!ItemAdd(bb_with_spacing, id)) { - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) + if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet) PushColumnClipRect(); return false; } @@ -9400,7 +9394,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl RenderFrame(bb_with_spacing.Min, bb_with_spacing.Max, col, false, 0.0f); } - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) + if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet) { PushColumnClipRect(); bb_with_spacing.Max.x -= (GetContentRegionMax().x - max_x); @@ -10552,7 +10546,7 @@ void ImGui::Separator() } // Horizontal Separator - if (window->DC.ColumnsCount > 1) + if (window->DC.ColumnsSet) PopClipRect(); float x1 = window->Pos.x; @@ -10564,7 +10558,7 @@ void ImGui::Separator() 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, 0)) { - if (window->DC.ColumnsCount > 1) + if (window->DC.ColumnsSet) PushColumnClipRect(); return; } @@ -10574,10 +10568,10 @@ void ImGui::Separator() if (g.LogEnabled) LogRenderedText(NULL, IM_NEWLINE "--------------------------------"); - if (window->DC.ColumnsCount > 1) + if (window->DC.ColumnsSet) { PushColumnClipRect(); - window->DC.ColumnsCellMinY = window->DC.CursorPos.y; + window->DC.ColumnsSet->ColumnsCellMinY = window->DC.CursorPos.y; } } @@ -10790,29 +10784,30 @@ void ImGui::NewLine() void ImGui::NextColumn() { ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems || window->DC.ColumnsCount <= 1) + if (window->SkipItems || window->DC.ColumnsSet == NULL) return; ImGuiContext& g = *GImGui; PopItemWidth(); PopClipRect(); - window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); - if (++window->DC.ColumnsCurrent < window->DC.ColumnsCount) + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + columns->ColumnsCellMaxY = ImMax(columns->ColumnsCellMaxY, window->DC.CursorPos.y); + if (++columns->ColumnsCurrent < columns->ColumnsCount) { // Columns 1+ cancel out IndentX - window->DC.ColumnsOffsetX = GetColumnOffset(window->DC.ColumnsCurrent) - window->DC.IndentX + g.Style.ItemSpacing.x; - window->DrawList->ChannelsSetCurrent(window->DC.ColumnsCurrent); + window->DC.ColumnsOffsetX = GetColumnOffset(columns->ColumnsCurrent) - window->DC.IndentX + g.Style.ItemSpacing.x; + window->DrawList->ChannelsSetCurrent(columns->ColumnsCurrent); } else { - window->DC.ColumnsCurrent = 0; window->DC.ColumnsOffsetX = 0.0f; - window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY; + columns->ColumnsCurrent = 0; + columns->ColumnsCellMinY = columns->ColumnsCellMaxY; window->DrawList->ChannelsSetCurrent(0); } window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); - window->DC.CursorPos.y = window->DC.ColumnsCellMinY; + window->DC.CursorPos.y = columns->ColumnsCellMinY; window->DC.CurrentLineHeight = 0.0f; window->DC.CurrentLineTextBaseOffset = 0.0f; @@ -10823,37 +10818,37 @@ void ImGui::NextColumn() int ImGui::GetColumnIndex() { ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.ColumnsCurrent; + return window->DC.ColumnsSet ? window->DC.ColumnsSet->ColumnsCurrent : 0; } int ImGui::GetColumnsCount() { ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.ColumnsCount; + return window->DC.ColumnsSet ? window->DC.ColumnsSet->ColumnsCount : 1; } -static float OffsetNormToPixels(ImGuiWindow* window, float offset_norm) +static float OffsetNormToPixels(const ImGuiColumnsSet* columns, float offset_norm) { - return offset_norm * (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); + return offset_norm * (columns->ColumnsMaxX - columns->ColumnsMinX); } -static float PixelsToOffsetNorm(ImGuiWindow* window, float offset) +static float PixelsToOffsetNorm(const ImGuiColumnsSet* columns, float offset) { - return (offset - window->DC.ColumnsMinX) / (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); + return (offset - columns->ColumnsMinX) / (columns->ColumnsMaxX - columns->ColumnsMinX); } -static float GetDraggedColumnOffset(int column_index) +static float GetDraggedColumnOffset(ImGuiColumnsSet* columns, int column_index) { // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning. ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(column_index > 0); // We cannot drag column 0. If you get this assert you may have a conflict between the ID of your columns and another widgets. - IM_ASSERT(g.ActiveId == window->DC.ColumnsSetId + ImGuiID(column_index)); + IM_ASSERT(g.ActiveId == columns->ColumnsSetId + ImGuiID(column_index)); float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x - window->Pos.x; x = ImMax(x, ImGui::GetColumnOffset(column_index-1) + g.Style.ColumnsMinSpacing); - if ((window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths)) + if ((columns->ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths)) x = ImMin(x, ImGui::GetColumnOffset(column_index+1) - g.Style.ColumnsMinSpacing); return x; @@ -10862,44 +10857,50 @@ static float GetDraggedColumnOffset(int column_index) float ImGui::GetColumnOffset(int column_index) { ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); + if (column_index < 0) - column_index = window->DC.ColumnsCurrent; + column_index = columns->ColumnsCurrent; /* if (g.ActiveId) { ImGuiContext& g = *GImGui; - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); + const ImGuiID column_id = columns->ColumnsSetId + ImGuiID(column_index); if (g.ActiveId == column_id) - return GetDraggedColumnOffset(column_index); + return GetDraggedColumnOffset(columns, column_index); } */ - IM_ASSERT(column_index < window->DC.ColumnsData.Size); - const float t = window->DC.ColumnsData[column_index].OffsetNorm; - const float x_offset = ImLerp(window->DC.ColumnsMinX, window->DC.ColumnsMaxX, t); + IM_ASSERT(column_index < columns->ColumnsData.Size); + const float t = columns->ColumnsData[column_index].OffsetNorm; + const float x_offset = ImLerp(columns->ColumnsMinX, columns->ColumnsMaxX, t); return x_offset; } void ImGui::SetColumnOffset(int column_index, float offset) { ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow* window = g.CurrentWindow; + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); + if (column_index < 0) - column_index = window->DC.ColumnsCurrent; + column_index = columns->ColumnsCurrent; - IM_ASSERT(column_index < window->DC.ColumnsData.Size); + IM_ASSERT(column_index < columns->ColumnsData.Size); - const bool preserve_width = !(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < window->DC.ColumnsCount-1); + const bool preserve_width = !(columns->ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->ColumnsCount-1); const float width = preserve_width ? GetColumnWidth(column_index) : 0.0f; - if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) - offset = ImMin(offset, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index)); - const float offset_norm = PixelsToOffsetNorm(window, offset); + if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) + offset = ImMin(offset, columns->ColumnsMaxX - g.Style.ColumnsMinSpacing * (columns->ColumnsCount - column_index)); + const float offset_norm = PixelsToOffsetNorm(columns, offset); - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); + const ImGuiID column_id = columns->ColumnsSetId + ImGuiID(column_index); window->DC.StateStorage->SetFloat(column_id, offset_norm); - window->DC.ColumnsData[column_index].OffsetNorm = offset_norm; + columns->ColumnsData[column_index].OffsetNorm = offset_norm; if (preserve_width) SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); @@ -10908,70 +10909,91 @@ void ImGui::SetColumnOffset(int column_index, float offset) float ImGui::GetColumnWidth(int column_index) { ImGuiWindow* window = GetCurrentWindowRead(); - if (column_index < 0) - column_index = window->DC.ColumnsCurrent; + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); - return OffsetNormToPixels(window, window->DC.ColumnsData[column_index+1].OffsetNorm - window->DC.ColumnsData[column_index].OffsetNorm); + if (column_index < 0) + column_index = columns->ColumnsCurrent; + return OffsetNormToPixels(columns, columns->ColumnsData[column_index+1].OffsetNorm - columns->ColumnsData[column_index].OffsetNorm); } void ImGui::SetColumnWidth(int column_index, float width) { ImGuiWindow* window = GetCurrentWindowRead(); - if (column_index < 0) - column_index = window->DC.ColumnsCurrent; + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); + if (column_index < 0) + column_index = columns->ColumnsCurrent; SetColumnOffset(column_index+1, GetColumnOffset(column_index) + width); } void ImGui::PushColumnClipRect(int column_index) { ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiColumnsSet* columns = window->DC.ColumnsSet; if (column_index < 0) - column_index = window->DC.ColumnsCurrent; + column_index = columns->ColumnsCurrent; - PushClipRect(window->DC.ColumnsData[column_index].ClipRect.Min, window->DC.ColumnsData[column_index].ClipRect.Max, false); + PushClipRect(columns->ColumnsData[column_index].ClipRect.Min, columns->ColumnsData[column_index].ClipRect.Max, false); } -void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags flags) +static ImGuiColumnsSet* FindOrAddColumnsSet(ImGuiWindow* window, ImGuiID id) +{ + for (int n = 0; n < window->DC.ColumnsSets.Size; n++) + if (window->DC.ColumnsSets[n].ColumnsSetId == id) + return &window->DC.ColumnsSets[n]; + + window->DC.ColumnsSets.push_back(ImGuiColumnsSet()); + ImGuiColumnsSet* columns = &window->DC.ColumnsSets.back(); + columns->ColumnsSetId = id; + return columns; +} + +void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(columns_count > 1); - IM_ASSERT(window->DC.ColumnsCount == 1); // Nested columns are currently not supported + IM_ASSERT(window->DC.ColumnsSet == NULL); // Nested columns are currently not supported // Differentiate column ID with an arbitrary prefix for cases where users name their columns set the same as another widget. // In addition, when an identifier isn't explicitly provided we include the number of columns in the hash to make it uniquer. - PushID(0x11223347 + (id ? 0 : columns_count)); - window->DC.ColumnsSetId = window->GetID(id ? id : "columns"); + PushID(0x11223347 + (str_id ? 0 : columns_count)); + ImGuiID id = window->GetID(str_id ? str_id : "columns"); PopID(); + ImGuiColumnsSet* columns = FindOrAddColumnsSet(window, id); + IM_ASSERT(columns->ColumnsSetId == id); + window->DC.ColumnsSet = columns; + // Set state for first column - window->DC.ColumnsCurrent = 0; - window->DC.ColumnsCount = columns_count; - window->DC.ColumnsFlags = flags; + columns->ColumnsCurrent = 0; + columns->ColumnsCount = columns_count; + columns->ColumnsFlags = flags; const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->Size.x -window->ScrollbarSizes.x); - window->DC.ColumnsMinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range - //window->DC.ColumnsMaxX = content_region_width - window->Scroll.x -((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; - window->DC.ColumnsMaxX = content_region_width - window->Scroll.x; - window->DC.ColumnsStartPosY = window->DC.CursorPos.y; - window->DC.ColumnsStartMaxPosX = window->DC.CursorMaxPos.x; - window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.CursorPos.y; + columns->ColumnsMinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range + //column->ColumnsMaxX = content_region_width - window->Scroll.x -((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; + columns->ColumnsMaxX = content_region_width - window->Scroll.x; + columns->ColumnsStartPosY = window->DC.CursorPos.y; + columns->ColumnsStartMaxPosX = window->DC.CursorMaxPos.x; + columns->ColumnsCellMinY = columns->ColumnsCellMaxY = window->DC.CursorPos.y; window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); // Cache column offsets - window->DC.ColumnsData.resize(columns_count + 1); + columns->ColumnsData.resize(columns_count + 1); for (int column_index = 0; column_index < columns_count + 1; column_index++) { - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); + const ImGuiID column_id = columns->ColumnsSetId + ImGuiID(column_index); KeepAliveID(column_id); - const float default_t = column_index / (float)window->DC.ColumnsCount; + const float default_t = column_index / (float)columns_count; float t = window->DC.StateStorage->GetFloat(column_id, default_t); - if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) - t = ImMin(t, PixelsToOffsetNorm(window, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index))); - window->DC.ColumnsData[column_index].OffsetNorm = t; + if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) + t = ImMin(t, PixelsToOffsetNorm(columns, columns->ColumnsMaxX - g.Style.ColumnsMinSpacing * (columns->ColumnsCount - column_index))); + columns->ColumnsData[column_index].OffsetNorm = t; } // Cache clipping rectangles @@ -10979,11 +11001,11 @@ void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags fl { float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index) - 1.0f); float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index + 1) - 1.0f); - window->DC.ColumnsData[column_index].ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); - window->DC.ColumnsData[column_index].ClipRect.ClipWith(window->ClipRect); + columns->ColumnsData[column_index].ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); + columns->ColumnsData[column_index].ClipRect.ClipWith(window->ClipRect); } - window->DrawList->ChannelsSplit(window->DC.ColumnsCount); + window->DrawList->ChannelsSplit(columns->ColumnsCount); PushColumnClipRect(); PushItemWidth(GetColumnWidth() * 0.65f); } @@ -10992,34 +11014,35 @@ void ImGui::EndColumns() { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - IM_ASSERT(window->DC.ColumnsCount > 1); + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); PopItemWidth(); PopClipRect(); window->DrawList->ChannelsMerge(); - window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); - window->DC.CursorPos.y = window->DC.ColumnsCellMaxY; - if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_GrowParentContentsSize)) - window->DC.CursorMaxPos.x = ImMax(window->DC.ColumnsStartMaxPosX, window->DC.ColumnsMaxX); // Restore cursor max pos, as columns don't grow parent + columns->ColumnsCellMaxY = ImMax(columns->ColumnsCellMaxY, window->DC.CursorPos.y); + window->DC.CursorPos.y = columns->ColumnsCellMaxY; + if (!(columns->ColumnsFlags & ImGuiColumnsFlags_GrowParentContentsSize)) + window->DC.CursorMaxPos.x = ImMax(columns->ColumnsStartMaxPosX, columns->ColumnsMaxX); // Restore cursor max pos, as columns don't grow parent // Draw columns borders and handle resize - if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) + if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) { - const float y1 = window->DC.ColumnsStartPosY; + const float y1 = columns->ColumnsStartPosY; const float y2 = window->DC.CursorPos.y; int dragging_column = -1; - for (int i = 1; i < window->DC.ColumnsCount; i++) + for (int i = 1; i < columns->ColumnsCount; i++) { float x = window->Pos.x + GetColumnOffset(i); - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(i); + const ImGuiID column_id = columns->ColumnsSetId + ImGuiID(i); const float column_hw = 4.0f; // Half-width for interaction const ImRect column_rect(ImVec2(x - column_hw, y1), ImVec2(x + column_hw, y2)); if (IsClippedEx(column_rect, column_id, false)) continue; bool hovered = false, held = false; - if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoResize)) + if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoResize)) { ButtonBehavior(column_rect, column_id, &hovered, &held); if (hovered || held) @@ -11040,16 +11063,13 @@ void ImGui::EndColumns() // Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame. if (dragging_column != -1) { - float x = GetDraggedColumnOffset(dragging_column); + float x = GetDraggedColumnOffset(columns, dragging_column); SetColumnOffset(dragging_column, x); } } - window->DC.ColumnsSetId = 0; - window->DC.ColumnsCurrent = 0; - window->DC.ColumnsCount = 1; - window->DC.ColumnsFlags = 0; - window->DC.ColumnsData.resize(0); + columns->ColumnsData.resize(0); + window->DC.ColumnsSet = NULL; window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); } @@ -11060,7 +11080,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(columns_count >= 1); - if (window->DC.ColumnsCount != columns_count && window->DC.ColumnsCount != 1) + if (window->DC.ColumnsSet != NULL && window->DC.ColumnsSet->ColumnsCount != columns_count) EndColumns(); ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder); diff --git a/imgui_internal.h b/imgui_internal.h index b8f7e992..30ac9707 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -331,14 +331,6 @@ struct ImGuiGroupData bool AdvanceCursor; }; -// Per column data for Columns() -struct ImGuiColumnData -{ - float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) - ImRect ClipRect; - //float IndentX; -}; - // Simple column measurement currently used for MenuItem() only. This is very short-sighted/throw-away code and NOT a generic helper. struct IMGUI_API ImGuiSimpleColumns { @@ -420,6 +412,42 @@ struct ImGuiPopupRef ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; } }; +// Per column data for Columns() +struct ImGuiColumnData +{ + float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) + ImRect ClipRect; +}; + +struct ImGuiColumnsSet +{ + int ColumnsCurrent; + int ColumnsCount; + float ColumnsMinX; + float ColumnsMaxX; + float ColumnsStartPosY; + float ColumnsStartMaxPosX; // Backup of CursorMaxPos + float ColumnsCellMinY; + float ColumnsCellMaxY; + ImGuiColumnsFlags ColumnsFlags; + ImGuiID ColumnsSetId; + ImVector ColumnsData; + + ImGuiColumnsSet() { Clear(); } + void Clear() + { + ColumnsCurrent = 0; + ColumnsCount = 1; + ColumnsMinX = ColumnsMaxX = 0.0f; + ColumnsStartPosY = 0.0f; + ColumnsStartMaxPosX = 0.0f; + ColumnsCellMinY = ColumnsCellMaxY = 0.0f; + ColumnsFlags = 0; + ColumnsSetId = 0; + ColumnsData.clear(); + } +}; + // Main state for ImGui struct ImGuiContext { @@ -674,17 +702,8 @@ struct IMGUI_API ImGuiDrawContext float IndentX; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) float GroupOffsetX; float ColumnsOffsetX; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API. - int ColumnsCurrent; - int ColumnsCount; - float ColumnsMinX; - float ColumnsMaxX; - float ColumnsStartPosY; - float ColumnsStartMaxPosX; // Backup of CursorMaxPos - float ColumnsCellMinY; - float ColumnsCellMaxY; - ImGuiColumnsFlags ColumnsFlags; - ImGuiID ColumnsSetId; - ImVector ColumnsData; + ImGuiColumnsSet* ColumnsSet; + ImVector ColumnsSets; ImGuiDrawContext() { @@ -708,14 +727,7 @@ struct IMGUI_API ImGuiDrawContext IndentX = 0.0f; GroupOffsetX = 0.0f; ColumnsOffsetX = 0.0f; - ColumnsCurrent = 0; - ColumnsCount = 1; - ColumnsMinX = ColumnsMaxX = 0.0f; - ColumnsStartPosY = 0.0f; - ColumnsStartMaxPosX = 0.0f; - ColumnsCellMinY = ColumnsCellMaxY = 0.0f; - ColumnsFlags = 0; - ColumnsSetId = 0; + ColumnsSet = NULL; } }; @@ -877,8 +889,8 @@ namespace ImGui IMGUI_API bool IsDragDropPayloadBeingAccepted(); // FIXME-WIP: New Columns API - IMGUI_API void BeginColumns(const char* id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). - IMGUI_API void EndColumns(); // close columns + IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). + IMGUI_API void EndColumns(); // close columns IMGUI_API void PushColumnClipRect(int column_index = -1); // NB: All position are in absolute pixels coordinates (never using window coordinates internally) From 3a31a75e3b9c184a8aab05c8c093bde833215eb6 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 18:42:06 +0100 Subject: [PATCH 03/11] Columns: Refactor: Renamed all members. (#125, #1499) --- imgui.cpp | 124 +++++++++++++++++++++++------------------------ imgui_internal.h | 38 +++++++-------- 2 files changed, 80 insertions(+), 82 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index bc60f574..38af1866 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1743,7 +1743,7 @@ static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height) window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHere() can properly function after the end of our clipper usage. window->DC.PrevLineHeight = (line_height - GImGui->Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list. if (window->DC.ColumnsSet) - window->DC.ColumnsSet->ColumnsCellMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly + window->DC.ColumnsSet->CellMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly } // Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1 @@ -5731,7 +5731,7 @@ ImVec2 ImGui::GetContentRegionMax() ImGuiWindow* window = GetCurrentWindowRead(); ImVec2 mx = window->ContentsRegionRect.Max; if (window->DC.ColumnsSet) - mx.x = GetColumnOffset(window->DC.ColumnsSet->ColumnsCurrent + 1) - window->WindowPadding.x; + mx.x = GetColumnOffset(window->DC.ColumnsSet->Current + 1) - window->WindowPadding.x; return mx; } @@ -10571,7 +10571,7 @@ void ImGui::Separator() if (window->DC.ColumnsSet) { PushColumnClipRect(); - window->DC.ColumnsSet->ColumnsCellMinY = window->DC.CursorPos.y; + window->DC.ColumnsSet->CellMinY = window->DC.CursorPos.y; } } @@ -10792,22 +10792,22 @@ void ImGui::NextColumn() PopClipRect(); ImGuiColumnsSet* columns = window->DC.ColumnsSet; - columns->ColumnsCellMaxY = ImMax(columns->ColumnsCellMaxY, window->DC.CursorPos.y); - if (++columns->ColumnsCurrent < columns->ColumnsCount) + columns->CellMaxY = ImMax(columns->CellMaxY, window->DC.CursorPos.y); + if (++columns->Current < columns->Count) { // Columns 1+ cancel out IndentX - window->DC.ColumnsOffsetX = GetColumnOffset(columns->ColumnsCurrent) - window->DC.IndentX + g.Style.ItemSpacing.x; - window->DrawList->ChannelsSetCurrent(columns->ColumnsCurrent); + window->DC.ColumnsOffsetX = GetColumnOffset(columns->Current) - window->DC.IndentX + g.Style.ItemSpacing.x; + window->DrawList->ChannelsSetCurrent(columns->Current); } else { window->DC.ColumnsOffsetX = 0.0f; - columns->ColumnsCurrent = 0; - columns->ColumnsCellMinY = columns->ColumnsCellMaxY; + columns->Current = 0; + columns->CellMinY = columns->CellMaxY; window->DrawList->ChannelsSetCurrent(0); } window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); - window->DC.CursorPos.y = columns->ColumnsCellMinY; + window->DC.CursorPos.y = columns->CellMinY; window->DC.CurrentLineHeight = 0.0f; window->DC.CurrentLineTextBaseOffset = 0.0f; @@ -10818,23 +10818,23 @@ void ImGui::NextColumn() int ImGui::GetColumnIndex() { ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.ColumnsSet ? window->DC.ColumnsSet->ColumnsCurrent : 0; + return window->DC.ColumnsSet ? window->DC.ColumnsSet->Current : 0; } int ImGui::GetColumnsCount() { ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.ColumnsSet ? window->DC.ColumnsSet->ColumnsCount : 1; + return window->DC.ColumnsSet ? window->DC.ColumnsSet->Count : 1; } static float OffsetNormToPixels(const ImGuiColumnsSet* columns, float offset_norm) { - return offset_norm * (columns->ColumnsMaxX - columns->ColumnsMinX); + return offset_norm * (columns->MaxX - columns->MinX); } static float PixelsToOffsetNorm(const ImGuiColumnsSet* columns, float offset) { - return (offset - columns->ColumnsMinX) / (columns->ColumnsMaxX - columns->ColumnsMinX); + return (offset - columns->MinX) / (columns->MaxX - columns->MinX); } static float GetDraggedColumnOffset(ImGuiColumnsSet* columns, int column_index) @@ -10844,11 +10844,11 @@ static float GetDraggedColumnOffset(ImGuiColumnsSet* columns, int column_index) ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(column_index > 0); // We cannot drag column 0. If you get this assert you may have a conflict between the ID of your columns and another widgets. - IM_ASSERT(g.ActiveId == columns->ColumnsSetId + ImGuiID(column_index)); + IM_ASSERT(g.ActiveId == columns->ID + ImGuiID(column_index)); float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x - window->Pos.x; x = ImMax(x, ImGui::GetColumnOffset(column_index-1) + g.Style.ColumnsMinSpacing); - if ((columns->ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths)) + if ((columns->Flags & ImGuiColumnsFlags_NoPreserveWidths)) x = ImMin(x, ImGui::GetColumnOffset(column_index+1) - g.Style.ColumnsMinSpacing); return x; @@ -10861,7 +10861,7 @@ float ImGui::GetColumnOffset(int column_index) IM_ASSERT(columns != NULL); if (column_index < 0) - column_index = columns->ColumnsCurrent; + column_index = columns->Current; /* if (g.ActiveId) @@ -10873,9 +10873,9 @@ float ImGui::GetColumnOffset(int column_index) } */ - IM_ASSERT(column_index < columns->ColumnsData.Size); - const float t = columns->ColumnsData[column_index].OffsetNorm; - const float x_offset = ImLerp(columns->ColumnsMinX, columns->ColumnsMaxX, t); + IM_ASSERT(column_index < columns->Columns.Size); + const float t = columns->Columns[column_index].OffsetNorm; + const float x_offset = ImLerp(columns->MinX, columns->MaxX, t); return x_offset; } @@ -10887,20 +10887,20 @@ void ImGui::SetColumnOffset(int column_index, float offset) IM_ASSERT(columns != NULL); if (column_index < 0) - column_index = columns->ColumnsCurrent; + column_index = columns->Current; - IM_ASSERT(column_index < columns->ColumnsData.Size); + IM_ASSERT(column_index < columns->Columns.Size); - const bool preserve_width = !(columns->ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->ColumnsCount-1); + const bool preserve_width = !(columns->Flags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->Count-1); const float width = preserve_width ? GetColumnWidth(column_index) : 0.0f; - if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) - offset = ImMin(offset, columns->ColumnsMaxX - g.Style.ColumnsMinSpacing * (columns->ColumnsCount - column_index)); + if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) + offset = ImMin(offset, columns->MaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index)); const float offset_norm = PixelsToOffsetNorm(columns, offset); - const ImGuiID column_id = columns->ColumnsSetId + ImGuiID(column_index); + const ImGuiID column_id = columns->ID + ImGuiID(column_index); window->DC.StateStorage->SetFloat(column_id, offset_norm); - columns->ColumnsData[column_index].OffsetNorm = offset_norm; + columns->Columns[column_index].OffsetNorm = offset_norm; if (preserve_width) SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); @@ -10913,8 +10913,8 @@ float ImGui::GetColumnWidth(int column_index) IM_ASSERT(columns != NULL); if (column_index < 0) - column_index = columns->ColumnsCurrent; - return OffsetNormToPixels(columns, columns->ColumnsData[column_index+1].OffsetNorm - columns->ColumnsData[column_index].OffsetNorm); + column_index = columns->Current; + return OffsetNormToPixels(columns, columns->Columns[column_index+1].OffsetNorm - columns->Columns[column_index].OffsetNorm); } void ImGui::SetColumnWidth(int column_index, float width) @@ -10924,7 +10924,7 @@ void ImGui::SetColumnWidth(int column_index, float width) IM_ASSERT(columns != NULL); if (column_index < 0) - column_index = columns->ColumnsCurrent; + column_index = columns->Current; SetColumnOffset(column_index+1, GetColumnOffset(column_index) + width); } @@ -10933,20 +10933,20 @@ void ImGui::PushColumnClipRect(int column_index) ImGuiWindow* window = GetCurrentWindowRead(); ImGuiColumnsSet* columns = window->DC.ColumnsSet; if (column_index < 0) - column_index = columns->ColumnsCurrent; + column_index = columns->Current; - PushClipRect(columns->ColumnsData[column_index].ClipRect.Min, columns->ColumnsData[column_index].ClipRect.Max, false); + PushClipRect(columns->Columns[column_index].ClipRect.Min, columns->Columns[column_index].ClipRect.Max, false); } static ImGuiColumnsSet* FindOrAddColumnsSet(ImGuiWindow* window, ImGuiID id) { for (int n = 0; n < window->DC.ColumnsSets.Size; n++) - if (window->DC.ColumnsSets[n].ColumnsSetId == id) + if (window->DC.ColumnsSets[n].ID == id) return &window->DC.ColumnsSets[n]; window->DC.ColumnsSets.push_back(ImGuiColumnsSet()); ImGuiColumnsSet* columns = &window->DC.ColumnsSets.back(); - columns->ColumnsSetId = id; + columns->ID = id; return columns; } @@ -10965,35 +10965,35 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag PopID(); ImGuiColumnsSet* columns = FindOrAddColumnsSet(window, id); - IM_ASSERT(columns->ColumnsSetId == id); + IM_ASSERT(columns->ID == id); window->DC.ColumnsSet = columns; // Set state for first column - columns->ColumnsCurrent = 0; - columns->ColumnsCount = columns_count; - columns->ColumnsFlags = flags; + columns->Current = 0; + columns->Count = columns_count; + columns->Flags = flags; const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->Size.x -window->ScrollbarSizes.x); - columns->ColumnsMinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range + columns->MinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range //column->ColumnsMaxX = content_region_width - window->Scroll.x -((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; - columns->ColumnsMaxX = content_region_width - window->Scroll.x; - columns->ColumnsStartPosY = window->DC.CursorPos.y; - columns->ColumnsStartMaxPosX = window->DC.CursorMaxPos.x; - columns->ColumnsCellMinY = columns->ColumnsCellMaxY = window->DC.CursorPos.y; + columns->MaxX = content_region_width - window->Scroll.x; + columns->StartPosY = window->DC.CursorPos.y; + columns->StartMaxPosX = window->DC.CursorMaxPos.x; + columns->CellMinY = columns->CellMaxY = window->DC.CursorPos.y; window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); // Cache column offsets - columns->ColumnsData.resize(columns_count + 1); + columns->Columns.resize(columns_count + 1); for (int column_index = 0; column_index < columns_count + 1; column_index++) { - const ImGuiID column_id = columns->ColumnsSetId + ImGuiID(column_index); + const ImGuiID column_id = columns->ID + ImGuiID(column_index); KeepAliveID(column_id); const float default_t = column_index / (float)columns_count; float t = window->DC.StateStorage->GetFloat(column_id, default_t); - if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) - t = ImMin(t, PixelsToOffsetNorm(columns, columns->ColumnsMaxX - g.Style.ColumnsMinSpacing * (columns->ColumnsCount - column_index))); - columns->ColumnsData[column_index].OffsetNorm = t; + if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) + t = ImMin(t, PixelsToOffsetNorm(columns, columns->MaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index))); + columns->Columns[column_index].OffsetNorm = t; } // Cache clipping rectangles @@ -11001,11 +11001,11 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag { float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index) - 1.0f); float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index + 1) - 1.0f); - columns->ColumnsData[column_index].ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); - columns->ColumnsData[column_index].ClipRect.ClipWith(window->ClipRect); + columns->Columns[column_index].ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); + columns->Columns[column_index].ClipRect.ClipWith(window->ClipRect); } - window->DrawList->ChannelsSplit(columns->ColumnsCount); + window->DrawList->ChannelsSplit(columns->Count); PushColumnClipRect(); PushItemWidth(GetColumnWidth() * 0.65f); } @@ -11021,28 +11021,28 @@ void ImGui::EndColumns() PopClipRect(); window->DrawList->ChannelsMerge(); - columns->ColumnsCellMaxY = ImMax(columns->ColumnsCellMaxY, window->DC.CursorPos.y); - window->DC.CursorPos.y = columns->ColumnsCellMaxY; - if (!(columns->ColumnsFlags & ImGuiColumnsFlags_GrowParentContentsSize)) - window->DC.CursorMaxPos.x = ImMax(columns->ColumnsStartMaxPosX, columns->ColumnsMaxX); // Restore cursor max pos, as columns don't grow parent + columns->CellMaxY = ImMax(columns->CellMaxY, window->DC.CursorPos.y); + window->DC.CursorPos.y = columns->CellMaxY; + if (!(columns->Flags & ImGuiColumnsFlags_GrowParentContentsSize)) + window->DC.CursorMaxPos.x = ImMax(columns->StartMaxPosX, columns->MaxX); // Restore cursor max pos, as columns don't grow parent // Draw columns borders and handle resize - if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) + if (!(columns->Flags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) { - const float y1 = columns->ColumnsStartPosY; + const float y1 = columns->StartPosY; const float y2 = window->DC.CursorPos.y; int dragging_column = -1; - for (int i = 1; i < columns->ColumnsCount; i++) + for (int i = 1; i < columns->Count; i++) { float x = window->Pos.x + GetColumnOffset(i); - const ImGuiID column_id = columns->ColumnsSetId + ImGuiID(i); + const ImGuiID column_id = columns->ID + ImGuiID(i); const float column_hw = 4.0f; // Half-width for interaction const ImRect column_rect(ImVec2(x - column_hw, y1), ImVec2(x + column_hw, y2)); if (IsClippedEx(column_rect, column_id, false)) continue; bool hovered = false, held = false; - if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoResize)) + if (!(columns->Flags & ImGuiColumnsFlags_NoResize)) { ButtonBehavior(column_rect, column_id, &hovered, &held); if (hovered || held) @@ -11068,7 +11068,7 @@ void ImGui::EndColumns() } } - columns->ColumnsData.resize(0); + columns->Columns.resize(0); window->DC.ColumnsSet = NULL; window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); @@ -11080,7 +11080,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(columns_count >= 1); - if (window->DC.ColumnsSet != NULL && window->DC.ColumnsSet->ColumnsCount != columns_count) + if (window->DC.ColumnsSet != NULL && window->DC.ColumnsSet->Count != columns_count) EndColumns(); ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder); diff --git a/imgui_internal.h b/imgui_internal.h index 30ac9707..ab990e50 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -421,30 +421,28 @@ struct ImGuiColumnData struct ImGuiColumnsSet { - int ColumnsCurrent; - int ColumnsCount; - float ColumnsMinX; - float ColumnsMaxX; - float ColumnsStartPosY; - float ColumnsStartMaxPosX; // Backup of CursorMaxPos - float ColumnsCellMinY; - float ColumnsCellMaxY; - ImGuiColumnsFlags ColumnsFlags; - ImGuiID ColumnsSetId; - ImVector ColumnsData; + ImGuiID ID; + ImGuiColumnsFlags Flags; + int Current; + int Count; + float MinX, MaxX; + float StartPosY; + float StartMaxPosX; // Backup of CursorMaxPos + float CellMinY, CellMaxY; + ImVector Columns; ImGuiColumnsSet() { Clear(); } void Clear() { - ColumnsCurrent = 0; - ColumnsCount = 1; - ColumnsMinX = ColumnsMaxX = 0.0f; - ColumnsStartPosY = 0.0f; - ColumnsStartMaxPosX = 0.0f; - ColumnsCellMinY = ColumnsCellMaxY = 0.0f; - ColumnsFlags = 0; - ColumnsSetId = 0; - ColumnsData.clear(); + ID = 0; + Flags = 0; + Current = 0; + Count = 1; + MinX = MaxX = 0.0f; + StartPosY = 0.0f; + StartMaxPosX = 0.0f; + CellMinY = CellMaxY = 0.0f; + Columns.clear(); } }; From b016215c80f64fef17b8aaad843167c3c8d3855b Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 19:07:09 +0100 Subject: [PATCH 04/11] Columns: Refactor: Not using statestorage lookup anymore. (#125, #1499) --- imgui.cpp | 71 +++++++++++++++++++++++++----------------------- imgui_internal.h | 5 ++-- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 38af1866..e12e6ea6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10847,9 +10847,9 @@ static float GetDraggedColumnOffset(ImGuiColumnsSet* columns, int column_index) IM_ASSERT(g.ActiveId == columns->ID + ImGuiID(column_index)); float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x - window->Pos.x; - x = ImMax(x, ImGui::GetColumnOffset(column_index-1) + g.Style.ColumnsMinSpacing); + x = ImMax(x, ImGui::GetColumnOffset(column_index - 1) + g.Style.ColumnsMinSpacing); if ((columns->Flags & ImGuiColumnsFlags_NoPreserveWidths)) - x = ImMin(x, ImGui::GetColumnOffset(column_index+1) - g.Style.ColumnsMinSpacing); + x = ImMin(x, ImGui::GetColumnOffset(column_index + 1) - g.Style.ColumnsMinSpacing); return x; } @@ -10862,6 +10862,7 @@ float ImGui::GetColumnOffset(int column_index) if (column_index < 0) column_index = columns->Current; + IM_ASSERT(column_index < columns->Columns.Size); /* if (g.ActiveId) @@ -10873,7 +10874,6 @@ float ImGui::GetColumnOffset(int column_index) } */ - IM_ASSERT(column_index < columns->Columns.Size); const float t = columns->Columns[column_index].OffsetNorm; const float x_offset = ImLerp(columns->MinX, columns->MaxX, t); return x_offset; @@ -10888,7 +10888,6 @@ void ImGui::SetColumnOffset(int column_index, float offset) if (column_index < 0) column_index = columns->Current; - IM_ASSERT(column_index < columns->Columns.Size); const bool preserve_width = !(columns->Flags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->Count-1); @@ -10896,11 +10895,7 @@ void ImGui::SetColumnOffset(int column_index, float offset) if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) offset = ImMin(offset, columns->MaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index)); - const float offset_norm = PixelsToOffsetNorm(columns, offset); - - const ImGuiID column_id = columns->ID + ImGuiID(column_index); - window->DC.StateStorage->SetFloat(column_id, offset_norm); - columns->Columns[column_index].OffsetNorm = offset_norm; + columns->Columns[column_index].OffsetNorm = PixelsToOffsetNorm(columns, offset); if (preserve_width) SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); @@ -10925,7 +10920,7 @@ void ImGui::SetColumnWidth(int column_index, float width) if (column_index < 0) column_index = columns->Current; - SetColumnOffset(column_index+1, GetColumnOffset(column_index) + width); + SetColumnOffset(column_index + 1, GetColumnOffset(column_index) + width); } void ImGui::PushColumnClipRect(int column_index) @@ -10964,15 +10959,15 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag ImGuiID id = window->GetID(str_id ? str_id : "columns"); PopID(); + // Acquire storage for the columns set ImGuiColumnsSet* columns = FindOrAddColumnsSet(window, id); IM_ASSERT(columns->ID == id); - window->DC.ColumnsSet = columns; - - // Set state for first column columns->Current = 0; columns->Count = columns_count; columns->Flags = flags; + window->DC.ColumnsSet = columns; + // Set state for first column const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->Size.x -window->ScrollbarSizes.x); columns->MinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range //column->ColumnsMaxX = content_region_width - window->Scroll.x -((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; @@ -10983,26 +10978,36 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); - // Cache column offsets - columns->Columns.resize(columns_count + 1); - for (int column_index = 0; column_index < columns_count + 1; column_index++) + // Initialize defaults + if (columns->Columns.Size == 0) { - const ImGuiID column_id = columns->ID + ImGuiID(column_index); - KeepAliveID(column_id); - const float default_t = column_index / (float)columns_count; - float t = window->DC.StateStorage->GetFloat(column_id, default_t); - if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) - t = ImMin(t, PixelsToOffsetNorm(columns, columns->MaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index))); - columns->Columns[column_index].OffsetNorm = t; + columns->Columns.reserve(columns_count + 1); + for (int n = 0; n < columns_count + 1; n++) + { + ImGuiColumnData column; + column.OffsetNorm = n / (float)columns_count; + columns->Columns.push_back(column); + } } + IM_ASSERT(columns->Columns.Size == columns_count + 1); - // Cache clipping rectangles - for (int column_index = 0; column_index < columns_count; column_index++) + for (int n = 0; n < columns_count + 1; n++) { - float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index) - 1.0f); - float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index + 1) - 1.0f); - columns->Columns[column_index].ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); - columns->Columns[column_index].ClipRect.ClipWith(window->ClipRect); + // Clamp + ImGuiColumnData* column = &columns->Columns[n]; + float t = column->OffsetNorm; + if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) + t = ImMin(t, PixelsToOffsetNorm(columns, columns->MaxX - g.Style.ColumnsMinSpacing * (columns->Count - n))); + column->OffsetNorm = t; + + if (n == columns_count) + continue; + + // Compute clipping rectangles + float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n) - 1.0f); + float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n + 1) - 1.0f); + column->ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); + column->ClipRect.ClipWith(window->ClipRect); } window->DrawList->ChannelsSplit(columns->Count); @@ -11038,6 +11043,7 @@ void ImGui::EndColumns() const ImGuiID column_id = columns->ID + ImGuiID(i); const float column_hw = 4.0f; // Half-width for interaction const ImRect column_rect(ImVec2(x - column_hw, y1), ImVec2(x + column_hw, y2)); + KeepAliveID(column_id); if (IsClippedEx(column_rect, column_id, false)) continue; @@ -11053,8 +11059,7 @@ void ImGui::EndColumns() dragging_column = i; } - // Draw column - // We clip the Y boundaries CPU side because very long triangles are mishandled by some GPU drivers. + // Draw column (we clip the Y boundaries CPU side because very long triangles are mishandled by some GPU drivers.) const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); const float xi = (float)(int)x; window->DrawList->AddLine(ImVec2(xi, ImMax(y1 + 1.0f, window->ClipRect.Min.y)), ImVec2(xi, ImMin(y2, window->ClipRect.Max.y)), col); @@ -11068,18 +11073,16 @@ void ImGui::EndColumns() } } - columns->Columns.resize(0); window->DC.ColumnsSet = NULL; window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); } -// [2017/08: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing] +// [2017/12: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing] void ImGui::Columns(int columns_count, const char* id, bool border) { ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(columns_count >= 1); - if (window->DC.ColumnsSet != NULL && window->DC.ColumnsSet->Count != columns_count) EndColumns(); diff --git a/imgui_internal.h b/imgui_internal.h index ab990e50..e2975ece 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -412,11 +412,12 @@ struct ImGuiPopupRef ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; } }; -// Per column data for Columns() struct ImGuiColumnData { - float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) + float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) ImRect ClipRect; + + ImGuiColumnData() { OffsetNorm = 0.0f; } }; struct ImGuiColumnsSet From 4ae5c7e22716a4f1d0555b7f317d5850052506fa Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 19:21:21 +0100 Subject: [PATCH 05/11] Columns: Refactor: Moved ColumnsSet[] to window out of DC as they are persistent data for most + fix for pre C++11 compilers. (#125, #1499) --- imgui.cpp | 10 +++++----- imgui_internal.h | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e12e6ea6..e28b9939 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10935,12 +10935,12 @@ void ImGui::PushColumnClipRect(int column_index) static ImGuiColumnsSet* FindOrAddColumnsSet(ImGuiWindow* window, ImGuiID id) { - for (int n = 0; n < window->DC.ColumnsSets.Size; n++) - if (window->DC.ColumnsSets[n].ID == id) - return &window->DC.ColumnsSets[n]; + for (int n = 0; n < window->ColumnsStorage.Size; n++) + if (window->ColumnsStorage[n].ID == id) + return &window->ColumnsStorage[n]; - window->DC.ColumnsSets.push_back(ImGuiColumnsSet()); - ImGuiColumnsSet* columns = &window->DC.ColumnsSets.back(); + window->ColumnsStorage.push_back(ImGuiColumnsSet()); + ImGuiColumnsSet* columns = &window->ColumnsStorage.back(); columns->ID = id; return columns; } diff --git a/imgui_internal.h b/imgui_internal.h index e2975ece..f79f46b1 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -201,7 +201,7 @@ enum ImGuiColumnsFlags_ ImGuiColumnsFlags_NoResize = 1 << 1, // Disable resizing columns when clicking on the dividers ImGuiColumnsFlags_NoPreserveWidths = 1 << 2, // Disable column width preservation when adjusting columns ImGuiColumnsFlags_NoForceWithinWindow = 1 << 3, // Disable forcing columns to fit within window - ImGuiColumnsFlags_GrowParentContentsSize= 1 << 4, // (WIP) Restore pre-1.51 behavior of extending the parent window contents size but _without affecting the columns width at all_. Will eventually remove. + ImGuiColumnsFlags_GrowParentContentsSize= 1 << 4 // (WIP) Restore pre-1.51 behavior of extending the parent window contents size but _without affecting the columns width at all_. Will eventually remove. }; enum ImGuiSelectableFlagsPrivate_ @@ -403,19 +403,19 @@ struct ImGuiMouseCursorData // Storage for current popup stack struct ImGuiPopupRef { - ImGuiID PopupId; // Set on OpenPopup() - ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() - ImGuiWindow* ParentWindow; // Set on OpenPopup() - ImGuiID ParentMenuSet; // Set on OpenPopup() - ImVec2 MousePosOnOpen; // Copy of mouse position at the time of opening popup + ImGuiID PopupId; // Set on OpenPopup() + ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() + ImGuiWindow* ParentWindow; // Set on OpenPopup() + ImGuiID ParentMenuSet; // Set on OpenPopup() + ImVec2 MousePosOnOpen; // Copy of mouse position at the time of opening popup ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; } }; struct ImGuiColumnData { - float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) - ImRect ClipRect; + float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) + ImRect ClipRect; ImGuiColumnData() { OffsetNorm = 0.0f; } }; @@ -701,8 +701,7 @@ struct IMGUI_API ImGuiDrawContext float IndentX; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) float GroupOffsetX; float ColumnsOffsetX; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API. - ImGuiColumnsSet* ColumnsSet; - ImVector ColumnsSets; + ImGuiColumnsSet* ColumnsSet; // Current columns set ImGuiDrawContext() { @@ -784,6 +783,7 @@ struct IMGUI_API ImGuiWindow float ItemWidthDefault; ImGuiSimpleColumns MenuColumns; // Simplified columns storage for menu items ImGuiStorage StateStorage; + ImVector ColumnsStorage; float FontWindowScale; // Scale multiplier per-window ImDrawList* DrawList; ImGuiWindow* ParentWindow; // If we are a child _or_ popup window, this is pointing to our parent. Otherwise NULL. From e8e84a6ad68c339f3e1c537069655b6d228b7eae Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 19:26:04 +0100 Subject: [PATCH 06/11] Columns: Added internal tracking of a few flag temporarily, to facilitate the work of third-parties who have columns patches. (#125) --- imgui.cpp | 3 +++ imgui_internal.h | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index e28b9939..bd628225 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10979,6 +10979,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); // Initialize defaults + columns->IsFirstFrame = (columns->Columns.Size == 0); if (columns->Columns.Size == 0) { columns->Columns.reserve(columns_count + 1); @@ -11032,6 +11033,7 @@ void ImGui::EndColumns() window->DC.CursorMaxPos.x = ImMax(columns->StartMaxPosX, columns->MaxX); // Restore cursor max pos, as columns don't grow parent // Draw columns borders and handle resize + columns->IsBeingResized = false; if (!(columns->Flags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) { const float y1 = columns->StartPosY; @@ -11070,6 +11072,7 @@ void ImGui::EndColumns() { float x = GetDraggedColumnOffset(columns, dragging_column); SetColumnOffset(dragging_column, x); + columns->IsBeingResized = true; } } diff --git a/imgui_internal.h b/imgui_internal.h index f79f46b1..ca1086b9 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -424,6 +424,8 @@ struct ImGuiColumnsSet { ImGuiID ID; ImGuiColumnsFlags Flags; + bool IsFirstFrame; + bool IsBeingResized; int Current; int Count; float MinX, MaxX; @@ -437,6 +439,8 @@ struct ImGuiColumnsSet { ID = 0; Flags = 0; + IsFirstFrame = false; + IsBeingResized = false; Current = 0; Count = 1; MinX = MaxX = 0.0f; From f7c5f420e7e87dd420a553eac5c2a1e55904d3ec Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 19:44:54 +0100 Subject: [PATCH 07/11] BeginChild() fix using negative sizes as window position because of erroneous clamping. It was hard to notice until we added asserts for it. (#1500) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index bd628225..0055b05f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3953,9 +3953,9 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b ImVec2 size = ImFloor(size_arg); const int auto_fit_axises = ((size.x == 0.0f) ? (1 << ImGuiAxis_X) : 0x00) | ((size.y == 0.0f) ? (1 << ImGuiAxis_Y) : 0x00); if (size.x <= 0.0f) - size.x = ImMax(content_avail.x, 4.0f) - fabsf(size.x); // Arbitrary minimum zero-ish child size of 4.0f (0.0f causing too much issues) + size.x = ImMax(content_avail.x + size.x, 4.0f); // Arbitrary minimum child size (0.0f causing too much issues) if (size.y <= 0.0f) - size.y = ImMax(content_avail.y, 4.0f) - fabsf(size.y); + size.y = ImMax(content_avail.y + size.y, 4.0f); const float backup_border_size = g.Style.ChildBorderSize; if (!border) From ba71e1c0e4afab77f263d2b5c5a445e85bca87a2 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 21:48:56 +0100 Subject: [PATCH 08/11] Columns: Minor stylistic fixes. (#125) --- imgui.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0055b05f..91b77773 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10879,6 +10879,17 @@ float ImGui::GetColumnOffset(int column_index) return x_offset; } +float ImGui::GetColumnWidth(int column_index) +{ + ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); + + if (column_index < 0) + column_index = columns->Current; + return OffsetNormToPixels(columns, columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm); +} + void ImGui::SetColumnOffset(int column_index, float offset) { ImGuiContext& g = *GImGui; @@ -10901,17 +10912,6 @@ void ImGui::SetColumnOffset(int column_index, float offset) SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); } -float ImGui::GetColumnWidth(int column_index) -{ - ImGuiWindow* window = GetCurrentWindowRead(); - ImGuiColumnsSet* columns = window->DC.ColumnsSet; - IM_ASSERT(columns != NULL); - - if (column_index < 0) - column_index = columns->Current; - return OffsetNormToPixels(columns, columns->Columns[column_index+1].OffsetNorm - columns->Columns[column_index].OffsetNorm); -} - void ImGui::SetColumnWidth(int column_index, float width) { ImGuiWindow* window = GetCurrentWindowRead(); @@ -11039,10 +11039,10 @@ void ImGui::EndColumns() const float y1 = columns->StartPosY; const float y2 = window->DC.CursorPos.y; int dragging_column = -1; - for (int i = 1; i < columns->Count; i++) + for (int n = 1; n < columns->Count; n++) { - float x = window->Pos.x + GetColumnOffset(i); - const ImGuiID column_id = columns->ID + ImGuiID(i); + float x = window->Pos.x + GetColumnOffset(n); + const ImGuiID column_id = columns->ID + ImGuiID(n); const float column_hw = 4.0f; // Half-width for interaction const ImRect column_rect(ImVec2(x - column_hw, y1), ImVec2(x + column_hw, y2)); KeepAliveID(column_id); @@ -11058,7 +11058,7 @@ void ImGui::EndColumns() if (held && g.ActiveIdIsJustActivated) g.ActiveIdClickOffset.x -= column_hw; // Store from center of column line (we used a 8 wide rect for columns clicking). This is used by GetDraggedColumnOffset(). if (held) - dragging_column = i; + dragging_column = n; } // Draw column (we clip the Y boundaries CPU side because very long triangles are mishandled by some GPU drivers.) From ddbcda8c1bc6987d0adae2ac9bc7a1aad14c10f0 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 21:51:23 +0100 Subject: [PATCH 09/11] Columns: Column width data is no longer lost while dragging toward the right side. (#1499, #125) --- imgui.cpp | 23 ++++++++++++++++++++--- imgui_internal.h | 5 +++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 91b77773..cf21d0e9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10879,6 +10879,19 @@ float ImGui::GetColumnOffset(int column_index) return x_offset; } +static float GetColumnWidthEx(ImGuiColumnsSet* columns, int column_index, bool before_resize = false) +{ + if (column_index < 0) + column_index = columns->Current; + + float offset_norm; + if (before_resize) + offset_norm = columns->Columns[column_index + 1].OffsetNormBeforeResize - columns->Columns[column_index].OffsetNormBeforeResize; + else + offset_norm = columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm; + return OffsetNormToPixels(columns, offset_norm); +} + float ImGui::GetColumnWidth(int column_index) { ImGuiWindow* window = GetCurrentWindowRead(); @@ -10902,7 +10915,7 @@ void ImGui::SetColumnOffset(int column_index, float offset) IM_ASSERT(column_index < columns->Columns.Size); const bool preserve_width = !(columns->Flags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->Count-1); - const float width = preserve_width ? GetColumnWidth(column_index) : 0.0f; + const float width = preserve_width ? GetColumnWidthEx(columns, column_index, columns->IsBeingResized) : 0.0f; if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) offset = ImMin(offset, columns->MaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index)); @@ -11033,7 +11046,7 @@ void ImGui::EndColumns() window->DC.CursorMaxPos.x = ImMax(columns->StartMaxPosX, columns->MaxX); // Restore cursor max pos, as columns don't grow parent // Draw columns borders and handle resize - columns->IsBeingResized = false; + bool is_being_resized = false; if (!(columns->Flags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) { const float y1 = columns->StartPosY; @@ -11070,11 +11083,15 @@ void ImGui::EndColumns() // Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame. if (dragging_column != -1) { + if (!columns->IsBeingResized) + for (int n = 0; n < columns->Count + 1; n++) + columns->Columns[n].OffsetNormBeforeResize = columns->Columns[n].OffsetNorm; + columns->IsBeingResized = is_being_resized = true; float x = GetDraggedColumnOffset(columns, dragging_column); SetColumnOffset(dragging_column, x); - columns->IsBeingResized = true; } } + columns->IsBeingResized = is_being_resized; window->DC.ColumnsSet = NULL; window->DC.ColumnsOffsetX = 0.0f; diff --git a/imgui_internal.h b/imgui_internal.h index ca1086b9..f0d598b4 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -414,10 +414,11 @@ struct ImGuiPopupRef struct ImGuiColumnData { - float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) + float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) + float OffsetNormBeforeResize; ImRect ClipRect; - ImGuiColumnData() { OffsetNorm = 0.0f; } + ImGuiColumnData() { OffsetNorm = OffsetNormBeforeResize = 0.0f; } }; struct ImGuiColumnsSet From 39058160825eff27d0e39a2c0d56b11bcec9f09e Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 21:59:16 +0100 Subject: [PATCH 10/11] Added ShowFontSelector(), ShowStyleSelector(). (#707) --- imgui.h | 4 +++- imgui_demo.cpp | 49 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/imgui.h b/imgui.h index 52a0239f..c05d92c6 100644 --- a/imgui.h +++ b/imgui.h @@ -133,10 +133,12 @@ namespace ImGui IMGUI_API void EndFrame(); // ends the ImGui frame. automatically called by Render(), so most likely don't need to ever call that yourself directly. If you don't need to render you may call EndFrame() but you'll have wasted CPU already. If you don't need to render, better to not create any imgui windows instead! IMGUI_API void Shutdown(); - // Demo/Debug/Info + // Demo, Debug, Informations IMGUI_API void ShowTestWindow(bool* p_open = NULL); // create demo/test window. demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application! IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // create metrics window. display ImGui internals: draw commands (with individual draw calls and vertices), window list, basic internal state, etc. IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // add style editor block (not a window). you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style) + IMGUI_API bool ShowStyleSelector(const char* label); + IMGUI_API void ShowFontSelector(const char* label); IMGUI_API void ShowUserGuide(); // add basic help/info block (not a window): how to manipulate ImGui as a end-user (mouse/keyboard controls). // Window diff --git a/imgui_demo.cpp b/imgui_demo.cpp index f45a8582..50aecce9 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1903,6 +1903,41 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::End(); } +bool ImGui::ShowStyleSelector(const char* label) +{ + static int style_idx = 0; + if (ImGui::Combo(label, &style_idx, "Classic\0Dark\0Light\0")) + { + switch (style_idx) + { + case 0: ImGui::StyleColorsClassic(); break; + case 1: ImGui::StyleColorsDark(); break; + case 2: ImGui::StyleColorsLight(); break; + } + return true; + } + return false; +} + +void ImGui::ShowFontSelector(const char* label) +{ + ImGuiIO& io = ImGui::GetIO(); + ImFont* font_current = ImGui::GetFont(); + if (ImGui::BeginCombo(label, font_current->GetDebugName())) + { + for (int n = 0; n < io.Fonts->Fonts.Size; n++) + if (ImGui::Selectable(io.Fonts->Fonts[n]->GetDebugName(), io.Fonts->Fonts[n] == font_current)) + io.FontDefault = io.Fonts->Fonts[n]; + ImGui::EndCombo(); + } + ImGui::SameLine(); + ShowHelpMarker( + "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n" + "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n" + "- Read FAQ and documentation in extra_fonts/ for more details.\n" + "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame()."); +} + void ImGui::ShowStyleEditor(ImGuiStyle* ref) { // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it compares to an internally stored reference) @@ -1919,18 +1954,9 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f); - // Default Styles Selector - static int style_idx = 0; - if (ImGui::Combo("Colors##Selector", &style_idx, "Classic\0Dark\0Light\0")) - { - switch (style_idx) - { - case 0: ImGui::StyleColorsClassic(); break; - case 1: ImGui::StyleColorsDark(); break; - case 2: ImGui::StyleColorsLight(); break; - } + if (ImGui::ShowStyleSelector("Colors##Selector")) ref_saved_style = style; - } + ImGui::ShowFontSelector("Fonts##Selector"); // Simplified Settings if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f")) @@ -2050,7 +2076,6 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) } bool fonts_opened = ImGui::TreeNode("Fonts", "Fonts (%d)", ImGui::GetIO().Fonts->Fonts.Size); - ImGui::SameLine(); ShowHelpMarker("Tip: Load fonts with io.Fonts->AddFontFromFileTTF()\nbefore calling io.Fonts->GetTex* functions."); if (fonts_opened) { ImFontAtlas* atlas = ImGui::GetIO().Fonts; From f265e16b840f3352fc54f0d3a03bfb5bfd1b8b17 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 22:05:48 +0100 Subject: [PATCH 11/11] Revert "Scrollbar: Minor simplication of the code using InnerRect data." > Introduced sheering on the scrollbar rectangle because InnerRect isn't setup at this point. This reverts commit 7ac1583411095fe8a82ccbc56d09777f87222e9d. --- imgui.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index cf21d0e9..69f04d8c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5021,8 +5021,10 @@ void ImGui::Scrollbar(ImGuiLayoutType direction) const ImRect window_rect = window->Rect(); const float border_size = window->WindowBorderSize; ImRect bb = horizontal - ? ImRect(window->InnerRect.Min.x, window_rect.Max.y - style.ScrollbarSize, window->InnerRect.Max.x, window_rect.Max.y - border_size) - : ImRect(window_rect.Max.x - style.ScrollbarSize, window->InnerRect.Min.y, window_rect.Max.x - border_size, window->InnerRect.Max.y); + ? ImRect(window->Pos.x + border_size, window_rect.Max.y - style.ScrollbarSize, window_rect.Max.x - other_scrollbar_size_w - border_size, window_rect.Max.y - border_size) + : ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + border_size, window_rect.Max.x - border_size, window_rect.Max.y - other_scrollbar_size_w - border_size); + if (!horizontal) + bb.Min.y += window->TitleBarHeight() + ((window->Flags & ImGuiWindowFlags_MenuBar) ? window->MenuBarHeight() : 0.0f); if (bb.GetWidth() <= 0.0f || bb.GetHeight() <= 0.0f) return;