mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-07 21:39:54 +02:00
Merge branch 'master' into docking
# Conflicts: # imgui.cpp # imgui_internal.h
This commit is contained in:
@ -1694,21 +1694,21 @@ bool ImGui::Combo(const char* label, int* current_item, const char* items_separa
|
||||
|
||||
static const ImGuiDataTypeInfo GDataTypeInfo[] =
|
||||
{
|
||||
{ sizeof(char), "%d", "%d" }, // ImGuiDataType_S8
|
||||
{ sizeof(unsigned char), "%u", "%u" },
|
||||
{ sizeof(short), "%d", "%d" }, // ImGuiDataType_S16
|
||||
{ sizeof(unsigned short), "%u", "%u" },
|
||||
{ sizeof(int), "%d", "%d" }, // ImGuiDataType_S32
|
||||
{ sizeof(unsigned int), "%u", "%u" },
|
||||
{ sizeof(char), "S8", "%d", "%d" }, // ImGuiDataType_S8
|
||||
{ sizeof(unsigned char), "U8", "%u", "%u" },
|
||||
{ sizeof(short), "S16", "%d", "%d" }, // ImGuiDataType_S16
|
||||
{ sizeof(unsigned short), "U16", "%u", "%u" },
|
||||
{ sizeof(int), "S32", "%d", "%d" }, // ImGuiDataType_S32
|
||||
{ sizeof(unsigned int), "U32", "%u", "%u" },
|
||||
#ifdef _MSC_VER
|
||||
{ sizeof(ImS64), "%I64d","%I64d" }, // ImGuiDataType_S64
|
||||
{ sizeof(ImU64), "%I64u","%I64u" },
|
||||
{ sizeof(ImS64), "S64", "%I64d","%I64d" }, // ImGuiDataType_S64
|
||||
{ sizeof(ImU64), "U64", "%I64u","%I64u" },
|
||||
#else
|
||||
{ sizeof(ImS64), "%lld", "%lld" }, // ImGuiDataType_S64
|
||||
{ sizeof(ImU64), "%llu", "%llu" },
|
||||
{ sizeof(ImS64), "S64", "%lld", "%lld" }, // ImGuiDataType_S64
|
||||
{ sizeof(ImU64), "U64", "%llu", "%llu" },
|
||||
#endif
|
||||
{ sizeof(float), "%f", "%f" }, // ImGuiDataType_Float (float are promoted to double in va_arg)
|
||||
{ sizeof(double), "%f", "%lf" }, // ImGuiDataType_Double
|
||||
{ sizeof(float), "float", "%f", "%f" }, // ImGuiDataType_Float (float are promoted to double in va_arg)
|
||||
{ sizeof(double), "double","%f", "%lf" }, // ImGuiDataType_Double
|
||||
};
|
||||
IM_STATIC_ASSERT(IM_ARRAYSIZE(GDataTypeInfo) == ImGuiDataType_COUNT);
|
||||
|
||||
@ -3698,14 +3698,22 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f
|
||||
// Generic named filters
|
||||
if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific))
|
||||
{
|
||||
// The libc allows overriding locale, with e.g. 'setlocale(LC_NUMERIC, "de_DE.UTF-8");' which affect the output/input of printf/scanf.
|
||||
// The standard mandate that programs starts in the "C" locale where the decimal point is '.'.
|
||||
// We don't really intend to provide widespread support for it, but out of empathy for people stuck with using odd API, we support the bare minimum aka overriding the decimal point.
|
||||
// Change the default decimal_point with:
|
||||
// ImGui::GetCurrentContext()->PlatformLocaleDecimalPoint = *localeconv()->decimal_point;
|
||||
ImGuiContext& g = *GImGui;
|
||||
const unsigned c_decimal_point = (unsigned int)g.PlatformLocaleDecimalPoint;
|
||||
|
||||
// Allow 0-9 . - + * /
|
||||
if (flags & ImGuiInputTextFlags_CharsDecimal)
|
||||
if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/'))
|
||||
if (!(c >= '0' && c <= '9') && (c != c_decimal_point) && (c != '-') && (c != '+') && (c != '*') && (c != '/'))
|
||||
return false;
|
||||
|
||||
// Allow 0-9 . - + * / e E
|
||||
if (flags & ImGuiInputTextFlags_CharsScientific)
|
||||
if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/') && (c != 'e') && (c != 'E'))
|
||||
if (!(c >= '0' && c <= '9') && (c != c_decimal_point) && (c != '-') && (c != '+') && (c != '*') && (c != '/') && (c != 'e') && (c != 'E'))
|
||||
return false;
|
||||
|
||||
// Allow 0-9 a-F A-F
|
||||
@ -4515,6 +4523,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
}
|
||||
}
|
||||
|
||||
if (is_password && !is_displaying_hint)
|
||||
PopFont();
|
||||
|
||||
if (is_multiline)
|
||||
{
|
||||
Dummy(text_size + ImVec2(0.0f, g.FontSize)); // Always add room to scroll an extra line
|
||||
@ -4522,9 +4533,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
if (is_password && !is_displaying_hint)
|
||||
PopFont();
|
||||
|
||||
// Log as text
|
||||
if (g.LogEnabled && (!is_password || is_displaying_hint))
|
||||
LogRenderedText(&draw_pos, buf_display, buf_display_end);
|
||||
@ -6785,7 +6793,7 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected,
|
||||
// - TabBarAddTab() [Internal]
|
||||
// - TabBarRemoveTab() [Internal]
|
||||
// - TabBarCloseTab() [Internal]
|
||||
// - TabBarScrollClamp()v
|
||||
// - TabBarScrollClamp() [Internal]
|
||||
// - TabBarScrollToTab() [Internal]
|
||||
// - TabBarQueueChangeTabOrder() [Internal]
|
||||
// - TabBarScrollingButtons() [Internal]
|
||||
@ -6809,20 +6817,21 @@ ImGuiTabBar::ImGuiTabBar()
|
||||
SelectedTabId = NextSelectedTabId = VisibleTabId = 0;
|
||||
CurrFrameVisible = PrevFrameVisible = -1;
|
||||
LastTabContentHeight = 0.0f;
|
||||
OffsetMax = OffsetMaxIdeal = OffsetNextTab = 0.0f;
|
||||
WidthAllTabs = WidthAllTabsIdeal = OffsetNextTab = 0.0f;
|
||||
ScrollingAnim = ScrollingTarget = ScrollingTargetDistToVisibility = ScrollingSpeed = 0.0f;
|
||||
Flags = ImGuiTabBarFlags_None;
|
||||
ReorderRequestTabId = 0;
|
||||
ReorderRequestDir = 0;
|
||||
TabsActiveCount = 0;
|
||||
WantLayout = VisibleTabWasSubmitted = false;
|
||||
LastTabItemIdx = -1;
|
||||
}
|
||||
|
||||
static int IMGUI_CDECL TabItemComparerByVisibleOffset(const void* lhs, const void* rhs)
|
||||
static int IMGUI_CDECL TabItemComparerByBeginOrder(const void* lhs, const void* rhs)
|
||||
{
|
||||
const ImGuiTabItem* a = (const ImGuiTabItem*)lhs;
|
||||
const ImGuiTabItem* b = (const ImGuiTabItem*)rhs;
|
||||
return (int)(a->Offset - b->Offset);
|
||||
return (int)(a->BeginOrder - b->BeginOrder);
|
||||
}
|
||||
|
||||
static ImGuiTabBar* GetTabBarFromTabBarRef(const ImGuiPtrOrIndex& ref)
|
||||
@ -6874,10 +6883,9 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
|
||||
return true;
|
||||
}
|
||||
|
||||
// When toggling back from ordered to manually-reorderable, shuffle tabs to enforce the last visible order.
|
||||
// Otherwise, the most recently inserted tabs would move at the end of visible list which can be a little too confusing or magic for the user.
|
||||
if ((flags & ImGuiTabBarFlags_Reorderable) && !(tab_bar->Flags & ImGuiTabBarFlags_Reorderable) && tab_bar->Tabs.Size > 1 && tab_bar->PrevFrameVisible != -1)
|
||||
ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerByVisibleOffset);
|
||||
// When toggling ImGuiTabBarFlags_Reorderable flag, ensure tabs are ordered based on their submission order.
|
||||
if ((flags & ImGuiTabBarFlags_Reorderable) != (tab_bar->Flags & ImGuiTabBarFlags_Reorderable) && tab_bar->Tabs.Size > 1)
|
||||
ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerByBeginOrder);
|
||||
|
||||
// Flags
|
||||
if ((flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0)
|
||||
@ -6889,6 +6897,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
|
||||
tab_bar->PrevFrameVisible = tab_bar->CurrFrameVisible;
|
||||
tab_bar->CurrFrameVisible = g.FrameCount;
|
||||
tab_bar->FramePadding = g.Style.FramePadding;
|
||||
tab_bar->TabsActiveCount = 0;
|
||||
|
||||
// Set cursor pos in a way which only be used in the off-chance the user erroneously submits item before BeginTabItem(): items will overlap
|
||||
window->DC.CursorPos.x = tab_bar->BarRect.Min.x;
|
||||
@ -6981,23 +6990,9 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
|
||||
// Process order change request (we could probably process it when requested but it's just saner to do it in a single spot).
|
||||
if (tab_bar->ReorderRequestTabId != 0)
|
||||
{
|
||||
if (ImGuiTabItem* tab1 = TabBarFindTabByID(tab_bar, tab_bar->ReorderRequestTabId))
|
||||
{
|
||||
//IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools
|
||||
int tab2_order = tab_bar->GetTabOrder(tab1) + tab_bar->ReorderRequestDir;
|
||||
if (tab2_order >= 0 && tab2_order < tab_bar->Tabs.Size)
|
||||
{
|
||||
ImGuiTabItem* tab2 = &tab_bar->Tabs[tab2_order];
|
||||
ImGuiTabItem item_tmp = *tab1;
|
||||
*tab1 = *tab2;
|
||||
*tab2 = item_tmp;
|
||||
if (tab2->ID == tab_bar->SelectedTabId)
|
||||
scroll_track_selected_tab_id = tab2->ID;
|
||||
tab1 = tab2 = NULL;
|
||||
}
|
||||
if (tab_bar->Flags & ImGuiTabBarFlags_SaveSettings)
|
||||
MarkIniSettingsDirty();
|
||||
}
|
||||
if (TabBarProcessReorder(tab_bar))
|
||||
if (tab_bar->ReorderRequestTabId == tab_bar->SelectedTabId)
|
||||
scroll_track_selected_tab_id = tab_bar->ReorderRequestTabId;
|
||||
tab_bar->ReorderRequestTabId = 0;
|
||||
}
|
||||
|
||||
@ -7071,11 +7066,11 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
|
||||
offset_x += tab->Width + g.Style.ItemInnerSpacing.x;
|
||||
offset_x_ideal += tab->ContentWidth + g.Style.ItemInnerSpacing.x;
|
||||
}
|
||||
tab_bar->OffsetMax = ImMax(offset_x - g.Style.ItemInnerSpacing.x, 0.0f);
|
||||
tab_bar->OffsetMaxIdeal = ImMax(offset_x_ideal - g.Style.ItemInnerSpacing.x, 0.0f);
|
||||
tab_bar->WidthAllTabs = ImMax(offset_x - g.Style.ItemInnerSpacing.x, 0.0f);
|
||||
tab_bar->WidthAllTabsIdeal = ImMax(offset_x_ideal - g.Style.ItemInnerSpacing.x, 0.0f);
|
||||
|
||||
// Horizontal scrolling buttons
|
||||
const bool scrolling_buttons = (tab_bar->OffsetMax > tab_bar->BarRect.GetWidth() && tab_bar->Tabs.Size > 1) && !(tab_bar->Flags & ImGuiTabBarFlags_NoTabListScrollingButtons) && (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll);
|
||||
const bool scrolling_buttons = (tab_bar->WidthAllTabs > tab_bar->BarRect.GetWidth() && tab_bar->Tabs.Size > 1) && !(tab_bar->Flags & ImGuiTabBarFlags_NoTabListScrollingButtons) && (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll);
|
||||
if (scrolling_buttons)
|
||||
if (ImGuiTabItem* tab_to_select = TabBarScrollingButtons(tab_bar)) // NB: Will alter BarRect.Max.x!
|
||||
scroll_track_selected_tab_id = tab_bar->SelectedTabId = tab_to_select->ID;
|
||||
@ -7121,7 +7116,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
|
||||
// Actual layout in host window (we don't do it in BeginTabBar() so as not to waste an extra frame)
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
window->DC.CursorPos = tab_bar->BarRect.Min;
|
||||
ItemSize(ImVec2(tab_bar->OffsetMaxIdeal, tab_bar->BarRect.GetHeight()), tab_bar->FramePadding.y);
|
||||
ItemSize(ImVec2(tab_bar->WidthAllTabsIdeal, tab_bar->BarRect.GetHeight()), tab_bar->FramePadding.y);
|
||||
}
|
||||
|
||||
// Dockables uses Name/ID in the global namespace. Non-dockable items use the ID stack.
|
||||
@ -7216,7 +7211,7 @@ void ImGui::TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
|
||||
|
||||
static float ImGui::TabBarScrollClamp(ImGuiTabBar* tab_bar, float scrolling)
|
||||
{
|
||||
scrolling = ImMin(scrolling, tab_bar->OffsetMax - tab_bar->BarRect.GetWidth());
|
||||
scrolling = ImMin(scrolling, tab_bar->WidthAllTabs - tab_bar->BarRect.GetWidth());
|
||||
return ImMax(scrolling, 0.0f);
|
||||
}
|
||||
|
||||
@ -7240,7 +7235,7 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui::TabBarQueueChangeTabOrder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int dir)
|
||||
void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int dir)
|
||||
{
|
||||
IM_ASSERT(dir == -1 || dir == +1);
|
||||
IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
|
||||
@ -7248,6 +7243,28 @@ void ImGui::TabBarQueueChangeTabOrder(ImGuiTabBar* tab_bar, const ImGuiTabItem*
|
||||
tab_bar->ReorderRequestDir = (ImS8)dir;
|
||||
}
|
||||
|
||||
bool ImGui::TabBarProcessReorder(ImGuiTabBar* tab_bar)
|
||||
{
|
||||
ImGuiTabItem* tab1 = TabBarFindTabByID(tab_bar, tab_bar->ReorderRequestTabId);
|
||||
if (!tab1)
|
||||
return false;
|
||||
|
||||
//IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools
|
||||
int tab2_order = tab_bar->GetTabOrder(tab1) + tab_bar->ReorderRequestDir;
|
||||
if (tab2_order < 0 || tab2_order >= tab_bar->Tabs.Size)
|
||||
return false;
|
||||
|
||||
ImGuiTabItem* tab2 = &tab_bar->Tabs[tab2_order];
|
||||
ImGuiTabItem item_tmp = *tab1;
|
||||
*tab1 = *tab2;
|
||||
*tab2 = item_tmp;
|
||||
tab1 = tab2 = NULL;
|
||||
|
||||
if (tab_bar->Flags & ImGuiTabBarFlags_SaveSettings)
|
||||
MarkIniSettingsDirty();
|
||||
return true;
|
||||
}
|
||||
|
||||
static ImGuiTabItem* ImGui::TabBarScrollingButtons(ImGuiTabBar* tab_bar)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@ -7359,7 +7376,7 @@ bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags f
|
||||
ImGuiTabBar* tab_bar = g.CurrentTabBar;
|
||||
if (tab_bar == NULL)
|
||||
{
|
||||
IM_ASSERT_USER_ERROR(tab_bar, "BeginTabItem() Needs to be called between BeginTabBar() and EndTabBar()!");
|
||||
IM_ASSERT_USER_ERROR(tab_bar, "Needs to be called between BeginTabBar() and EndTabBar()!");
|
||||
return false;
|
||||
}
|
||||
bool ret = TabItemEx(tab_bar, label, p_open, flags, NULL);
|
||||
@ -7381,7 +7398,7 @@ void ImGui::EndTabItem()
|
||||
ImGuiTabBar* tab_bar = g.CurrentTabBar;
|
||||
if (tab_bar == NULL)
|
||||
{
|
||||
IM_ASSERT(tab_bar != NULL && "Needs to be called between BeginTabBar() and EndTabBar()!");
|
||||
IM_ASSERT_USER_ERROR(tab_bar != NULL, "Needs to be called between BeginTabBar() and EndTabBar()!");
|
||||
return;
|
||||
}
|
||||
IM_ASSERT(tab_bar->LastTabItemIdx >= 0);
|
||||
@ -7437,6 +7454,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
||||
}
|
||||
tab_bar->LastTabItemIdx = (short)tab_bar->Tabs.index_from_ptr(tab);
|
||||
tab->ContentWidth = size.x;
|
||||
tab->BeginOrder = tab_bar->TabsActiveCount++;
|
||||
|
||||
const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount);
|
||||
const bool tab_bar_focused = (tab_bar->Flags & ImGuiTabBarFlags_IsFocused) != 0;
|
||||
@ -7561,13 +7579,13 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
||||
{
|
||||
drag_distance_from_edge_x = bb.Min.x - g.IO.MousePos.x;
|
||||
if (tab_bar->Flags & ImGuiTabBarFlags_Reorderable)
|
||||
TabBarQueueChangeTabOrder(tab_bar, tab, -1);
|
||||
TabBarQueueReorder(tab_bar, tab, -1);
|
||||
}
|
||||
else if (g.IO.MouseDelta.x > 0.0f && g.IO.MousePos.x > bb.Max.x)
|
||||
{
|
||||
drag_distance_from_edge_x = g.IO.MousePos.x - bb.Max.x;
|
||||
if (tab_bar->Flags & ImGuiTabBarFlags_Reorderable)
|
||||
TabBarQueueChangeTabOrder(tab_bar, tab, +1);
|
||||
TabBarQueueReorder(tab_bar, tab, +1);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user