@@ -5147,6 +5147,156 @@ static void DemoWindowLayout()
51475147
51485148 ImGui::TreePop();
51495149 }
5150+
5151+ #if IMGUI_HAS_STACK_LAYOUT
5152+ IMGUI_DEMO_MARKER("Layout/Stack Layout");
5153+ if (ImGui::TreeNode("Stack Layout"))
5154+ {
5155+ static bool widget_a = true, widget_b = true, widget_c = true;
5156+ static bool spring_a = true, spring_ab = true, spring_bc = true, spring_c = true;
5157+ static bool minimize_width = false, minimize_height = true;
5158+ static bool horizontal = true, draw_springs = true;
5159+ static ImVec2 item_spacing = ImGui::GetStyle().ItemSpacing;
5160+ static float a_c_spring_weight = 0.0f;
5161+ static float ab_spring_weight = 0.5f;
5162+ static float alignment = 0.5f;
5163+
5164+ struct funcs
5165+ {
5166+ static void VisibleSpring(float spring_weight)
5167+ {
5168+ ImGui::Spring(spring_weight);
5169+ if (!draw_springs)
5170+ return;
5171+
5172+ ImVec2 rect_min = ImGui::GetItemRectMin();
5173+ ImVec2 rect_max = ImGui::GetItemRectMax();
5174+
5175+ ImVec2 rect_size = ImGui::GetItemRectSize();
5176+ if (rect_size.x <= 0.0f && rect_size.y <= 0.0f)
5177+ return;
5178+
5179+ // Draw zig-zag
5180+ float width = 0.0f, spacing = 0.0f;
5181+ ImVec2 direction, origin;
5182+ ImVec2 spacing_min, spring_max;
5183+
5184+ if (horizontal)
5185+ {
5186+ spacing = floorf(item_spacing.x);
5187+ width = rect_size.x - spacing;
5188+ origin = ImVec2(floorf(rect_min.x), floorf(rect_min.y + (rect_max.y - rect_min.y) / 2));
5189+ direction = ImVec2(1.0f, 0.0f);
5190+ spring_max = ImVec2(rect_min.x + width, rect_max.y);
5191+ spacing_min = ImVec2(rect_min.x + width, rect_min.y);
5192+ }
5193+ else
5194+ {
5195+ spacing = floorf(item_spacing.y);
5196+ width = rect_size.y - spacing;
5197+ origin = ImVec2(floorf(rect_min.x + (rect_max.x - rect_min.x) / 2), floorf(rect_min.y));
5198+ direction = ImVec2(0.0f, 1.0f);
5199+ spring_max = ImVec2(rect_max.x, rect_min.y + width);
5200+ spacing_min = ImVec2(rect_min.x, rect_min.y + width);
5201+ }
5202+
5203+ if (spring_weight <= 0.0f && spacing <= 0.0f)
5204+ return;
5205+
5206+ ImDrawList* draw_list = ImGui::GetWindowDrawList();
5207+
5208+ draw_list->PushClipRect(rect_min, rect_max, true);
5209+
5210+ draw_list->AddRectFilled(rect_min, spring_max, ImColor(80, 20, 80));
5211+ draw_list->AddRectFilled(spacing_min, rect_max, ImColor(80, 20, 20));
5212+
5213+ const float zig_zag_size = 3;
5214+ ImVec2 normal = ImVec2(-direction.y, direction.x);
5215+
5216+ draw_list->PathClear();
5217+ origin.x += 0.5f;
5218+ origin.y += 0.5f;
5219+ draw_list->PathLineTo(origin);
5220+ for (float x = zig_zag_size * 0.5f; x <= width; x += zig_zag_size)
5221+ {
5222+ ImVec2 p;
5223+ p.x = origin.x + direction.x * x + normal.x * zig_zag_size;
5224+ p.y = origin.y + direction.y * x + normal.y * zig_zag_size;
5225+ draw_list->PathLineTo(p);
5226+ normal = ImVec2(-normal.x, -normal.y);
5227+ }
5228+ draw_list->PathStroke(ImColor(255, 255, 255, 190), false, 1.0f);
5229+
5230+ draw_list->PopClipRect();
5231+ }
5232+ };
5233+
5234+ ImGui::Checkbox("Widget A", &widget_a); ImGui::SameLine();
5235+ ImGui::Checkbox("Widget B", &widget_b); ImGui::SameLine();
5236+ ImGui::Checkbox("Widget C", &widget_c);
5237+ ImGui::Checkbox("Spring A", &spring_a); ImGui::SameLine();
5238+ ImGui::Checkbox("Spring AB", &spring_ab); ImGui::SameLine();
5239+ ImGui::Checkbox("Spring BC", &spring_bc); ImGui::SameLine();
5240+ ImGui::Checkbox("Spring C", &spring_c);
5241+ ImGui::Checkbox("Horizontal", &horizontal); ImGui::SameLine();
5242+ ImGui::Checkbox("Minimize Width", &minimize_width); ImGui::SameLine();
5243+ ImGui::Checkbox("Minimize Height", &minimize_height);
5244+ ImGui::Checkbox("Draw Springs", &draw_springs); ImGui::SameLine();
5245+ ImGui::TextUnformatted(" "); ImGui::SameLine();
5246+ ImGui::ColorButton("- Spring", ImColor(80, 20, 80), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoPicker); ImGui::SameLine();
5247+ ImGui::TextUnformatted("Spring"); ImGui::SameLine();
5248+ ImGui::TextUnformatted(" "); ImGui::SameLine();
5249+ ImGui::ColorButton("- Spacing", ImColor(80, 20, 20), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoPicker); ImGui::SameLine();
5250+ ImGui::TextUnformatted("Item Spacing");
5251+ ImGui::DragFloat("Item Spacing", horizontal ? &item_spacing.x : &item_spacing.y, 0.1f, 0.0f, 50.0f);
5252+ ImGui::DragFloat("A & C Spring Weight", &a_c_spring_weight, 0.002f, 0.0f, 1.0f);
5253+ ImGui::DragFloat("AB Spring Weight", &ab_spring_weight, 0.002f, 0.0f, 1.0f);
5254+ if (ImGui::IsItemHovered()) ImGui::SetTooltip("BC Spring Weight = 1 - AB Spring Weight");
5255+ ImGui::DragFloat("Minor Axis Alignment", &alignment, 0.002f, 0.0f, 1.0f);
5256+ if (ImGui::IsItemHovered()) ImGui::SetTooltip("This is vertical alignment for horizontal layouts and horizontal alignment for vertical layouts.");
5257+ ImGui::Text("Layout widgets:");
5258+ ImGui::Text("| Spring A | Widget A | Spring AB | Widget B | Spring BC | Widget C | Spring C |");
5259+
5260+ ImGui::Spacing();
5261+
5262+ ImVec2 widget_size;
5263+ widget_size.x = floorf(ImGui::GetContentRegionAvail().x / 4);
5264+ widget_size.y = horizontal ? floorf(widget_size.x / 3) : widget_size.x;
5265+
5266+ ImVec2 small_widget_size = widget_size;
5267+ if (horizontal)
5268+ small_widget_size.y = floorf(small_widget_size.y / 2);
5269+ else
5270+ small_widget_size.x = floorf(small_widget_size.x / 2);
5271+
5272+ ImVec2 layout_size = ImVec2(widget_size.x * 4, widget_size.y * 4);
5273+ if (minimize_width) layout_size.x = 0.0f;
5274+ if (minimize_height) layout_size.y = 0.0f;
5275+
5276+ // Minor axis alignment can be set by style or directly in BeginHorizontal/BeginVertical
5277+ // Example:
5278+ // ImGui::PushStyleVar(ImGuiStyleVar_LayoutAlign, alignment);
5279+
5280+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(floorf(item_spacing.x), floorf(item_spacing.y)));
5281+
5282+ if (horizontal) { ImGui::BeginHorizontal("h1", layout_size, alignment); } else { ImGui::BeginVertical("v1", layout_size, alignment); }
5283+ if (spring_a) { funcs::VisibleSpring(a_c_spring_weight); }
5284+ if (widget_a) { ImGui::Button("Widget A", widget_size); }
5285+ if (spring_ab) { funcs::VisibleSpring(ab_spring_weight); }
5286+ if (widget_b) { ImGui::Button("Widget B", small_widget_size); }
5287+ if (spring_bc) { funcs::VisibleSpring(1.0f - ab_spring_weight); }
5288+ if (widget_c) { ImGui::Button("Widget C", widget_size); }
5289+ if (spring_c) { funcs::VisibleSpring(a_c_spring_weight); }
5290+ if (horizontal) { ImGui::EndHorizontal(); } else { ImGui::EndVertical(); }
5291+
5292+ ImGui::PopStyleVar();
5293+
5294+ ImDrawList* draw_list = ImGui::GetWindowDrawList();
5295+ draw_list->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), ImGui::GetColorU32(ImGuiCol_Border));
5296+
5297+ ImGui::TreePop();
5298+ }
5299+ #endif // IMGUI_HAS_STACK_LAYOUT
51505300}
51515301
51525302//-----------------------------------------------------------------------------
0 commit comments