From ec2a24a5f13fe8724acda7fc77c3328db6bf076a Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 26 Mar 2020 20:15:44 +0100 Subject: [PATCH] Selectable: Allow using ImGuiSelectableFlags_SpanAllColumns in other columns than first. Comments. (#125) --- docs/CHANGELOG.txt | 1 + docs/TODO.txt | 5 +++-- imgui.cpp | 2 +- imgui.h | 10 +++++++--- imgui_demo.cpp | 6 +++--- imgui_widgets.cpp | 16 +++++++++++----- 6 files changed, 26 insertions(+), 14 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 05739c5c..07c882ba 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -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) diff --git a/docs/TODO.txt b/docs/TODO.txt index e0a8bc12..474b5ce5 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -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) diff --git a/imgui.cpp b/imgui.cpp index da5c5c3f..5dc479f7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -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. diff --git a/imgui.h b/imgui.h index 32059b3b..098ff637 100644 --- a/imgui.h +++ b/imgui.h @@ -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) @@ -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. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 2664cb14..28a5940e 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -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()); @@ -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++) { diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 7d0c9cbe..3a360b96 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -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(); @@ -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); @@ -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