Skip to content

Commit

Permalink
Selectable: Allow using ImGuiSelectableFlags_SpanAllColumns in other …
Browse files Browse the repository at this point in the history
…columns than first. Comments. (#125)
  • Loading branch information
ocornut committed Mar 26, 2020
1 parent 5be5add commit ec2a24a
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 14 deletions.
1 change: 1 addition & 0 deletions docs/CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Other Changes:
- InputText: Fixed password fields displaying ASCII spaces as blanks instead of using the '*'
glyph. (#2149, #515)
- Selectable: Fixed honoring style.SelectableTextAlign with unspecified size. (#2347, #2601)
- Selectable: Allow using ImGuiSelectableFlags_SpanAllColumns in other columns than first. (#125)
- Scrolling: Fixed scrolling centering API leading to non-integer scrolling values and initial
cursor position. This would often get fixed after the fix item submission, but using the
ImGuiListClipper as the first thing after Begin() could largely break size calculations. (#3073)
Expand Down
5 changes: 3 additions & 2 deletions docs/TODO.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,12 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- widgets: alignment options in style (e.g. center Selectable, Right-Align within Button, etc.) #1260
- widgets: activate by identifier (trigger button, focus given id)
- widgets: a way to represent "mixed" values, so e.g. all values replaced with *, including check-boxes, colors, etc. with support for multi-components widgets (e.g. SliderFloat3, make only "Y" mixed) (#2644)
- widgets: selectable: generic BeginSelectable()/EndSelectable() mechanism.
- widgets: selectable: a way to visualize partial/mixed selection (e.g. parent tree node has children with mixed selection)
- widgets: checkbox: checkbox with custom glyph inside frame.
- widgets: coloredit: keep reporting as active when picker is on?
- widgets: group/scalarn functions: expose more per-component information. e.g. store NextItemData.ComponentIdx set by scalarn function, groups can expose them back somehow.
- selectable: using (size.x == 0.0f) and (SelectableTextAlign.x > 0.0f) followed by SameLine() is currently not supported.
- selectable: generic BeginSelectable()/EndSelectable() mechanism.
- selectable: a way to visualize partial/mixed selection (e.g. parent tree node has children with mixed selection)

- input text: clean up the mess caused by converting UTF-8 <> wchar. the code is rather inefficient right now and super fragile.
- input text: reorganize event handling, allow CharFilter to modify buffers, allow multiple events? (#541)
Expand Down
2 changes: 1 addition & 1 deletion imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1023,7 +1023,7 @@ ImGuiStyle::ImGuiStyle()
TabBorderSize = 0.0f; // Thickness of border around tabs.
ColorButtonPosition = ImGuiDir_Right; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text.
SelectableTextAlign = ImVec2(0.0f,0.0f);// Alignment of selectable text when button is larger than text.
SelectableTextAlign = ImVec2(0.0f,0.0f);// Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
DisplayWindowPadding = ImVec2(19,19); // Window position are clamped to be visible within the display area or monitors by at least this amount. Only applies to regular windows.
DisplaySafeAreaPadding = ImVec2(3,3); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows.
MouseCursorScale = 1.0f; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later.
Expand Down
10 changes: 7 additions & 3 deletions imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -1141,8 +1141,12 @@ enum ImGuiCol_
};

// Enumeration for PushStyleVar() / PopStyleVar() to temporarily modify the ImGuiStyle structure.
// NB: the enum only refers to fields of ImGuiStyle which makes sense to be pushed/popped inside UI code. During initialization, feel free to just poke into ImGuiStyle directly.
// NB: if changing this enum, you need to update the associated internal table GStyleVarInfo[] accordingly. This is where we link enum values to members offset/type.
// - The enum only refers to fields of ImGuiStyle which makes sense to be pushed/popped inside UI code.
// During initialization or between frames, feel free to just poke into ImGuiStyle directly.
// - Tip: Use your programming IDE navigation facilities on the names in the _second column_ below to find the actual members and their description.
// In Visual Studio IDE: CTRL+comma ("Edit.NavigateTo") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
// With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments.
// - When changing this enum, you need to update the associated internal table GStyleVarInfo[] accordingly. This is where we link enum values to members offset/type.
enum ImGuiStyleVar_
{
// Enum name --------------------- // Member in ImGuiStyle structure (see ImGuiStyle for descriptions)
Expand Down Expand Up @@ -1387,7 +1391,7 @@ struct ImGuiStyle
float TabBorderSize; // Thickness of border around tabs.
ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered).
ImVec2 SelectableTextAlign; // Alignment of selectable text when selectable is larger than text. Defaults to (0.0f, 0.0f) (top-left aligned).
ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
ImVec2 DisplayWindowPadding; // Window position are clamped to be visible within the display area by at least this amount. Only applies to regular windows.
ImVec2 DisplaySafeAreaPadding; // If you cannot see the edges of your screen (e.g. on a TV) increase the safe area padding. Apply to popups/tooltips as well regular windows. NB: Prefer configuring your TV sets correctly!
float MouseCursorScale; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later.
Expand Down
6 changes: 3 additions & 3 deletions imgui_demo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -643,9 +643,9 @@ static void ShowDemoWindowWidgets()
static bool align_label_with_current_x_position = false;
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnArrow", (unsigned int*)&base_flags, ImGuiTreeNodeFlags_OpenOnArrow);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", (unsigned int*)&base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", (unsigned int*)&base_flags, ImGuiTreeNodeFlags_SpanAvailWidth);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", (unsigned int*)&base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); ImGui::SameLine(); HelpMarker("Extend hit area to all available width instead of allowing more items to be layed out after the node.");
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", (unsigned int*)&base_flags, ImGuiTreeNodeFlags_SpanFullWidth);
ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position);
ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position);
ImGui::Text("Hello!");
if (align_label_with_current_x_position)
ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
Expand Down Expand Up @@ -980,7 +980,7 @@ static void ShowDemoWindowWidgets()
}
if (ImGui::TreeNode("Alignment"))
{
HelpMarker("Alignment applies when a selectable is larger than its text content.\nBy default, Selectables uses style.SelectableTextAlign but it can be overriden on a per-item basis using PushStyleVar().");
HelpMarker("By default, Selectables uses style.SelectableTextAlign but it can be overriden on a per-item basis using PushStyleVar(). You'll probably want to always keep your default situation to left-align otherwise it becomes difficult to layout multiple items on a same line");
static bool selected[3*3] = { true, false, true, false, true, false, true, false, true };
for (int y = 0; y < 3; y++)
{
Expand Down
16 changes: 11 additions & 5 deletions imgui_widgets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5558,6 +5558,8 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags

// Tip: pass a non-visible label (e.g. "##dummy") then you can use the space to draw other text or image.
// But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID or use ##unique_id.
// With this scheme, ImGuiSelectableFlags_SpanAllColumns and ImGuiSelectableFlags_AllowItemOverlap are also frequently used flags.
// FIXME: Selectable() with (size.x == 0.0f) and (SelectableTextAlign.x > 0.0f) followed by SameLine() is currently not supported.
bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg)
{
ImGuiWindow* window = GetCurrentWindow();
Expand All @@ -5579,13 +5581,17 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
ItemSize(size, 0.0f);

// Fill horizontal space
const float max_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? GetWindowContentRegionMax().x + window->Pos.x : GetContentRegionMaxAbs().x;
const float min_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? window->ContentRegionRect.Min.x : pos.x;
const float max_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? window->ContentRegionRect.Max.x : GetContentRegionMaxAbs().x;
if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_SpanAvailWidth))
size.x = ImMax(label_size.x, max_x - pos.x);
ImRect bb_align(pos, pos + size);
size.x = ImMax(label_size.x, max_x - min_x);

// Text stays at the submission position, but bounding box may be extended on both sides
const ImVec2 text_min = pos;
const ImVec2 text_max(min_x + size.x, pos.y + size.y);

// Selectables are meant to be tightly packed together with no click-gap, so we extend their box to cover spacing between selectable.
ImRect bb_enlarged = bb_align;
ImRect bb_enlarged(min_x, pos.y, text_max.x, text_max.y);
const float spacing_x = style.ItemSpacing.x;
const float spacing_y = style.ItemSpacing.y;
const float spacing_L = IM_FLOOR(spacing_x * 0.50f);
Expand Down Expand Up @@ -5665,7 +5671,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
PopColumnsBackground();

if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]);
RenderTextClipped(bb_align.Min, bb_align.Max, label, NULL, &label_size, style.SelectableTextAlign, &bb_enlarged);
RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb_enlarged);
if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor();

