mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-30 20:51:06 +01:00 
			
		
		
		
	Columns: Refactor: Moved columns data into their own data structure. Minimum changes now to ease diffing. (#125, #1499)
This commit is contained in:
		
							
								
								
									
										214
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										214
									
								
								imgui.cpp
									
									
									
									
									
								
							| @@ -627,8 +627,6 @@ | |||||||
| // Forward Declarations | // Forward Declarations | ||||||
| //------------------------------------------------------------------------- | //------------------------------------------------------------------------- | ||||||
|  |  | ||||||
| static float            GetDraggedColumnOffset(int column_index); |  | ||||||
|  |  | ||||||
| static bool             IsKeyPressedMap(ImGuiKey key, bool repeat = true); | static bool             IsKeyPressedMap(ImGuiKey key, bool repeat = true); | ||||||
|  |  | ||||||
| static ImFont*          GetDefaultFont(); | static ImFont*          GetDefaultFont(); | ||||||
| @@ -1744,8 +1742,8 @@ static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height) | |||||||
|     ImGuiWindow* window = ImGui::GetCurrentWindow(); |     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.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. |     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) |     if (window->DC.ColumnsSet) | ||||||
|         window->DC.ColumnsCellMinY = window->DC.CursorPos.y;                    // Setting this so that cell Y position are set properly |         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 | // 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.ItemFlagsStack.resize(0); | ||||||
|         window->DC.ItemWidthStack.resize(0); |         window->DC.ItemWidthStack.resize(0); | ||||||
|         window->DC.TextWrapPosStack.resize(0); |         window->DC.TextWrapPosStack.resize(0); | ||||||
|         window->DC.ColumnsCurrent = 0; |         window->DC.ColumnsSet = NULL; | ||||||
|         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.TreeDepth = 0; |         window->DC.TreeDepth = 0; | ||||||
|         window->DC.StateStorage = &window->StateStorage; |         window->DC.StateStorage = &window->StateStorage; | ||||||
|         window->DC.GroupStack.resize(0); |         window->DC.GroupStack.resize(0); | ||||||
| @@ -4990,7 +4984,7 @@ void ImGui::End() | |||||||
|     ImGuiContext& g = *GImGui; |     ImGuiContext& g = *GImGui; | ||||||
|     ImGuiWindow* window = g.CurrentWindow; |     ImGuiWindow* window = g.CurrentWindow; | ||||||
|  |  | ||||||
|     if (window->DC.ColumnsCount != 1) // close columns set if any is open |     if (window->DC.ColumnsSet != NULL) | ||||||
|         EndColumns(); |         EndColumns(); | ||||||
|     PopClipRect();   // inner window clip rectangle |     PopClipRect();   // inner window clip rectangle | ||||||
|  |  | ||||||
| @@ -5736,8 +5730,8 @@ ImVec2 ImGui::GetContentRegionMax() | |||||||
| { | { | ||||||
|     ImGuiWindow* window = GetCurrentWindowRead(); |     ImGuiWindow* window = GetCurrentWindowRead(); | ||||||
|     ImVec2 mx = window->ContentsRegionRect.Max; |     ImVec2 mx = window->ContentsRegionRect.Max; | ||||||
|     if (window->DC.ColumnsCount != 1) |     if (window->DC.ColumnsSet) | ||||||
|         mx.x = GetColumnOffset(window->DC.ColumnsCurrent + 1) - window->WindowPadding.x; |         mx.x = GetColumnOffset(window->DC.ColumnsSet->ColumnsCurrent + 1) - window->WindowPadding.x; | ||||||
|     return mx; |     return mx; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -9347,7 +9341,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl | |||||||
|     ImGuiContext& g = *GImGui; |     ImGuiContext& g = *GImGui; | ||||||
|     const ImGuiStyle& style = g.Style; |     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(); |         PopClipRect(); | ||||||
|  |  | ||||||
|     ImGuiID id = window->GetID(label); |     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; |     bb_with_spacing.Max.y += spacing_D; | ||||||
|     if (!ItemAdd(bb_with_spacing, id)) |     if (!ItemAdd(bb_with_spacing, id)) | ||||||
|     { |     { | ||||||
|         if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) |         if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet) | ||||||
|             PushColumnClipRect(); |             PushColumnClipRect(); | ||||||
|         return false; |         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); |         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(); |         PushColumnClipRect(); | ||||||
|         bb_with_spacing.Max.x -= (GetContentRegionMax().x - max_x); |         bb_with_spacing.Max.x -= (GetContentRegionMax().x - max_x); | ||||||
| @@ -10552,7 +10546,7 @@ void ImGui::Separator() | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Horizontal Separator |     // Horizontal Separator | ||||||
|     if (window->DC.ColumnsCount > 1) |     if (window->DC.ColumnsSet) | ||||||
|         PopClipRect(); |         PopClipRect(); | ||||||
|  |  | ||||||
|     float x1 = window->Pos.x; |     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. |     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 (!ItemAdd(bb, 0)) | ||||||
|     { |     { | ||||||
|         if (window->DC.ColumnsCount > 1) |         if (window->DC.ColumnsSet) | ||||||
|             PushColumnClipRect(); |             PushColumnClipRect(); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -10574,10 +10568,10 @@ void ImGui::Separator() | |||||||
|     if (g.LogEnabled) |     if (g.LogEnabled) | ||||||
|             LogRenderedText(NULL, IM_NEWLINE "--------------------------------"); |             LogRenderedText(NULL, IM_NEWLINE "--------------------------------"); | ||||||
|  |  | ||||||
|     if (window->DC.ColumnsCount > 1) |     if (window->DC.ColumnsSet) | ||||||
|     { |     { | ||||||
|         PushColumnClipRect(); |         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() | void ImGui::NextColumn() | ||||||
| { | { | ||||||
|     ImGuiWindow* window = GetCurrentWindow(); |     ImGuiWindow* window = GetCurrentWindow(); | ||||||
|     if (window->SkipItems || window->DC.ColumnsCount <= 1) |     if (window->SkipItems || window->DC.ColumnsSet == NULL) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     ImGuiContext& g = *GImGui; |     ImGuiContext& g = *GImGui; | ||||||
|     PopItemWidth(); |     PopItemWidth(); | ||||||
|     PopClipRect(); |     PopClipRect(); | ||||||
|  |  | ||||||
|     window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); |     ImGuiColumnsSet* columns = window->DC.ColumnsSet; | ||||||
|     if (++window->DC.ColumnsCurrent < window->DC.ColumnsCount) |     columns->ColumnsCellMaxY = ImMax(columns->ColumnsCellMaxY, window->DC.CursorPos.y); | ||||||
|  |     if (++columns->ColumnsCurrent < columns->ColumnsCount) | ||||||
|     { |     { | ||||||
|         // Columns 1+ cancel out IndentX |         // Columns 1+ cancel out IndentX | ||||||
|         window->DC.ColumnsOffsetX = GetColumnOffset(window->DC.ColumnsCurrent) - window->DC.IndentX + g.Style.ItemSpacing.x; |         window->DC.ColumnsOffsetX = GetColumnOffset(columns->ColumnsCurrent) - window->DC.IndentX + g.Style.ItemSpacing.x; | ||||||
|         window->DrawList->ChannelsSetCurrent(window->DC.ColumnsCurrent); |         window->DrawList->ChannelsSetCurrent(columns->ColumnsCurrent); | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
|         window->DC.ColumnsCurrent = 0; |  | ||||||
|         window->DC.ColumnsOffsetX = 0.0f; |         window->DC.ColumnsOffsetX = 0.0f; | ||||||
|         window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY; |         columns->ColumnsCurrent = 0; | ||||||
|  |         columns->ColumnsCellMinY = columns->ColumnsCellMaxY; | ||||||
|         window->DrawList->ChannelsSetCurrent(0); |         window->DrawList->ChannelsSetCurrent(0); | ||||||
|     } |     } | ||||||
|     window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); |     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.CurrentLineHeight = 0.0f; | ||||||
|     window->DC.CurrentLineTextBaseOffset = 0.0f; |     window->DC.CurrentLineTextBaseOffset = 0.0f; | ||||||
|  |  | ||||||
| @@ -10823,37 +10818,37 @@ void ImGui::NextColumn() | |||||||
| int ImGui::GetColumnIndex() | int ImGui::GetColumnIndex() | ||||||
| { | { | ||||||
|     ImGuiWindow* window = GetCurrentWindowRead(); |     ImGuiWindow* window = GetCurrentWindowRead(); | ||||||
|     return window->DC.ColumnsCurrent; |     return window->DC.ColumnsSet ? window->DC.ColumnsSet->ColumnsCurrent : 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| int ImGui::GetColumnsCount() | int ImGui::GetColumnsCount() | ||||||
| { | { | ||||||
|     ImGuiWindow* window = GetCurrentWindowRead(); |     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 |     // 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. |     // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning. | ||||||
|     ImGuiContext& g = *GImGui; |     ImGuiContext& g = *GImGui; | ||||||
|     ImGuiWindow* window = g.CurrentWindow; |     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(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; |     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 ((window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths)) |     if ((columns->ColumnsFlags & 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; |     return x; | ||||||
| @@ -10862,44 +10857,50 @@ static float GetDraggedColumnOffset(int column_index) | |||||||
| float ImGui::GetColumnOffset(int column_index) | float ImGui::GetColumnOffset(int column_index) | ||||||
| { | { | ||||||
|     ImGuiWindow* window = GetCurrentWindowRead(); |     ImGuiWindow* window = GetCurrentWindowRead(); | ||||||
|  |     ImGuiColumnsSet* columns = window->DC.ColumnsSet; | ||||||
|  |     IM_ASSERT(columns != NULL); | ||||||
|  |  | ||||||
|     if (column_index < 0) |     if (column_index < 0) | ||||||
|         column_index = window->DC.ColumnsCurrent; |         column_index = columns->ColumnsCurrent; | ||||||
|  |  | ||||||
|     /* |     /* | ||||||
|     if (g.ActiveId) |     if (g.ActiveId) | ||||||
|     { |     { | ||||||
|         ImGuiContext& g = *GImGui; |         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) |         if (g.ActiveId == column_id) | ||||||
|             return GetDraggedColumnOffset(column_index); |             return GetDraggedColumnOffset(columns, column_index); | ||||||
|     } |     } | ||||||
|     */ |     */ | ||||||
|  |  | ||||||
|     IM_ASSERT(column_index < window->DC.ColumnsData.Size); |     IM_ASSERT(column_index < columns->ColumnsData.Size); | ||||||
|     const float t = window->DC.ColumnsData[column_index].OffsetNorm; |     const float t = columns->ColumnsData[column_index].OffsetNorm; | ||||||
|     const float x_offset = ImLerp(window->DC.ColumnsMinX, window->DC.ColumnsMaxX, t); |     const float x_offset = ImLerp(columns->ColumnsMinX, columns->ColumnsMaxX, t); | ||||||
|     return x_offset; |     return x_offset; | ||||||
| } | } | ||||||
|  |  | ||||||
| void ImGui::SetColumnOffset(int column_index, float offset) | void ImGui::SetColumnOffset(int column_index, float offset) | ||||||
| { | { | ||||||
|     ImGuiContext& g = *GImGui; |     ImGuiContext& g = *GImGui; | ||||||
|     ImGuiWindow* window = GetCurrentWindow(); |     ImGuiWindow* window = g.CurrentWindow; | ||||||
|  |     ImGuiColumnsSet* columns = window->DC.ColumnsSet; | ||||||
|  |     IM_ASSERT(columns != NULL); | ||||||
|  |  | ||||||
|     if (column_index < 0) |     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; |     const float width = preserve_width ? GetColumnWidth(column_index) : 0.0f; | ||||||
|  |  | ||||||
|     if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) |     if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) | ||||||
|         offset = ImMin(offset, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index)); |         offset = ImMin(offset, columns->ColumnsMaxX - g.Style.ColumnsMinSpacing * (columns->ColumnsCount - column_index)); | ||||||
|     const float offset_norm = PixelsToOffsetNorm(window, offset); |     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.StateStorage->SetFloat(column_id, offset_norm); | ||||||
|     window->DC.ColumnsData[column_index].OffsetNorm = offset_norm; |     columns->ColumnsData[column_index].OffsetNorm = offset_norm; | ||||||
|  |  | ||||||
|     if (preserve_width) |     if (preserve_width) | ||||||
|         SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, 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) | float ImGui::GetColumnWidth(int column_index) | ||||||
| { | { | ||||||
|     ImGuiWindow* window = GetCurrentWindowRead(); |     ImGuiWindow* window = GetCurrentWindowRead(); | ||||||
|     if (column_index < 0) |     ImGuiColumnsSet* columns = window->DC.ColumnsSet; | ||||||
|         column_index = window->DC.ColumnsCurrent; |     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) | void ImGui::SetColumnWidth(int column_index, float width) | ||||||
| { | { | ||||||
|     ImGuiWindow* window = GetCurrentWindowRead(); |     ImGuiWindow* window = GetCurrentWindowRead(); | ||||||
|     if (column_index < 0) |     ImGuiColumnsSet* columns = window->DC.ColumnsSet; | ||||||
|         column_index = window->DC.ColumnsCurrent; |     IM_ASSERT(columns != NULL); | ||||||
|  |  | ||||||
|  |     if (column_index < 0) | ||||||
|  |         column_index = columns->ColumnsCurrent; | ||||||
|     SetColumnOffset(column_index+1, GetColumnOffset(column_index) + width); |     SetColumnOffset(column_index+1, GetColumnOffset(column_index) + width); | ||||||
| } | } | ||||||
|  |  | ||||||
| void ImGui::PushColumnClipRect(int column_index) | void ImGui::PushColumnClipRect(int column_index) | ||||||
| { | { | ||||||
|     ImGuiWindow* window = GetCurrentWindowRead(); |     ImGuiWindow* window = GetCurrentWindowRead(); | ||||||
|  |     ImGuiColumnsSet* columns = window->DC.ColumnsSet; | ||||||
|     if (column_index < 0) |     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; |     ImGuiContext& g = *GImGui; | ||||||
|     ImGuiWindow* window = GetCurrentWindow(); |     ImGuiWindow* window = GetCurrentWindow(); | ||||||
|  |  | ||||||
|     IM_ASSERT(columns_count > 1); |     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. |     // 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. |     // 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)); |     PushID(0x11223347 + (str_id ? 0 : columns_count)); | ||||||
|     window->DC.ColumnsSetId = window->GetID(id ? id : "columns"); |     ImGuiID id = window->GetID(str_id ? str_id : "columns"); | ||||||
|     PopID(); |     PopID(); | ||||||
|  |  | ||||||
|  |     ImGuiColumnsSet* columns = FindOrAddColumnsSet(window, id); | ||||||
|  |     IM_ASSERT(columns->ColumnsSetId == id); | ||||||
|  |     window->DC.ColumnsSet = columns; | ||||||
|  |  | ||||||
|     // Set state for first column |     // Set state for first column | ||||||
|     window->DC.ColumnsCurrent = 0; |     columns->ColumnsCurrent = 0; | ||||||
|     window->DC.ColumnsCount = columns_count; |     columns->ColumnsCount = columns_count; | ||||||
|     window->DC.ColumnsFlags = flags; |     columns->ColumnsFlags = flags; | ||||||
|  |  | ||||||
|     const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->Size.x -window->ScrollbarSizes.x); |     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 |     columns->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; |     //column->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; |     columns->ColumnsMaxX = content_region_width - window->Scroll.x; | ||||||
|     window->DC.ColumnsStartPosY = window->DC.CursorPos.y; |     columns->ColumnsStartPosY = window->DC.CursorPos.y; | ||||||
|     window->DC.ColumnsStartMaxPosX = window->DC.CursorMaxPos.x; |     columns->ColumnsStartMaxPosX = window->DC.CursorMaxPos.x; | ||||||
|     window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.CursorPos.y; |     columns->ColumnsCellMinY = columns->ColumnsCellMaxY = window->DC.CursorPos.y; | ||||||
|     window->DC.ColumnsOffsetX = 0.0f; |     window->DC.ColumnsOffsetX = 0.0f; | ||||||
|     window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); |     window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); | ||||||
|  |  | ||||||
|     // Cache column offsets |     // 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++) |     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); |         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); |         float t = window->DC.StateStorage->GetFloat(column_id, default_t); | ||||||
|         if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) |         if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) | ||||||
|             t = ImMin(t, PixelsToOffsetNorm(window, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index))); |             t = ImMin(t, PixelsToOffsetNorm(columns, columns->ColumnsMaxX - g.Style.ColumnsMinSpacing * (columns->ColumnsCount - column_index))); | ||||||
|         window->DC.ColumnsData[column_index].OffsetNorm = t; |         columns->ColumnsData[column_index].OffsetNorm = t; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Cache clipping rectangles |     // 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_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); |         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); |         columns->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.ClipWith(window->ClipRect); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     window->DrawList->ChannelsSplit(window->DC.ColumnsCount); |     window->DrawList->ChannelsSplit(columns->ColumnsCount); | ||||||
|     PushColumnClipRect(); |     PushColumnClipRect(); | ||||||
|     PushItemWidth(GetColumnWidth() * 0.65f); |     PushItemWidth(GetColumnWidth() * 0.65f); | ||||||
| } | } | ||||||
| @@ -10992,34 +11014,35 @@ void ImGui::EndColumns() | |||||||
| { | { | ||||||
|     ImGuiContext& g = *GImGui; |     ImGuiContext& g = *GImGui; | ||||||
|     ImGuiWindow* window = GetCurrentWindow(); |     ImGuiWindow* window = GetCurrentWindow(); | ||||||
|     IM_ASSERT(window->DC.ColumnsCount > 1); |     ImGuiColumnsSet* columns = window->DC.ColumnsSet; | ||||||
|  |     IM_ASSERT(columns != NULL); | ||||||
|  |  | ||||||
|     PopItemWidth(); |     PopItemWidth(); | ||||||
|     PopClipRect(); |     PopClipRect(); | ||||||
|     window->DrawList->ChannelsMerge(); |     window->DrawList->ChannelsMerge(); | ||||||
|  |  | ||||||
|     window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); |     columns->ColumnsCellMaxY = ImMax(columns->ColumnsCellMaxY, window->DC.CursorPos.y); | ||||||
|     window->DC.CursorPos.y = window->DC.ColumnsCellMaxY; |     window->DC.CursorPos.y = columns->ColumnsCellMaxY; | ||||||
|     if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_GrowParentContentsSize)) |     if (!(columns->ColumnsFlags & ImGuiColumnsFlags_GrowParentContentsSize)) | ||||||
|         window->DC.CursorMaxPos.x = ImMax(window->DC.ColumnsStartMaxPosX, window->DC.ColumnsMaxX);  // Restore cursor max pos, as columns don't grow parent |         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 |     // 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; |         const float y2 = window->DC.CursorPos.y; | ||||||
|         int dragging_column = -1; |         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); |             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 float column_hw = 4.0f; // Half-width for interaction | ||||||
|             const ImRect column_rect(ImVec2(x - column_hw, y1), ImVec2(x + column_hw, y2)); |             const ImRect column_rect(ImVec2(x - column_hw, y1), ImVec2(x + column_hw, y2)); | ||||||
|             if (IsClippedEx(column_rect, column_id, false)) |             if (IsClippedEx(column_rect, column_id, false)) | ||||||
|                 continue; |                 continue; | ||||||
|              |              | ||||||
|             bool hovered = false, held = false; |             bool hovered = false, held = false; | ||||||
|             if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoResize)) |             if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoResize)) | ||||||
|             { |             { | ||||||
|                 ButtonBehavior(column_rect, column_id, &hovered, &held); |                 ButtonBehavior(column_rect, column_id, &hovered, &held); | ||||||
|                 if (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. |         // 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 (dragging_column != -1) | ||||||
|         { |         { | ||||||
|             float x = GetDraggedColumnOffset(dragging_column); |             float x = GetDraggedColumnOffset(columns, dragging_column); | ||||||
|             SetColumnOffset(dragging_column, x); |             SetColumnOffset(dragging_column, x); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     window->DC.ColumnsSetId = 0; |     columns->ColumnsData.resize(0); | ||||||
|     window->DC.ColumnsCurrent = 0; |     window->DC.ColumnsSet = NULL; | ||||||
|     window->DC.ColumnsCount = 1; |  | ||||||
|     window->DC.ColumnsFlags = 0; |  | ||||||
|     window->DC.ColumnsData.resize(0); |  | ||||||
|     window->DC.ColumnsOffsetX = 0.0f; |     window->DC.ColumnsOffsetX = 0.0f; | ||||||
|     window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); |     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(); |     ImGuiWindow* window = GetCurrentWindow(); | ||||||
|     IM_ASSERT(columns_count >= 1); |     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(); |         EndColumns(); | ||||||
|      |      | ||||||
|     ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder); |     ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder); | ||||||
|   | |||||||
| @@ -331,14 +331,6 @@ struct ImGuiGroupData | |||||||
|     bool        AdvanceCursor; |     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. | // 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 | 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; } |     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<ImGuiColumnData> 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 | // Main state for ImGui | ||||||
| struct ImGuiContext | 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                   IndentX;                // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) | ||||||
|     float                   GroupOffsetX; |     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. |     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; |     ImGuiColumnsSet*          ColumnsSet; | ||||||
|     int                     ColumnsCount; |     ImVector<ImGuiColumnsSet> ColumnsSets; | ||||||
|     float                   ColumnsMinX; |  | ||||||
|     float                   ColumnsMaxX; |  | ||||||
|     float                   ColumnsStartPosY; |  | ||||||
|     float                   ColumnsStartMaxPosX;   // Backup of CursorMaxPos |  | ||||||
|     float                   ColumnsCellMinY; |  | ||||||
|     float                   ColumnsCellMaxY; |  | ||||||
|     ImGuiColumnsFlags       ColumnsFlags; |  | ||||||
|     ImGuiID                 ColumnsSetId; |  | ||||||
|     ImVector<ImGuiColumnData> ColumnsData; |  | ||||||
|  |  | ||||||
|     ImGuiDrawContext() |     ImGuiDrawContext() | ||||||
|     { |     { | ||||||
| @@ -708,14 +727,7 @@ struct IMGUI_API ImGuiDrawContext | |||||||
|         IndentX = 0.0f; |         IndentX = 0.0f; | ||||||
|         GroupOffsetX = 0.0f; |         GroupOffsetX = 0.0f; | ||||||
|         ColumnsOffsetX = 0.0f; |         ColumnsOffsetX = 0.0f; | ||||||
|         ColumnsCurrent = 0; |         ColumnsSet = NULL; | ||||||
|         ColumnsCount = 1; |  | ||||||
|         ColumnsMinX = ColumnsMaxX = 0.0f; |  | ||||||
|         ColumnsStartPosY = 0.0f; |  | ||||||
|         ColumnsStartMaxPosX = 0.0f; |  | ||||||
|         ColumnsCellMinY = ColumnsCellMaxY = 0.0f; |  | ||||||
|         ColumnsFlags = 0; |  | ||||||
|         ColumnsSetId = 0; |  | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -877,7 +889,7 @@ namespace ImGui | |||||||
|     IMGUI_API bool          IsDragDropPayloadBeingAccepted(); |     IMGUI_API bool          IsDragDropPayloadBeingAccepted(); | ||||||
|  |  | ||||||
|     // FIXME-WIP: New Columns API |     // 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          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          EndColumns();                                                             // close columns | ||||||
|     IMGUI_API void          PushColumnClipRect(int column_index = -1); |     IMGUI_API void          PushColumnClipRect(int column_index = -1); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user