Skip to content

Commit

Permalink
Added BeginGroup() / EndGroup() layout tools (#160)
Browse files Browse the repository at this point in the history
  • Loading branch information
ocornut committed Mar 17, 2015
1 parent da4bfe3 commit 7e29794
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 5 deletions.
115 changes: 111 additions & 4 deletions imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,16 @@ struct ImGuiAabb // 2D axis aligned bounding-box
void Clip(const ImGuiAabb& clip) { Min.x = ImMax(Min.x, clip.Min.x); Min.y = ImMax(Min.y, clip.Min.y); Max.x = ImMin(Max.x, clip.Max.x); Max.y = ImMin(Max.y, clip.Max.y); }
};

struct ImGuiGroupData
{
ImVec2 BackupCursorPos;
ImVec2 BackupCursorMaxPos;
float BackupColumnsStartX;
float BackupCurrentLineHeight;
float BackupCurrentLineTextBaseOffset;
float BackupLogLinePosY;
};

// Temporary per-window data, reset at the beginning of the frame
struct ImGuiDrawContext
{
Expand All @@ -924,6 +934,7 @@ struct ImGuiDrawContext
ImVector<bool> AllowKeyboardFocus;
ImVector<float> ItemWidth; // 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window
ImVector<float> TextWrapPos;
ImVector<ImGuiGroupData> GroupStack;
ImGuiColorEditMode ColorEditMode;
ImGuiStorage* StateStorage;

Expand Down Expand Up @@ -3096,6 +3107,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size, float bg
window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.ColumnsStartPos.y;
window->DC.TreeDepth = 0;
window->DC.StateStorage = &window->StateStorage;
window->DC.GroupStack.resize(0);

if (window->AutoFitFrames > 0)
window->AutoFitFrames--;
Expand Down Expand Up @@ -6383,8 +6395,8 @@ bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg)

// Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar.
ImVec2 size;
size.x = (size_arg.x != 0.0f) ? size_arg.x : ImGui::CalcItemWidth() + style.FramePadding.x * 2.0f;
size.y = (size_arg.y != 0.0f) ? size_arg.y : ImGui::GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y;
size.x = (size_arg.x != 0.0f) ? (size_arg.x) : ImGui::CalcItemWidth() + style.FramePadding.x * 2.0f;
size.y = (size_arg.y != 0.0f) ? (size_arg.y) : ImGui::GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y;
const ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y));
const ImGuiAabb frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
const ImGuiAabb bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
Expand Down Expand Up @@ -6421,6 +6433,9 @@ void ImGui::ListBoxFooter()

ImGui::EndChildFrame();

// Redeclare item size so that it includes the label (we have stored the full size in LastItemAabb)
// We call SameLine() to restore DC.CurrentLine* data
ImGui::SameLine();
parent_window->DC.CursorPos = bb.Min;
ItemSize(bb, style.FramePadding.y);
}
Expand Down Expand Up @@ -6760,6 +6775,52 @@ static bool ItemAdd(const ImGuiAabb& bb, const ImGuiID* id)
return true;
}

void ImGui::BeginGroup()
{
ImGuiWindow* window = GetCurrentWindow();

window->DC.GroupStack.resize(window->DC.GroupStack.size() + 1);
ImGuiGroupData& group_data = window->DC.GroupStack.back();
group_data.BackupCursorPos = window->DC.CursorPos;
group_data.BackupCursorMaxPos = window->DC.CursorMaxPos;
group_data.BackupColumnsStartX = window->DC.ColumnsStartX;
group_data.BackupCurrentLineHeight = window->DC.CurrentLineHeight;
group_data.BackupCurrentLineTextBaseOffset = window->DC.CurrentLineTextBaseOffset;
group_data.BackupLogLinePosY = window->DC.LogLinePosY;

window->DC.ColumnsStartX = window->DC.CursorPos.x - window->Pos.x;
window->DC.CursorMaxPos = window->DC.CursorPos;
window->DC.CurrentLineHeight = 0.0f;
window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f;
}

