1
0
mirror of https://github.com/ocornut/imgui.git synced 2024-11-28 09:30:56 +01:00

Added SetNextItemWidth() helper to avoid using PushItemWidth/PopItemWidth() for single items.

This commit is contained in:
omar 2019-04-18 18:29:28 +02:00
parent 8d53f834ee
commit 5078fa208b
6 changed files with 90 additions and 69 deletions

View File

@ -46,6 +46,10 @@ Other Changes:
- InputText: Work-around for buggy standard libraries where isprint('\t') returns true. (#2467, #1336) - InputText: Work-around for buggy standard libraries where isprint('\t') returns true. (#2467, #1336)
- InputText: Fixed ImGuiInputTextFlags_AllowTabInput leading to two tabs characters being inserted - InputText: Fixed ImGuiInputTextFlags_AllowTabInput leading to two tabs characters being inserted
if the back-end provided both Key and Character input. (#2467, #1336) if the back-end provided both Key and Character input. (#2467, #1336)
- Added SetNextItemWidth() helper to avoid using PushItemWidth/PopItemWidth() for single items.
Note that SetNextItemWidth() currently only affect the same subset of items as PushItemWidth(),
generally referred to as the large framed+labeled items.
Because the new SetNextItemWidth() function is explicit
- GetMouseDragDelta(): also returns the delta on the mouse button released frame. (#2419) - GetMouseDragDelta(): also returns the delta on the mouse button released frame. (#2419)
- GetMouseDragDelta(): verify that mouse positions are valid otherwise returns zero. - GetMouseDragDelta(): verify that mouse positions are valid otherwise returns zero.
- Inputs: Also add support for horizontal scroll with Shift+Mouse Wheel. (#2424, #1463) [@LucaRood] - Inputs: Also add support for horizontal scroll with Shift+Mouse Wheel. (#2424, #1463) [@LucaRood]

View File

@ -2068,10 +2068,8 @@ ImGuiTextFilter::ImGuiTextFilter(const char* default_filter)
bool ImGuiTextFilter::Draw(const char* label, float width) bool ImGuiTextFilter::Draw(const char* label, float width)
{ {
if (width != 0.0f) if (width != 0.0f)
ImGui::PushItemWidth(width); ImGui::SetNextItemWidth(width);
bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf)); bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
if (width != 0.0f)
ImGui::PopItemWidth();
if (value_changed) if (value_changed)
Build(); Build();
return value_changed; return value_changed;
@ -5744,6 +5742,12 @@ void ImGui::FocusPreviousWindowIgnoringOne(ImGuiWindow* ignore_window)
} }
} }
void ImGui::SetNextItemWidth(float item_width)
{
ImGuiWindow* window = GetCurrentWindow();
window->DC.NextItemWidth = item_width;
}
void ImGui::PushItemWidth(float item_width) void ImGui::PushItemWidth(float item_width)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
@ -5755,8 +5759,6 @@ void ImGui::PushMultiItemsWidths(int components, float w_full)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
const ImGuiStyle& style = GImGui->Style; const ImGuiStyle& style = GImGui->Style;
if (w_full <= 0.0f)
w_full = CalcItemWidth();
const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components));
const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1)));
window->DC.ItemWidthStack.push_back(w_item_last); window->DC.ItemWidthStack.push_back(w_item_last);
@ -5772,11 +5774,21 @@ void ImGui::PopItemWidth()
window->DC.ItemWidth = window->DC.ItemWidthStack.empty() ? window->ItemWidthDefault : window->DC.ItemWidthStack.back(); window->DC.ItemWidth = window->DC.ItemWidthStack.empty() ? window->ItemWidthDefault : window->DC.ItemWidthStack.back();
} }
// Calculate default item width given value passed to PushItemWidth() // Calculate default item width given value passed to PushItemWidth() or SetNextItemWidth(),
float ImGui::CalcItemWidth() // Then consume the
float ImGui::GetNextItemWidth()
{ {
ImGuiWindow* window = GImGui->CurrentWindow; ImGuiWindow* window = GImGui->CurrentWindow;
float w = window->DC.ItemWidth; float w;
if (window->DC.NextItemWidth != FLT_MAX)
{
w = window->DC.NextItemWidth;
window->DC.NextItemWidth = FLT_MAX;
}
else
{
w = window->DC.ItemWidth;
}
if (w < 0.0f) if (w < 0.0f)
{ {
float region_max_x = GetContentRegionMaxScreen().x; float region_max_x = GetContentRegionMaxScreen().x;
@ -5786,10 +5798,21 @@ float ImGui::CalcItemWidth()
return w; return w;
} }
// [Internal] Calculate full item size given user provided 'size' parameter and default width/height. Default width is often == CalcItemWidth(). // Calculate item width *without* popping/consuming NextItemWidth if it was set.
// (rarely used, which is why we avoid calling this from GetNextItemWidth() and instead do a backup/restore here)
float ImGui::CalcItemWidth()
{
ImGuiWindow* window = GImGui->CurrentWindow;
float backup_next_item_width = window->DC.NextItemWidth;
float w = GetNextItemWidth();
window->DC.NextItemWidth = backup_next_item_width;
return w;
}
// [Internal] Calculate full item size given user provided 'size' parameter and default width/height. Default width is often == GetNextItemWidth().
// Those two functions CalcItemWidth vs CalcItemSize are awkwardly named because they are not fully symmetrical. // Those two functions CalcItemWidth vs CalcItemSize are awkwardly named because they are not fully symmetrical.
// Note that only CalcItemWidth() is publicly exposed. // Note that only CalcItemWidth() is publicly exposed.
// The 4.0f here may be changed to match CalcItemWidth() and/or BeginChild() (right now we have a mismatch which is harmless but undesirable) // The 4.0f here may be changed to match GetNextItemWidth() and/or BeginChild() (right now we have a mismatch which is harmless but undesirable)
ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_w, float default_h) ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_w, float default_h)
{ {
ImGuiWindow* window = GImGui->CurrentWindow; ImGuiWindow* window = GImGui->CurrentWindow;
@ -9147,11 +9170,10 @@ void ImGui::LogButtons()
const bool log_to_tty = Button("Log To TTY"); SameLine(); const bool log_to_tty = Button("Log To TTY"); SameLine();
const bool log_to_file = Button("Log To File"); SameLine(); const bool log_to_file = Button("Log To File"); SameLine();
const bool log_to_clipboard = Button("Log To Clipboard"); SameLine(); const bool log_to_clipboard = Button("Log To Clipboard"); SameLine();
PushItemWidth(80.0f);
PushAllowKeyboardFocus(false); PushAllowKeyboardFocus(false);
SetNextItemWidth(80.0f);
SliderInt("Default Depth", &g.LogDepthToExpandDefault, 0, 9, NULL); SliderInt("Default Depth", &g.LogDepthToExpandDefault, 0, 9, NULL);
PopAllowKeyboardFocus(); PopAllowKeyboardFocus();
PopItemWidth();
PopID(); PopID();
// Start logging at the end of the function so that the buttons don't appear in the log // Start logging at the end of the function so that the buttons don't appear in the log
@ -9739,9 +9761,8 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImGui::Checkbox("Show windows begin order", &show_windows_begin_order); ImGui::Checkbox("Show windows begin order", &show_windows_begin_order);
ImGui::Checkbox("Show windows rectangles", &show_windows_rects); ImGui::Checkbox("Show windows rectangles", &show_windows_rects);
ImGui::SameLine(); ImGui::SameLine();
ImGui::PushItemWidth(ImGui::GetFontSize() * 12); ImGui::SetNextItemWidth(ImGui::GetFontSize() * 12);
show_windows_rects |= ImGui::Combo("##rects_type", &show_windows_rect_type, "OuterRect\0" "OuterRectClipped\0" "InnerMainRect\0" "InnerClipRect\0" "ContentsRegionRect\0"); show_windows_rects |= ImGui::Combo("##rects_type", &show_windows_rect_type, "OuterRect\0" "OuterRectClipped\0" "InnerMainRect\0" "InnerClipRect\0" "ContentsRegionRect\0");
ImGui::PopItemWidth();
ImGui::Checkbox("Show clipping rectangle when hovering ImDrawCmd node", &show_drawcmd_clip_rects); ImGui::Checkbox("Show clipping rectangle when hovering ImDrawCmd node", &show_drawcmd_clip_rects);
ImGui::TreePop(); ImGui::TreePop();
} }

