浏览代码

Merge branch 'ggtucker-master'

omar 8 年之前
父节点
当前提交
ea493fd8da
共有 5 个文件被更改,包括 225 次插入124 次删除
  1. 143 78
      imgui.cpp
  2. 13 11
      imgui.h
  3. 49 30
      imgui_demo.cpp
  4. 2 2
      imgui_draw.cpp
  5. 18 3
      imgui_internal.h

+ 143 - 78
imgui.cpp

@@ -3542,7 +3542,7 @@ static bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags)
 bool ImGui::BeginPopup(const char* str_id)
 {
     ImGuiContext& g = *GImGui;
-    if (g.OpenPopupStack.Size <= g.CurrentPopupStack.Size)	// Early out for performance
+    if (g.OpenPopupStack.Size <= g.CurrentPopupStack.Size) // Early out for performance
     {
         ClearSetNextWindowData(); // We behave like Begin() and need to consume those values
         return false;
@@ -4345,6 +4345,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us
         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.TreeDepth = 0;
         window->DC.StateStorage = &window->StateStorage;
@@ -4450,7 +4451,7 @@ void ImGui::End()
     ImGuiWindow* window = g.CurrentWindow;
 
     if (window->DC.ColumnsCount != 1) // close columns set if any is open
-        Columns(1, "#CLOSECOLUMNS");
+        EndColumns();
     PopClipRect();   // inner window clip rectangle
 
     // Stop logging
@@ -9808,7 +9809,7 @@ void ImGui::EndGroup()
     ImGuiContext& g = *GImGui;
     ImGuiWindow* window = GetCurrentWindow();
 
-    IM_ASSERT(!window->DC.GroupStack.empty());	// Mismatched BeginGroup()/EndGroup() calls
+    IM_ASSERT(!window->DC.GroupStack.empty());    // Mismatched BeginGroup()/EndGroup() calls
 
     ImGuiGroupData& group_data = window->DC.GroupStack.back();
 
@@ -9928,6 +9929,16 @@ int ImGui::GetColumnsCount()
     return window->DC.ColumnsCount;
 }
 
+static float OffsetNormToPixels(ImGuiWindow* window, float offset_norm)
+{
+    return offset_norm * (window->DC.ColumnsMaxX - window->DC.ColumnsMinX);
+}
+
+static float PixelsToOffsetNorm(ImGuiWindow* window, float offset)
+{
+    return (offset - window->DC.ColumnsMinX) / (window->DC.ColumnsMaxX - window->DC.ColumnsMinX);
+}
+
 static float GetDraggedColumnOffset(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
@@ -9938,43 +9949,57 @@ static float GetDraggedColumnOffset(int column_index)
     IM_ASSERT(g.ActiveId == window->DC.ColumnsSetId + ImGuiID(column_index));
 
     float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x - window->Pos.x;
-    x = ImClamp(x, ImGui::GetColumnOffset(column_index-1)+g.Style.ColumnsMinSpacing, 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))
+        x = ImMin(x, ImGui::GetColumnOffset(column_index+1) - g.Style.ColumnsMinSpacing);
 
-    return (float)(int)x;
+    return x;
 }
 
 float ImGui::GetColumnOffset(int column_index)
 {
-    ImGuiContext& g = *GImGui;
     ImGuiWindow* window = GetCurrentWindowRead();
     if (column_index < 0)
         column_index = window->DC.ColumnsCurrent;
 
+    /*
     if (g.ActiveId)
     {
+        ImGuiContext& g = *GImGui;
         const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index);
         if (g.ActiveId == column_id)
             return GetDraggedColumnOffset(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);
-    return (float)(int)x_offset;
+    return x_offset;
 }
 
 void ImGui::SetColumnOffset(int column_index, float offset)
 {
+    ImGuiContext& g = *GImGui;
     ImGuiWindow* window = GetCurrentWindow();
     if (column_index < 0)
         column_index = window->DC.ColumnsCurrent;
 
     IM_ASSERT(column_index < window->DC.ColumnsData.Size);
-    const float t = (offset - window->DC.ColumnsMinX) / (window->DC.ColumnsMaxX - window->DC.ColumnsMinX);
-    window->DC.ColumnsData[column_index].OffsetNorm = t;
+
+    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, t);
+    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 ImGui::GetColumnWidth(int column_index)
@@ -9983,8 +10008,16 @@ float ImGui::GetColumnWidth(int column_index)
     if (column_index < 0)
         column_index = window->DC.ColumnsCurrent;
 
-    float w = GetColumnOffset(column_index+1) - GetColumnOffset(column_index);
-    return w;
+    return OffsetNormToPixels(window, window->DC.ColumnsData[column_index+1].OffsetNorm - window->DC.ColumnsData[column_index].OffsetNorm);
+}
+
+void ImGui::SetColumnWidth(int column_index, float width)
+{
+    ImGuiWindow* window = GetCurrentWindowRead();
+    if (column_index < 0)
+        column_index = window->DC.ColumnsCurrent;
+
+    SetColumnOffset(column_index+1, GetColumnOffset(column_index) + width);
 }
 
 static void PushColumnClipRect(int column_index)
@@ -9998,57 +10031,13 @@ static void PushColumnClipRect(int column_index)
     ImGui::PushClipRect(ImVec2(x1,-FLT_MAX), ImVec2(x2,+FLT_MAX), true);
 }
 
-void ImGui::Columns(int columns_count, const char* id, bool border)
+void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags flags)
 {
     ImGuiContext& g = *GImGui;
     ImGuiWindow* window = GetCurrentWindow();
-    IM_ASSERT(columns_count >= 1);
-
-    if (window->DC.ColumnsCount != 1)
-    {
-        if (window->DC.ColumnsCurrent != 0)
-            ItemSize(ImVec2(0,0));   // Advance to column 0
-        PopItemWidth();
-        PopClipRect();
-        window->DrawList->ChannelsMerge();
-
-        window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y);
-        window->DC.CursorPos.y = window->DC.ColumnsCellMaxY;
-    }
-
-    // Draw columns borders and handle resize at the time of "closing" a columns set
-    if (window->DC.ColumnsCount != columns_count && window->DC.ColumnsCount != 1 && window->DC.ColumnsShowBorders && !window->SkipItems)
-    {
-        const float y1 = window->DC.ColumnsStartPosY;
-        const float y2 = window->DC.CursorPos.y;
-        for (int i = 1; i < window->DC.ColumnsCount; i++)
-        {
-            float x = window->Pos.x + GetColumnOffset(i);
-            const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(i);
-            const float column_w = 4.0f;
-            const ImRect column_rect(ImVec2(x - column_w, y1), ImVec2(x + column_w, y2));
-            if (IsClippedEx(column_rect, &column_id, false))
-                continue;
-
-            bool hovered, held;
-            ButtonBehavior(column_rect, column_id, &hovered, &held);
-            if (hovered || held)
-                g.MouseCursor = ImGuiMouseCursor_ResizeEW;
 
-            // Draw before resize so our items positioning are in sync with the line being drawn
-            const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator);
-            const float xi = (float)(int)x;
-            window->DrawList->AddLine(ImVec2(xi, y1+1.0f), ImVec2(xi, y2), col);
-
-            if (held)
-            {
-                if (g.ActiveIdIsJustActivated)
-                    g.ActiveIdClickOffset.x -= column_w;   // Store from center of column line (we used a 8 wide rect for columns clicking)
-                x = GetDraggedColumnOffset(i);
-                SetColumnOffset(i, x);
-            }
-        }
-    }
+    IM_ASSERT(columns_count > 1);
+    IM_ASSERT(window->DC.ColumnsCount == 1); // 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.
@@ -10059,36 +10048,112 @@ void ImGui::Columns(int columns_count, const char* id, bool border)
     // Set state for first column
     window->DC.ColumnsCurrent = 0;
     window->DC.ColumnsCount = columns_count;
-    window->DC.ColumnsShowBorders = border;
+    window->DC.ColumnsFlags = flags;
 
     const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : window->Size.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->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x;
+    window->DC.ColumnsMaxX = content_region_width - window->Scroll.x - window->ScrollbarSizes.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;
     window->DC.ColumnsOffsetX = 0.0f;
     window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX);
 
-    if (window->DC.ColumnsCount != 1)
+    // Cache column offsets
+    window->DC.ColumnsData.resize(columns_count + 1);
+    for (int column_index = 0; column_index < columns_count + 1; column_index++)
     {
-        // Cache column offsets
-        window->DC.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);
+        KeepAliveID(column_id);
+        const float default_t = column_index / (float)window->DC.ColumnsCount;
+        float t = window->DC.StateStorage->GetFloat(column_id, default_t);      // Cheaply store our floating point value inside the integer (could store a union into the map?)
+        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;
+    }
+    window->DrawList->ChannelsSplit(window->DC.ColumnsCount);
+    PushColumnClipRect();
+    PushItemWidth(GetColumnWidth() * 0.65f);
+}
+
+void ImGui::EndColumns()
+{
+	ImGuiContext& g = *GImGui;
+	ImGuiWindow* window = GetCurrentWindow();
+	IM_ASSERT(window->DC.ColumnsCount > 1);
+
+	PopItemWidth();
+	PopClipRect();
+	window->DrawList->ChannelsMerge();
+
+	window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y);
+	window->DC.CursorPos.y = window->DC.ColumnsCellMaxY;
+    window->DC.CursorMaxPos.x = ImMax(window->DC.ColumnsStartMaxPosX, window->DC.ColumnsMaxX);  // Columns don't grow parent
+
+	// Draw columns borders and handle resize
+	if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems)
+	{
+		const float y1 = window->DC.ColumnsStartPosY;
+		const float y2 = window->DC.CursorPos.y;
+        int dragging_column = -1;
+		for (int i = 1; i < window->DC.ColumnsCount; i++)
+		{
+			float x = window->Pos.x + GetColumnOffset(i);
+			const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(i);
+            const float column_w = 4.0f; // Width for interaction
+            const ImRect column_rect(ImVec2(x - column_w, y1), ImVec2(x + column_w, y2));
+			if (IsClippedEx(column_rect, &column_id, false))
+				continue;
+            
+            bool hovered = false, held = false;
+            if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoResize))
+            {
+                ButtonBehavior(column_rect, column_id, &hovered, &held);
+                if (hovered || held)
+                    g.MouseCursor = ImGuiMouseCursor_ResizeEW;
+                if (held && g.ActiveIdIsJustActivated)
+                    g.ActiveIdClickOffset.x -= column_w; // 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;
+            }
+
+            // Draw column
+            const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator);
+            const float xi = (float)(int)x;
+            window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col);
+        }
+
+        // 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)
         {
-            const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index);
-            KeepAliveID(column_id);
-            const float default_t = column_index / (float)window->DC.ColumnsCount;
-            const float t = window->DC.StateStorage->GetFloat(column_id, default_t);      // Cheaply store our floating point value inside the integer (could store a union into the map?)
-            window->DC.ColumnsData[column_index].OffsetNorm = t;
+            float x = GetDraggedColumnOffset(dragging_column);
+            SetColumnOffset(dragging_column, x);
         }
-        window->DrawList->ChannelsSplit(window->DC.ColumnsCount);
-        PushColumnClipRect();
-        PushItemWidth(GetColumnWidth() * 0.65f);
-    }
-    else
-    {
-        window->DC.ColumnsData.resize(0);
-    }
+	}
+
+	window->DC.ColumnsSetId = 0;
+	window->DC.ColumnsCurrent = 0;
+	window->DC.ColumnsCount = 1;
+	window->DC.ColumnsFlags = 0;
+	window->DC.ColumnsData.resize(0);
+    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]
+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)
+		EndColumns();
+    
+    ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder);
+    //flags |= ImGuiColumnsFlags_NoPreserveWidths; // NB: Legacy behavior
+    if (columns_count != 1)
+        BeginColumns(id, columns_count, flags);
 }
 
 void ImGui::Indent(float indent_w)

+ 13 - 11
imgui.h

@@ -74,6 +74,7 @@ typedef int ImGuiColorEditFlags;    // color edit flags for Color*()        // e
 typedef int ImGuiMouseCursor;       // a mouse cursor identifier            // enum ImGuiMouseCursor_
 typedef int ImGuiWindowFlags;       // window flags for Begin*()            // enum ImGuiWindowFlags_
 typedef int ImGuiCond;              // condition flags for Set*()           // enum ImGuiCond_
+typedef int ImGuiColumnsFlags;      // flags for *Columns*()                // enum ImGuiColumnsFlags_
 typedef int ImGuiInputTextFlags;    // flags for InputText*()               // enum ImGuiInputTextFlags_
 typedef int ImGuiSelectableFlags;   // flags for Selectable()               // enum ImGuiSelectableFlags_
 typedef int ImGuiTreeNodeFlags;     // flags for TreeNode*(), Collapsing*() // enum ImGuiTreeNodeFlags_
@@ -230,14 +231,15 @@ namespace ImGui
     IMGUI_API float         GetItemsLineHeightWithSpacing();                                    // distance (in pixels) between 2 consecutive lines of standard height widgets == GetWindowFontSize() + GetStyle().FramePadding.y*2 + GetStyle().ItemSpacing.y
 
     // Columns
-    // You can also use SameLine(pos_x) for simplified columning. The columns API is still work-in-progress and rather lacking.
-    IMGUI_API void          Columns(int count = 1, const char* id = NULL, bool border = true);  // setup number of columns. use an identifier to distinguish multiple column sets. close with Columns(1).
-    IMGUI_API void          NextColumn();                                                       // next column
-    IMGUI_API int           GetColumnIndex();                                                   // get current column index
-    IMGUI_API float         GetColumnOffset(int column_index = -1);                             // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetcolumnsCount() inclusive. column 0 is usually 0.0f and not resizable unless you call this
-    IMGUI_API void          SetColumnOffset(int column_index, float offset_x);                  // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column
-    IMGUI_API float         GetColumnWidth(int column_index = -1);                              // column width (== GetColumnOffset(GetColumnIndex()+1) - GetColumnOffset(GetColumnOffset())
-    IMGUI_API int           GetColumnsCount();                                                  // number of columns (what was passed to Columns())
+    // You can also use SameLine(pos_x) for simplified columns. The columns API is still work-in-progress and rather lacking.
+    IMGUI_API void          Columns(int count = 1, const char* id = NULL, bool border = true);
+    IMGUI_API void          NextColumn();                                                        // next column, defaults to current row or next row if the current row is finished
+    IMGUI_API int           GetColumnIndex();                                                    // get current column index
+    IMGUI_API float         GetColumnWidth(int column_index = -1);                               // get column width (in pixels). pass -1 to use current column
+    IMGUI_API void          SetColumnWidth(int column_index, float width);                       // set column width (in pixels). pass -1 to use current column
+    IMGUI_API float         GetColumnOffset(int column_index = -1);                              // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetColumnsCount() inclusive. column 0 is typically 0.0f
+    IMGUI_API void          SetColumnOffset(int column_index, float offset_x);                   // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column
+    IMGUI_API int           GetColumnsCount();
 
     // ID scopes
     // If you are creating widgets in a loop you most likely want to push a unique identifier so ImGui can differentiate them.
@@ -431,7 +433,7 @@ namespace ImGui
     IMGUI_API ImVec2        CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f);
     IMGUI_API void          CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end);    // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can.
 
-    IMGUI_API bool          BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags = 0);	// helper to create a child window / scrolling region that looks like a normal widget frame
+    IMGUI_API bool          BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags = 0);    // helper to create a child window / scrolling region that looks like a normal widget frame
     IMGUI_API void          EndChildFrame();
 
     IMGUI_API ImVec4        ColorConvertU32ToFloat4(ImU32 in);
@@ -1071,8 +1073,8 @@ struct ImGuiTextEditCallbackData
 struct ImGuiSizeConstraintCallbackData
 {
     void*   UserData;       // Read-only.   What user passed to SetNextWindowSizeConstraints()
-    ImVec2  Pos;            // Read-only.	Window position, for reference.
-    ImVec2  CurrentSize;    // Read-only.	Current window size.
+    ImVec2  Pos;            // Read-only.    Window position, for reference.
+    ImVec2  CurrentSize;    // Read-only.    Current window size.
     ImVec2  DesiredSize;    // Read-write.  Desired size, based on user's mouse position. Write to this field to restrain resizing.
 };
 

+ 49 - 30
imgui_demo.cpp

@@ -1527,32 +1527,6 @@ void ImGui::ShowTestWindow(bool* p_open)
             ImGui::TreePop();
         }
 
-        // Scrolling columns
-        /*
-        if (ImGui::TreeNode("Scrolling"))
-        {
-            ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y));
-            ImGui::Columns(3);
-            ImGui::Text("ID"); ImGui::NextColumn();
-            ImGui::Text("Name"); ImGui::NextColumn();
-            ImGui::Text("Path"); ImGui::NextColumn();
-            ImGui::Columns(1);
-            ImGui::Separator();
-            ImGui::EndChild();
-            ImGui::BeginChild("##scrollingregion", ImVec2(0, 60));
-            ImGui::Columns(3);
-            for (int i = 0; i < 10; i++)
-            {
-                ImGui::Text("%04d", i); ImGui::NextColumn();
-                ImGui::Text("Foobar"); ImGui::NextColumn();
-                ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn();
-            }
-            ImGui::Columns(1);
-            ImGui::EndChild();
-            ImGui::TreePop();
-        }
-        */
-
         // Create multiple items in a same cell before switching to next column
         if (ImGui::TreeNode("Mixed items"))
         {
@@ -1570,7 +1544,7 @@ void ImGui::ShowTestWindow(bool* p_open)
             ImGui::Text("An extra line here.");
             ImGui::NextColumn();
 
-            ImGui::Text("Sailor");
+                ImGui::Text("Sailor");
             ImGui::Button("Corniflower");
             static float bar = 1.0f;
             ImGui::InputFloat("blue", &bar, 0.05f, 0, 3);
@@ -1607,14 +1581,59 @@ void ImGui::ShowTestWindow(bool* p_open)
             ImGui::SameLine();
             ImGui::Checkbox("vertical", &v_borders);
             ImGui::Columns(4, NULL, v_borders);
-            if (h_borders) ImGui::Separator();
-            for (int i = 0; i < 8; i++)
+            for (int i = 0; i < 4*3; i++)
             {
+                if (h_borders && ImGui::GetColumnIndex() == 0)
+                    ImGui::Separator();
                 ImGui::Text("%c%c%c", 'a'+i, 'a'+i, 'a'+i);
+                ImGui::Text("Width %.2f\nOffset %.2f", ImGui::GetColumnWidth(), ImGui::GetColumnOffset());
                 ImGui::NextColumn();
             }
             ImGui::Columns(1);
-            if (h_borders) ImGui::Separator();
+            if (h_borders)
+                ImGui::Separator();
+            ImGui::TreePop();
+        }
+
+        // Scrolling columns
+        /*
+        if (ImGui::TreeNode("Vertical Scrolling"))
+        {
+            ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y));
+            ImGui::Columns(3);
+            ImGui::Text("ID"); ImGui::NextColumn();
+            ImGui::Text("Name"); ImGui::NextColumn();
+            ImGui::Text("Path"); ImGui::NextColumn();
+            ImGui::Columns(1);
+            ImGui::Separator();
+            ImGui::EndChild();
+            ImGui::BeginChild("##scrollingregion", ImVec2(0, 60));
+            ImGui::Columns(3);
+            for (int i = 0; i < 10; i++)
+            {
+                ImGui::Text("%04d", i); ImGui::NextColumn();
+                ImGui::Text("Foobar"); ImGui::NextColumn();
+                ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn();
+            }
+            ImGui::Columns(1);
+            ImGui::EndChild();
+            ImGui::TreePop();
+        }
+        */
+
+        if (ImGui::TreeNode("Horizontal Scrolling"))
+        {
+            ImGui::SetNextWindowContentWidth(2000);
+            ImGui::BeginChild("##scrollingregion", ImVec2(0, 120), false, ImGuiWindowFlags_HorizontalScrollbar);
+            ImGui::Columns(10);
+            for (int i = 0; i < 20; i++)
+                for (int j = 0; j < 10; j++)
+                {
+                    ImGui::Text("Line %d Column %d", i, j);
+                    ImGui::NextColumn();
+                }
+            ImGui::Columns(1);
+            ImGui::EndChild();
             ImGui::TreePop();
         }
 

+ 2 - 2
imgui_draw.cpp

@@ -1213,8 +1213,8 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
 
     ConfigData.push_back(*font_cfg);
     ImFontConfig& new_font_cfg = ConfigData.back();
-	if (!new_font_cfg.DstFont)
-	    new_font_cfg.DstFont = Fonts.back();
+    if (!new_font_cfg.DstFont)
+        new_font_cfg.DstFont = Fonts.back();
     if (!new_font_cfg.FontDataOwnedByAtlas)
     {
         new_font_cfg.FontData = ImGui::MemAlloc(new_font_cfg.FontDataSize);

+ 18 - 3
imgui_internal.h

@@ -183,6 +183,15 @@ enum ImGuiSliderFlags_
     ImGuiSliderFlags_Vertical               = 1 << 0
 };
 
+enum ImGuiColumnsFlags_
+{
+    // Default: 0
+    ImGuiColumnsFlags_NoBorder              = 1 << 0,   // Disable column dividers
+    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
+};
+
 enum ImGuiSelectableFlagsPrivate_
 {
     // NB: need to be in sync with last value of ImGuiSelectableFlags_
@@ -306,7 +315,7 @@ struct ImGuiGroupData
 // 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)
     //float     IndentX;
 };
 
@@ -596,9 +605,10 @@ struct IMGUI_API ImGuiDrawContext
     float                   ColumnsMinX;
     float                   ColumnsMaxX;
     float                   ColumnsStartPosY;
+    float                   ColumnsStartMaxPosX;   // Backup of CursorMaxPos
     float                   ColumnsCellMinY;
     float                   ColumnsCellMaxY;
-    bool                    ColumnsShowBorders;
+    ImGuiColumnsFlags       ColumnsFlags;
     ImGuiID                 ColumnsSetId;
     ImVector<ImGuiColumnData> ColumnsData;
 
@@ -629,8 +639,9 @@ struct IMGUI_API ImGuiDrawContext
         ColumnsCount = 1;
         ColumnsMinX = ColumnsMaxX = 0.0f;
         ColumnsStartPosY = 0.0f;
+        ColumnsStartMaxPosX = 0.0f;
         ColumnsCellMinY = ColumnsCellMaxY = 0.0f;
-        ColumnsShowBorders = true;
+        ColumnsFlags = 0;
         ColumnsSetId = 0;
     }
 };
@@ -748,6 +759,10 @@ namespace ImGui
     IMGUI_API void          OpenPopupEx(ImGuiID id, bool reopen_existing);
     IMGUI_API bool          IsPopupOpen(ImGuiID id);
 
+    // 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
+
     // NB: All position are in absolute pixels coordinates (never using window coordinates internally)
     // AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. THOSE FUNCTIONS ARE A MESS. THEIR SIGNATURE AND BEHAVIOR WILL CHANGE, THEY NEED TO BE REFACTORED INTO SOMETHING DECENT.
     IMGUI_API void          RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);