// Automatically close popups
Expand Down

4 comments on commit ec2a24a

@franciscod
Copy link
Contributor

@franciscod franciscod commented on ec2a24a Apr 25, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this broke us. (EDIT: nope, we just were using the API badly 💃)

Trying to figure out exactly why... We're using a bunch of Selectable + SameLine, so sounds reasonable.

@franciscod
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and this unbreaks us:

diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 3a360b96..b3825bb1 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -5588,10 +5588,10 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
 
     // Text stays at the submission position, but bounding box may be extended on both sides
     const ImVec2 text_min = pos;
-    const ImVec2 text_max(min_x + size.x, pos.y + size.y);
+    const ImVec2 text_max(pos.x + size.x, pos.y + size.y);
 
     // Selectables are meant to be tightly packed together with no click-gap, so we extend their box to cover spacing between selectable.
-    ImRect bb_enlarged(min_x, pos.y, text_max.x, text_max.y);
+    ImRect bb_enlarged(pos.x, pos.y, text_max.x, text_max.y);
     const float spacing_x = style.ItemSpacing.x;
     const float spacing_y = style.ItemSpacing.y;
     const float spacing_L = IM_FLOOR(spacing_x * 0.50f);

@franciscod
Copy link
Contributor

@franciscod franciscod commented on ec2a24a Apr 25, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what we're doing... Now that I look at it, it doesn't make a lot of sense to make every Selectable SpanAllColumns...

        {
            ImGui::Begin("Hello, world!");
            ImVec2 sz(40, 20);
            ImGui::Selectable("a", true, ImGuiSelectableFlags_SpanAllColumns, sz);
            ImGui::SameLine();
            ImGui::Selectable("b", true, ImGuiSelectableFlags_SpanAllColumns, sz);

            ImGui::Selectable("c", true, ImGuiSelectableFlags_SpanAllColumns, sz);
            ImGui::SameLine();
            ImGui::Selectable("d", true, ImGuiSelectableFlags_SpanAllColumns, sz);
            ImGui::End();
        }

However, on v1.75:

Screenshot_2020-04-25_05-55-56

and v1.76:

Screenshot_2020-04-25_05-55-35

@franciscod
Copy link
Contributor

@franciscod franciscod commented on ec2a24a Apr 25, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced every instance of ImGuiSelectableFlags_SpanAllColumns with 0 (we set a size for each one) and the problem is gone.

Please sign in to comment.