View File

@ -321,8 +321,9 @@ namespace ImGui
IMGUI_API ImU32 GetColorU32(ImU32 col); // retrieve given color with style alpha applied IMGUI_API ImU32 GetColorU32(ImU32 col); // retrieve given color with style alpha applied
// Parameters stacks (current window) // Parameters stacks (current window)
IMGUI_API void PushItemWidth(float item_width); // width of items for the common item+label case, pixels. 0.0f = default to ~2/3 of windows width, >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side) IMGUI_API void PushItemWidth(float item_width); // set width of items for common large "item+label" widgets. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side). 0.0f = default to ~2/3 of windows width,
IMGUI_API void PopItemWidth(); IMGUI_API void PopItemWidth();
IMGUI_API void SetNextItemWidth(float item_width); // set width of the _next_ common large "item+label" widget. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side)
IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position
IMGUI_API void PushTextWrapPos(float wrap_local_pos_x = 0.0f); // word-wrapping for Text*() commands. < 0.0f: no wrapping; 0.0f: wrap to end of window (or column); > 0.0f: wrap at 'wrap_pos_x' position in window local space IMGUI_API void PushTextWrapPos(float wrap_local_pos_x = 0.0f); // word-wrapping for Text*() commands. < 0.0f: no wrapping; 0.0f: wrap to end of window (or column); > 0.0f: wrap at 'wrap_pos_x' position in window local space
IMGUI_API void PopTextWrapPos(); IMGUI_API void PopTextWrapPos();

