mirror of
https://github.com/ocornut/imgui.git
synced 2025-12-26 08:09:09 +00:00
Merge branch 'master' into navigation
# Conflicts: # imgui_internal.h
This commit is contained in:
315
imgui.cpp
315
imgui.cpp
@@ -664,8 +664,6 @@
|
||||
// Forward Declarations
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
static float GetDraggedColumnOffset(int column_index);
|
||||
|
||||
static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true);
|
||||
|
||||
static ImFont* GetDefaultFont();
|
||||
@@ -1787,8 +1785,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->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
|
||||
@@ -4834,9 +4832,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)
|
||||
@@ -5770,11 +5768,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);
|
||||
@@ -5946,7 +5940,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
|
||||
|
||||
@@ -5983,8 +5977,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;
|
||||
|
||||
@@ -6488,13 +6484,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;
|
||||
@@ -6710,8 +6706,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->Current + 1) - window->WindowPadding.x;
|
||||
return mx;
|
||||
}
|
||||
|
||||
@@ -10451,7 +10447,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);
|
||||
@@ -10482,7 +10478,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
bb_with_spacing.Max.y += spacing_D;
|
||||
if (!ItemAdd(bb_with_spacing, (flags & ImGuiSelectableFlags_Disabled) ? 0 : id))
|
||||
{
|
||||
if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1)
|
||||
if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet)
|
||||
PushColumnClipRect();
|
||||
return false;
|
||||
}
|
||||
@@ -10513,7 +10509,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
RenderNavHighlight(bb_with_spacing, id, ImGuiNavHighlightFlags_TypeThin);
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -11724,7 +11720,7 @@ void ImGui::Separator()
|
||||
}
|
||||
|
||||
// Horizontal Separator
|
||||
if (window->DC.ColumnsCount > 1)
|
||||
if (window->DC.ColumnsSet)
|
||||
PopClipRect();
|
||||
|
||||
float x1 = window->Pos.x;
|
||||
@@ -11736,7 +11732,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;
|
||||
}
|
||||
@@ -11746,10 +11742,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->CellMinY = window->DC.CursorPos.y;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11962,29 +11958,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->CellMaxY = ImMax(columns->CellMaxY, window->DC.CursorPos.y);
|
||||
if (++columns->Current < columns->Count)
|
||||
{
|
||||
// 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->Current) - window->DC.IndentX + g.Style.ItemSpacing.x;
|
||||
window->DrawList->ChannelsSetCurrent(columns->Current);
|
||||
}
|
||||
else
|
||||
{
|
||||
window->DC.ColumnsCurrent = 0;
|
||||
window->DC.ColumnsOffsetX = 0.0f;
|
||||
window->DC.ColumnsCellMinY = window->DC.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 = window->DC.ColumnsCellMinY;
|
||||
window->DC.CursorPos.y = columns->CellMinY;
|
||||
window->DC.CurrentLineHeight = 0.0f;
|
||||
window->DC.CurrentLineTextBaseOffset = 0.0f;
|
||||
|
||||
@@ -11995,38 +11992,38 @@ void ImGui::NextColumn()
|
||||
int ImGui::GetColumnIndex()
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindowRead();
|
||||
return window->DC.ColumnsCurrent;
|
||||
return window->DC.ColumnsSet ? window->DC.ColumnsSet->Current : 0;
|
||||
}
|
||||
|
||||
int ImGui::GetColumnsCount()
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindowRead();
|
||||
return window->DC.ColumnsCount;
|
||||
return window->DC.ColumnsSet ? window->DC.ColumnsSet->Count : 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->MaxX - columns->MinX);
|
||||
}
|
||||
|
||||
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->MinX) / (columns->MaxX - columns->MinX);
|
||||
}
|
||||
|
||||
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->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 ((window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths))
|
||||
x = ImMin(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);
|
||||
|
||||
return x;
|
||||
}
|
||||
@@ -12034,128 +12031,174 @@ 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->Current;
|
||||
IM_ASSERT(column_index < columns->Columns.Size);
|
||||
|
||||
/*
|
||||
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);
|
||||
const float t = columns->Columns[column_index].OffsetNorm;
|
||||
const float x_offset = ImLerp(columns->MinX, columns->MaxX, t);
|
||||
return x_offset;
|
||||
}
|
||||
|
||||
void ImGui::SetColumnOffset(int column_index, float offset)
|
||||
static float GetColumnWidthEx(ImGuiColumnsSet* columns, int column_index, bool before_resize = false)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (column_index < 0)
|
||||
column_index = window->DC.ColumnsCurrent;
|
||||
column_index = columns->Current;
|
||||
|
||||
IM_ASSERT(column_index < window->DC.ColumnsData.Size);
|
||||
|
||||
const bool preserve_width = !(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < window->DC.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);
|
||||
|
||||
const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index);
|
||||
window->DC.StateStorage->SetFloat(column_id, offset_norm);
|
||||
window->DC.ColumnsData[column_index].OffsetNorm = offset_norm;
|
||||
|
||||
if (preserve_width)
|
||||
SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width));
|
||||
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();
|
||||
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->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;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
ImGuiColumnsSet* columns = window->DC.ColumnsSet;
|
||||
IM_ASSERT(columns != NULL);
|
||||
|
||||
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);
|
||||
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));
|
||||
columns->Columns[column_index].OffsetNorm = PixelsToOffsetNorm(columns, offset);
|
||||
|
||||
if (preserve_width)
|
||||
SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width));
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
SetColumnOffset(column_index+1, GetColumnOffset(column_index) + width);
|
||||
if (column_index < 0)
|
||||
column_index = columns->Current;
|
||||
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->Current;
|
||||
|
||||
PushClipRect(window->DC.ColumnsData[column_index].ClipRect.Min, window->DC.ColumnsData[column_index].ClipRect.Max, false);
|
||||
PushClipRect(columns->Columns[column_index].ClipRect.Min, columns->Columns[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->ColumnsStorage.Size; n++)
|
||||
if (window->ColumnsStorage[n].ID == id)
|
||||
return &window->ColumnsStorage[n];
|
||||
|
||||
window->ColumnsStorage.push_back(ImGuiColumnsSet());
|
||||
ImGuiColumnsSet* columns = &window->ColumnsStorage.back();
|
||||
columns->ID = 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();
|
||||
|
||||
// Set state for first column
|
||||
window->DC.ColumnsCurrent = 0;
|
||||
window->DC.ColumnsCount = columns_count;
|
||||
window->DC.ColumnsFlags = flags;
|
||||
// Acquire storage for the columns set
|
||||
ImGuiColumnsSet* columns = FindOrAddColumnsSet(window, id);
|
||||
IM_ASSERT(columns->ID == id);
|
||||
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);
|
||||
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->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->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
|
||||
window->DC.ColumnsData.resize(columns_count + 1);
|
||||
for (int column_index = 0; column_index < columns_count + 1; column_index++)
|
||||
// Initialize defaults
|
||||
columns->IsFirstFrame = (columns->Columns.Size == 0);
|
||||
if (columns->Columns.Size == 0)
|
||||
{
|
||||
const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index);
|
||||
KeepAliveID(column_id);
|
||||
const float default_t = column_index / (float)window->DC.ColumnsCount;
|
||||
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;
|
||||
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);
|
||||
|
||||
for (int n = 0; n < columns_count + 1; n++)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Cache clipping rectangles
|
||||
for (int column_index = 0; column_index < columns_count; column_index++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
window->DrawList->ChannelsSplit(window->DC.ColumnsCount);
|
||||
window->DrawList->ChannelsSplit(columns->Count);
|
||||
PushColumnClipRect();
|
||||
PushItemWidth(GetColumnWidth() * 0.65f);
|
||||
}
|
||||
@@ -12164,34 +12207,37 @@ 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->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 (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems)
|
||||
bool is_being_resized = false;
|
||||
if (!(columns->Flags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems)
|
||||
{
|
||||
const float y1 = window->DC.ColumnsStartPosY;
|
||||
const float y1 = columns->StartPosY;
|
||||
const float y2 = window->DC.CursorPos.y;
|
||||
int dragging_column = -1;
|
||||
for (int i = 1; i < window->DC.ColumnsCount; i++)
|
||||
for (int n = 1; n < columns->Count; n++)
|
||||
{
|
||||
float x = window->Pos.x + GetColumnOffset(i);
|
||||
const ImGuiID column_id = window->DC.ColumnsSetId + 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);
|
||||
if (IsClippedEx(column_rect, column_id, false))
|
||||
continue;
|
||||
|
||||
bool hovered = false, held = false;
|
||||
if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoResize))
|
||||
if (!(columns->Flags & ImGuiColumnsFlags_NoResize))
|
||||
{
|
||||
ButtonBehavior(column_rect, column_id, &hovered, &held);
|
||||
if (hovered || held)
|
||||
@@ -12199,11 +12245,10 @@ 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.
|
||||
// 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);
|
||||
@@ -12212,27 +12257,27 @@ 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);
|
||||
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 = is_being_resized;
|
||||
|
||||
window->DC.ColumnsSetId = 0;
|
||||
window->DC.ColumnsCurrent = 0;
|
||||
window->DC.ColumnsCount = 1;
|
||||
window->DC.ColumnsFlags = 0;
|
||||
window->DC.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);
|
||||
}
|
||||
|
||||
// [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.ColumnsCount != columns_count && window->DC.ColumnsCount != 1)
|
||||
if (window->DC.ColumnsSet != NULL && window->DC.ColumnsSet->Count != columns_count)
|
||||
EndColumns();
|
||||
|
||||
ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder);
|
||||
|
||||
Reference in New Issue
Block a user