void ImGui::EndGroup()
{
ImGuiWindow* window = GetCurrentWindow();
ImGuiStyle& style = ImGui::GetStyle();

IM_ASSERT(!window->DC.GroupStack.empty());

ImGuiGroupData& group_data = window->DC.GroupStack.back();

ImGuiAabb group_bb(group_data.BackupCursorPos, window->DC.CursorMaxPos);
group_bb.Max.y -= style.ItemSpacing.y;

window->DC.CursorPos = group_data.BackupCursorPos;
window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos);
window->DC.CurrentLineHeight = group_data.BackupCurrentLineHeight;
window->DC.CurrentLineTextBaseOffset = group_data.BackupCurrentLineTextBaseOffset; // FIXME: Ideally we'll grab the base offset from the first line of the group.
window->DC.ColumnsStartX = group_data.BackupColumnsStartX;
window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f;

ItemSize(group_bb.GetSize(), group_data.BackupCurrentLineTextBaseOffset);
ItemAdd(group_bb, NULL);

window->DC.GroupStack.pop_back();

//window->DrawList->AddRect(group_bb.Min, group_bb.Max, 0xFFFF00FF); // Debug
}

// Gets back to previous line and continue with horizontal layout
// column_x == 0 : follow on previous item
// columm_x != 0 : align to specified column
Expand Down Expand Up @@ -9251,7 +9312,7 @@ void ImGui::ShowTestWindow(bool* opened)
{
if (ImGui::TreeNode("Text Baseline Alignment"))
{
ImGui::TextWrapped("This is testing the vertical alignment that occurs on text to keep it at the same baseline as widgets. Lines only composed of text or \"small\" widgets fit in less vertical spaces than lines with normal widgets.");
ImGui::TextWrapped("(This is testing the vertical alignment that occurs on text to keep it at the same baseline as widgets. Lines only composed of text or \"small\" widgets fit in less vertical spaces than lines with normal widgets)");

ImGui::Text("One\nTwo\nThree"); ImGui::SameLine();
ImGui::Text("Hello\nWorld"); ImGui::SameLine();
Expand Down Expand Up @@ -9283,8 +9344,10 @@ void ImGui::ShowTestWindow(bool* opened)
ImGui::TreePop();
}

if (ImGui::TreeNode("Horizontal Layout using SameLine()"))
if (ImGui::TreeNode("Basic Horizontal Layout"))
{
ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceeding item)");

// Text
ImGui::Text("Hello");
ImGui::SameLine();
Expand Down Expand Up @@ -9335,6 +9398,50 @@ void ImGui::ShowTestWindow(bool* opened)

ImGui::TreePop();
}

if (ImGui::TreeNode("Groups"))
{
ImGui::TextWrapped("(Using ImGui::BeginGroup()/EndGroup() to layout items)");

ImVec2 size;
ImGui::BeginGroup();
{
ImGui::BeginGroup();
ImGui::Button("AAA");
ImGui::SameLine();
ImGui::Button("BBB");
ImGui::SameLine();
ImGui::BeginGroup();
ImGui::Button("CCC");
ImGui::Button("DDD");
ImGui::EndGroup();
if (ImGui::IsItemHovered())
ImGui::SetTooltip("Group hovered");
ImGui::SameLine();
ImGui::Button("EEE");
ImGui::EndGroup();

// Capture the group size and create widgets using the same size
size = ImGui::GetItemRectSize();
const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f };
ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size);
}
ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y));
ImGui::SameLine();
ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y));
ImGui::EndGroup();
ImGui::SameLine();

ImGui::Button("LEVERAGE\nBUZZWORD", size);
ImGui::SameLine();

ImGui::ListBoxHeader("List", size);
ImGui::Selectable("Selected", true);
ImGui::Selectable("Not Selected", false);
ImGui::ListBoxFooter();

ImGui::TreePop();
}
}

if (ImGui::CollapsingHeader("Child regions"))
Expand Down
4 changes: 3 additions & 1 deletion imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,10 @@ namespace ImGui
IMGUI_API void EndTooltip();

// Layout
IMGUI_API void BeginGroup();
IMGUI_API void EndGroup();
IMGUI_API void Separator(); // horizontal line
IMGUI_API void SameLine(int column_x = 0, int spacing_w = -1); // call between widgets to layout them horizontally
IMGUI_API void SameLine(int column_x = 0, int spacing_w = -1); // call between widgets or groups to layout them horizontally
IMGUI_API void Spacing(); // add vertical spacing
IMGUI_API void Indent(); // move content position toward the right by style.IndentSpacing pixels
IMGUI_API void Unindent(); // move content position back to the left (cancel Indent)
Expand Down

0 comments on commit 7e29794

Please sign in to comment.