View File

@ -550,9 +550,8 @@ static void ShowDemoWindowWidgets()
ImGui::ListBox("listbox\n(single select)", &listbox_item_current, listbox_items, IM_ARRAYSIZE(listbox_items), 4); ImGui::ListBox("listbox\n(single select)", &listbox_item_current, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
//static int listbox_item_current2 = 2; //static int listbox_item_current2 = 2;
//ImGui::PushItemWidth(-1); //ImGui::SetNextItemWidth(-1);
//ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4); //ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
//ImGui::PopItemWidth();
} }
ImGui::TreePop(); ImGui::TreePop();
@ -1052,7 +1051,8 @@ static void ShowDemoWindowWidgets()
}; };
static int func_type = 0, display_count = 70; static int func_type = 0, display_count = 70;
ImGui::Separator(); ImGui::Separator();
ImGui::PushItemWidth(100); ImGui::Combo("func", &func_type, "Sin\0Saw\0"); ImGui::PopItemWidth(); ImGui::SetNextItemWidth(100);
ImGui::Combo("func", &func_type, "Sin\0Saw\0");
ImGui::SameLine(); ImGui::SameLine();
ImGui::SliderInt("Sample count", &display_count, 1, 400); ImGui::SliderInt("Sample count", &display_count, 1, 400);
float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw; float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;
@ -1667,9 +1667,8 @@ static void ShowDemoWindowLayout()
static int line = 50; static int line = 50;
bool goto_line = ImGui::Button("Goto"); bool goto_line = ImGui::Button("Goto");
ImGui::SameLine(); ImGui::SameLine();
ImGui::PushItemWidth(100); ImGui::SetNextItemWidth(100);
goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue); goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue);
ImGui::PopItemWidth();
// Child 1: no border, enable horizontal scrollbar // Child 1: no border, enable horizontal scrollbar
{ {
@ -1740,35 +1739,36 @@ static void ShowDemoWindowLayout()
if (ImGui::TreeNode("Widgets Width")) if (ImGui::TreeNode("Widgets Width"))
{ {
// Use SetNextItemWidth() to set the width of a single upcoming item.
// Use PushItemWidth()/PopItemWidth() to set the width of a group of items.
static float f = 0.0f; static float f = 0.0f;
ImGui::Text("PushItemWidth(100)"); ImGui::Text("SetNextItemWidth/PushItemWidth(100)");
ImGui::SameLine(); HelpMarker("Fixed width."); ImGui::SameLine(); HelpMarker("Fixed width.");
ImGui::PushItemWidth(100); ImGui::SetNextItemWidth(100);
ImGui::DragFloat("float##1", &f); ImGui::DragFloat("float##1", &f);
ImGui::PopItemWidth();
ImGui::Text("PushItemWidth(GetWindowWidth() * 0.5f)"); ImGui::Text("SetNextItemWidth/PushItemWidth(GetWindowWidth() * 0.5f)");
ImGui::SameLine(); HelpMarker("Half of window width."); ImGui::SameLine(); HelpMarker("Half of window width.");
ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f); ImGui::SetNextItemWidth(ImGui::GetWindowWidth() * 0.5f);
ImGui::DragFloat("float##2", &f); ImGui::DragFloat("float##2", &f);
ImGui::PopItemWidth();
ImGui::Text("PushItemWidth(GetContentRegionAvailWidth() * 0.5f)"); ImGui::Text("SetNextItemWidth/PushItemWidth(GetContentRegionAvailWidth() * 0.5f)");
ImGui::SameLine(); HelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)"); ImGui::SameLine(); HelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() * 0.5f); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvailWidth() * 0.5f);
ImGui::DragFloat("float##3", &f); ImGui::DragFloat("float##3", &f);
ImGui::PopItemWidth();
ImGui::Text("PushItemWidth(-100)"); ImGui::Text("SetNextItemWidth/PushItemWidth(-100)");
ImGui::SameLine(); HelpMarker("Align to right edge minus 100"); ImGui::SameLine(); HelpMarker("Align to right edge minus 100");
ImGui::PushItemWidth(-100); ImGui::SetNextItemWidth(-100);
ImGui::DragFloat("float##4", &f); ImGui::DragFloat("float##4", &f);
ImGui::PopItemWidth();
ImGui::Text("PushItemWidth(-1)"); // Demonstrate using PushItemWidth to surround three items. Calling SetNextItemWidth() before each of them would have the same effect.
ImGui::Text("SetNextItemWidth/PushItemWidth(-1)");
ImGui::SameLine(); HelpMarker("Align to right edge"); ImGui::SameLine(); HelpMarker("Align to right edge");
ImGui::PushItemWidth(-1); ImGui::PushItemWidth(-1);
ImGui::DragFloat("float##5", &f); ImGui::DragFloat("float##5a", &f);
ImGui::DragFloat("float##5b", &f);
ImGui::DragFloat("float##5c", &f);
ImGui::PopItemWidth(); ImGui::PopItemWidth();
ImGui::TreePop(); ImGui::TreePop();
@ -2241,9 +2241,8 @@ static void ShowDemoWindowPopups()
{ {
if (ImGui::Selectable("Set to zero")) value = 0.0f; if (ImGui::Selectable("Set to zero")) value = 0.0f;
if (ImGui::Selectable("Set to PI")) value = 3.1415f; if (ImGui::Selectable("Set to PI")) value = 3.1415f;
ImGui::PushItemWidth(-1); ImGui::SetNextItemWidth(-1);
ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f); ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f);
ImGui::PopItemWidth();
ImGui::EndPopup(); ImGui::EndPopup();
} }
@ -2968,7 +2967,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
} }
ImGui::LogFinish(); ImGui::LogFinish();
} }
ImGui::SameLine(); ImGui::PushItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0"); ImGui::PopItemWidth(); ImGui::SameLine(); ImGui::SetNextItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0");
ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified); ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified);
static ImGuiTextFilter filter; static ImGuiTextFilter filter;
@ -3807,12 +3806,11 @@ static void ShowExampleAppPropertyEditor(bool* p_open)
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
ImGui::TreeNodeEx("Field", ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Bullet, "Field_%d", i); ImGui::TreeNodeEx("Field", ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Bullet, "Field_%d", i);
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::PushItemWidth(-1); ImGui::SetNextItemWidth(-1);
if (i >= 5) if (i >= 5)
ImGui::InputFloat("##value", &dummy_members[i], 1.0f); ImGui::InputFloat("##value", &dummy_members[i], 1.0f);
else else
ImGui::DragFloat("##value", &dummy_members[i], 0.01f); ImGui::DragFloat("##value", &dummy_members[i], 0.01f);
ImGui::PopItemWidth();
ImGui::NextColumn(); ImGui::NextColumn();
} }
ImGui::PopID(); ImGui::PopID();
@ -3952,10 +3950,10 @@ static void ShowExampleAppConstrainedResize(bool* p_open)
if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine(); if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine(); if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); } if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
ImGui::PushItemWidth(200); ImGui::SetNextItemWidth(200);
ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc)); ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc));
ImGui::SetNextItemWidth(200);
ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100); ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
ImGui::PopItemWidth();
ImGui::Checkbox("Auto-resize", &auto_resize); ImGui::Checkbox("Auto-resize", &auto_resize);
for (int i = 0; i < display_lines; i++) for (int i = 0; i < display_lines; i++)
ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, ""); ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, "");
@ -4401,7 +4399,7 @@ void ShowExampleAppDocuments(bool* p_open)
if (ImGui::BeginPopupModal("Save?")) if (ImGui::BeginPopupModal("Save?"))
{ {
ImGui::Text("Save change to the following items?"); ImGui::Text("Save change to the following items?");
ImGui::PushItemWidth(-1.0f); ImGui::SetNextItemWidth(-1.0f);
if (ImGui::ListBoxHeader("##", close_queue_unsaved_documents, 6)) if (ImGui::ListBoxHeader("##", close_queue_unsaved_documents, 6))
{ {
for (int n = 0; n < close_queue.Size; n++) for (int n = 0; n < close_queue.Size; n++)

View File

@ -1146,6 +1146,7 @@ struct IMGUI_API ImGuiWindowTempData
// We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings.
ImGuiItemFlags ItemFlags; // == ItemFlagsStack.back() [empty == ImGuiItemFlags_Default] ImGuiItemFlags ItemFlags; // == ItemFlagsStack.back() [empty == ImGuiItemFlags_Default]
float ItemWidth; // == ItemWidthStack.back(). 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window float ItemWidth; // == ItemWidthStack.back(). 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window
float NextItemWidth;
float TextWrapPos; // == TextWrapPosStack.back() [empty == -1.0f] float TextWrapPos; // == TextWrapPosStack.back() [empty == -1.0f]
ImVector<ImGuiItemFlags>ItemFlagsStack; ImVector<ImGuiItemFlags>ItemFlagsStack;
ImVector<float> ItemWidthStack; ImVector<float> ItemWidthStack;
@ -1181,6 +1182,7 @@ struct IMGUI_API ImGuiWindowTempData
ItemFlags = ImGuiItemFlags_Default_; ItemFlags = ImGuiItemFlags_Default_;
ItemWidth = 0.0f; ItemWidth = 0.0f;
NextItemWidth = +FLT_MAX;
TextWrapPos = -1.0f; TextWrapPos = -1.0f;
memset(StackSizesBackup, 0, sizeof(StackSizesBackup)); memset(StackSizesBackup, 0, sizeof(StackSizesBackup));
@ -1438,9 +1440,10 @@ namespace ImGui
IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged); IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged);
IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id); // Return true if focus is requested IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id); // Return true if focus is requested
IMGUI_API void FocusableItemUnregister(ImGuiWindow* window); IMGUI_API void FocusableItemUnregister(ImGuiWindow* window);
IMGUI_API float GetNextItemWidth();
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h); IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h);
IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
IMGUI_API void PushMultiItemsWidths(int components, float width_full = 0.0f); IMGUI_API void PushMultiItemsWidths(int components, float width_full);
IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled);
IMGUI_API void PopItemFlag(); IMGUI_API void PopItemFlag();
IMGUI_API bool IsItemToggledSelection(); // was the last item selection toggled? (after Selectable(), TreeNode() etc. We only returns toggle _event_ in order to handle clipping correctly) IMGUI_API bool IsItemToggledSelection(); // was the last item selection toggled? (after Selectable(), TreeNode() etc. We only returns toggle _event_ in order to handle clipping correctly)

View File

@ -325,7 +325,7 @@ void ImGui::LabelTextV(const char* label, const char* fmt, va_list args)
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style; const ImGuiStyle& style = g.Style;
const float w = CalcItemWidth(); const float w = GetNextItemWidth();
const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImVec2 label_size = CalcTextSize(label, NULL, true);
const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2)); const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2));
@ -1089,7 +1089,7 @@ void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* over
const ImGuiStyle& style = g.Style; const ImGuiStyle& style = g.Style;
ImVec2 pos = window->DC.CursorPos; ImVec2 pos = window->DC.CursorPos;
ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y*2.0f); ImVec2 size = CalcItemSize(size_arg, GetNextItemWidth(), g.FontSize + style.FramePadding.y*2.0f);
ImRect bb(pos, pos + size); ImRect bb(pos, pos + size);
ItemSize(size, style.FramePadding.y); ItemSize(size, style.FramePadding.y);
if (!ItemAdd(bb, 0)) if (!ItemAdd(bb, 0))
@ -1353,7 +1353,8 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight(); const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImVec2 label_size = CalcTextSize(label, NULL, true);
const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : CalcItemWidth(); const float expected_w = GetNextItemWidth();
const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : expected_w;
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f)); const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
ItemSize(total_bb, style.FramePadding.y); ItemSize(total_bb, style.FramePadding.y);
@ -1978,7 +1979,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, floa
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style; const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(label); const ImGuiID id = window->GetID(label);
const float w = CalcItemWidth(); const float w = GetNextItemWidth();
const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImVec2 label_size = CalcTextSize(label, NULL, true);
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f)); const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));
@ -2052,7 +2053,7 @@ bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* v, int
bool value_changed = false; bool value_changed = false;
BeginGroup(); BeginGroup();
PushID(label); PushID(label);
PushMultiItemsWidths(components); PushMultiItemsWidths(components, GetNextItemWidth());
size_t type_size = GDataTypeInfo[data_type].Size; size_t type_size = GDataTypeInfo[data_type].Size;
for (int i = 0; i < components; i++) for (int i = 0; i < components; i++)
{ {
@ -2099,7 +2100,7 @@ bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_cu
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
PushID(label); PushID(label);
BeginGroup(); BeginGroup();
PushMultiItemsWidths(2); PushMultiItemsWidths(2, GetNextItemWidth());
bool value_changed = DragFloat("##min", v_current_min, v_speed, (v_min >= v_max) ? -FLT_MAX : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), format, power); bool value_changed = DragFloat("##min", v_current_min, v_speed, (v_min >= v_max) ? -FLT_MAX : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), format, power);
PopItemWidth(); PopItemWidth();
@ -2144,7 +2145,7 @@ bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
PushID(label); PushID(label);
BeginGroup(); BeginGroup();
PushMultiItemsWidths(2); PushMultiItemsWidths(2, GetNextItemWidth());
bool value_changed = DragInt("##min", v_current_min, v_speed, (v_min >= v_max) ? INT_MIN : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), format); bool value_changed = DragInt("##min", v_current_min, v_speed, (v_min >= v_max) ? INT_MIN : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), format);
PopItemWidth(); PopItemWidth();
@ -2422,7 +2423,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, co
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style; const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(label); const ImGuiID id = window->GetID(label);
const float w = CalcItemWidth(); const float w = GetNextItemWidth();
const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImVec2 label_size = CalcTextSize(label, NULL, true);
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f)); const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));
@ -2501,7 +2502,7 @@ bool ImGui::SliderScalarN(const char* label, ImGuiDataType data_type, void* v, i
bool value_changed = false; bool value_changed = false;
BeginGroup(); BeginGroup();
PushID(label); PushID(label);
PushMultiItemsWidths(components); PushMultiItemsWidths(components, GetNextItemWidth());
size_t type_size = GDataTypeInfo[data_type].Size; size_t type_size = GDataTypeInfo[data_type].Size;
for (int i = 0; i < components; i++) for (int i = 0; i < components; i++)
{ {
@ -2790,10 +2791,9 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p
BeginGroup(); // The only purpose of the group here is to allow the caller to query item data e.g. IsItemActive() BeginGroup(); // The only purpose of the group here is to allow the caller to query item data e.g. IsItemActive()
PushID(label); PushID(label);
PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2)); SetNextItemWidth(ImMax(1.0f, GetNextItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2));
if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view
value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, data_ptr, format); value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, data_ptr, format);
PopItemWidth();
// Step buttons // Step buttons
const ImVec2 backup_frame_padding = style.FramePadding; const ImVec2 backup_frame_padding = style.FramePadding;
@ -2839,7 +2839,7 @@ bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* v, in
bool value_changed = false; bool value_changed = false;
BeginGroup(); BeginGroup();
PushID(label); PushID(label);
PushMultiItemsWidths(components); PushMultiItemsWidths(components, GetNextItemWidth());
size_t type_size = GDataTypeInfo[data_type].Size; size_t type_size = GDataTypeInfo[data_type].Size;
for (int i = 0; i < components; i++) for (int i = 0; i < components; i++)
{ {
@ -3289,7 +3289,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
BeginGroup(); BeginGroup();
const ImGuiID id = window->GetID(label); const ImGuiID id = window->GetID(label);
const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImVec2 label_size = CalcTextSize(label, NULL, true);
ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? GetTextLineHeight() * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line ImVec2 size = CalcItemSize(size_arg, GetNextItemWidth(), (is_multiline ? GetTextLineHeight() * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size); const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size);
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f)); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f));
@ -4047,7 +4047,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
const ImGuiStyle& style = g.Style; const ImGuiStyle& style = g.Style;
const float square_sz = GetFrameHeight(); const float square_sz = GetFrameHeight();
const float w_extra = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x); const float w_extra = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x);
const float w_items_all = CalcItemWidth() - w_extra; const float w_items_all = GetNextItemWidth() - w_extra;
const char* label_display_end = FindRenderedTextEnd(label); const char* label_display_end = FindRenderedTextEnd(label);
BeginGroup(); BeginGroup();
@ -4112,13 +4112,11 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
}; };
const int fmt_idx = hide_prefix ? 0 : (flags & ImGuiColorEditFlags_DisplayHSV) ? 2 : 1; const int fmt_idx = hide_prefix ? 0 : (flags & ImGuiColorEditFlags_DisplayHSV) ? 2 : 1;
PushItemWidth(w_item_one);
for (int n = 0; n < components; n++) for (int n = 0; n < components; n++)
{ {
if (n > 0) if (n > 0)
SameLine(0, style.ItemInnerSpacing.x); SameLine(0, style.ItemInnerSpacing.x);
if (n + 1 == components) SetNextItemWidth((n + 1 < components) ? w_item_one : w_item_last);
PushItemWidth(w_item_last);
if (flags & ImGuiColorEditFlags_Float) if (flags & ImGuiColorEditFlags_Float)
{ {
value_changed |= DragFloat(ids[n], &f[n], 1.0f/255.0f, 0.0f, hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]); value_changed |= DragFloat(ids[n], &f[n], 1.0f/255.0f, 0.0f, hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]);
@ -4131,8 +4129,6 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
if (!(flags & ImGuiColorEditFlags_NoOptions)) if (!(flags & ImGuiColorEditFlags_NoOptions))
OpenPopupOnItemClick("context"); OpenPopupOnItemClick("context");
} }
PopItemWidth();
PopItemWidth();
} }
else if ((flags & ImGuiColorEditFlags_DisplayHex) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0) else if ((flags & ImGuiColorEditFlags_DisplayHex) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0)
{ {
@ -4142,7 +4138,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", ImClamp(i[0],0,255), ImClamp(i[1],0,255), ImClamp(i[2],0,255), ImClamp(i[3],0,255)); ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", ImClamp(i[0],0,255), ImClamp(i[1],0,255), ImClamp(i[2],0,255), ImClamp(i[3],0,255));
else else
ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", ImClamp(i[0],0,255), ImClamp(i[1],0,255), ImClamp(i[2],0,255)); ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", ImClamp(i[0],0,255), ImClamp(i[1],0,255), ImClamp(i[2],0,255));
PushItemWidth(w_items_all); SetNextItemWidth(w_items_all);
if (InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase)) if (InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase))
{ {
value_changed = true; value_changed = true;
@ -4157,7 +4153,6 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
} }
if (!(flags & ImGuiColorEditFlags_NoOptions)) if (!(flags & ImGuiColorEditFlags_NoOptions))
OpenPopupOnItemClick("context"); OpenPopupOnItemClick("context");
PopItemWidth();
} }
ImGuiWindow* picker_active_window = NULL; ImGuiWindow* picker_active_window = NULL;
@ -4190,9 +4185,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
} }
ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags__PickerMask | ImGuiColorEditFlags__InputMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar; ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags__PickerMask | ImGuiColorEditFlags__InputMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar;
ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf; ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf;
PushItemWidth(square_sz * 12.0f); // Use 256 + bar sizes? SetNextItemWidth(square_sz * 12.0f); // Use 256 + bar sizes?
value_changed |= ColorPicker4("##picker", col, picker_flags, &g.ColorPickerRef.x); value_changed |= ColorPicker4("##picker", col, picker_flags, &g.ColorPickerRef.x);
PopItemWidth();
EndPopup(); EndPopup();
} }
} }
@ -4360,7 +4354,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
ImVec2 picker_pos = window->DC.CursorPos; ImVec2 picker_pos = window->DC.CursorPos;
float square_sz = GetFrameHeight(); float square_sz = GetFrameHeight();
float bars_width = square_sz; // Arbitrary smallish width of Hue/Alpha picking bars float bars_width = square_sz; // Arbitrary smallish width of Hue/Alpha picking bars
float sv_picker_size = ImMax(bars_width * 1, CalcItemWidth() - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box float sv_picker_size = ImMax(bars_width * 1, GetNextItemWidth() - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box
float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x; float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x;
float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x; float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x;
float bars_triangles_half_sz = (float)(int)(bars_width * 0.20f); float bars_triangles_half_sz = (float)(int)(bars_width * 0.20f);
@ -5458,7 +5452,7 @@ bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg)
const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImVec2 label_size = CalcTextSize(label, NULL, true);
// Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar. // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar.
ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y); ImVec2 size = CalcItemSize(size_arg, GetNextItemWidth(), GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y);
ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y)); ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y));
ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size); ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
@ -5575,7 +5569,7 @@ void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_ge
const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImVec2 label_size = CalcTextSize(label, NULL, true);
if (frame_size.x == 0.0f) if (frame_size.x == 0.0f)
frame_size.x = CalcItemWidth(); frame_size.x = GetNextItemWidth();
if (frame_size.y == 0.0f) if (frame_size.y == 0.0f)
frame_size.y = label_size.y + (style.FramePadding.y * 2); frame_size.y = label_size.y + (style.FramePadding.y * 2);