imgui update to v1.91.7

This commit is contained in:
Arnaud Jamin
2025-01-14 23:38:40 -05:00
parent 5ee9a4ae13
commit e118785e1e
8 changed files with 760 additions and 556 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2014-2024 Omar Cornut Copyright (c) 2014-2025 Omar Cornut
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
File diff suppressed because it is too large Load Diff
+18 -11
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.91.6 // dear imgui, v1.91.7
// (headers) // (headers)
// Help: // Help:
@@ -28,8 +28,8 @@
// Library Version // Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.91.6" #define IMGUI_VERSION "1.91.7"
#define IMGUI_VERSION_NUM 19160 #define IMGUI_VERSION_NUM 19170
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch #define IMGUI_HAS_VIEWPORT // Viewport WIP branch
#define IMGUI_HAS_DOCK // Docking WIP branch #define IMGUI_HAS_DOCK // Docking WIP branch
@@ -141,6 +141,7 @@ Index of this file:
#elif defined(__GNUC__) #elif defined(__GNUC__)
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating-point with '==' or '!=' is unsafe
#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead #pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
#endif #endif
@@ -700,6 +701,7 @@ namespace ImGui
// Widgets: List Boxes // Widgets: List Boxes
// - This is essentially a thin wrapper to using BeginChild/EndChild with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label. // - This is essentially a thin wrapper to using BeginChild/EndChild with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label.
// - If you don't need a label you can probably simply use BeginChild() with the ImGuiChildFlags_FrameStyle flag for the same result.
// - You can submit contents and manage your selection state however you want it, by creating e.g. Selectable() or any other items. // - You can submit contents and manage your selection state however you want it, by creating e.g. Selectable() or any other items.
// - The simplified/old ListBox() api are helpers over BeginListBox()/EndListBox() which are kept available for convenience purpose. This is analoguous to how Combos are created. // - The simplified/old ListBox() api are helpers over BeginListBox()/EndListBox() which are kept available for convenience purpose. This is analoguous to how Combos are created.
// - Choose frame width: size.x > 0.0f: custom / size.x < 0.0f or -FLT_MIN: right-align / size.x = 0.0f (default): use current ItemWidth // - Choose frame width: size.x > 0.0f: custom / size.x < 0.0f or -FLT_MIN: right-align / size.x = 0.0f (default): use current ItemWidth
@@ -1136,8 +1138,8 @@ enum ImGuiWindowFlags_
// Obsolete names // Obsolete names
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiWindowFlags_NavFlattened = 1 << 29, // Obsoleted in 1.90.9: Use ImGuiChildFlags_NavFlattened in BeginChild() call.
ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 30, // Obsoleted in 1.90.0: Use ImGuiChildFlags_AlwaysUseWindowPadding in BeginChild() call. ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 30, // Obsoleted in 1.90.0: Use ImGuiChildFlags_AlwaysUseWindowPadding in BeginChild() call.
ImGuiWindowFlags_NavFlattened = 1 << 31, // Obsoleted in 1.90.9: Use ImGuiChildFlags_NavFlattened in BeginChild() call.
#endif #endif
}; };
@@ -1219,7 +1221,7 @@ enum ImGuiInputTextFlags_
ImGuiInputTextFlags_CallbackAlways = 1 << 20, // Callback on each iteration. User code may query cursor position, modify text buffer. ImGuiInputTextFlags_CallbackAlways = 1 << 20, // Callback on each iteration. User code may query cursor position, modify text buffer.
ImGuiInputTextFlags_CallbackCharFilter = 1 << 21, // Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard. ImGuiInputTextFlags_CallbackCharFilter = 1 << 21, // Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard.
ImGuiInputTextFlags_CallbackResize = 1 << 22, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this) ImGuiInputTextFlags_CallbackResize = 1 << 22, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this)
ImGuiInputTextFlags_CallbackEdit = 1 << 23, // Callback on any edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active) ImGuiInputTextFlags_CallbackEdit = 1 << 23, // Callback on any edit. Note that InputText() already returns true on edit + you can always use IsItemEdited(). The callback is useful to manipulate the underlying buffer while focus is active.
// Obsolete names // Obsolete names
//ImGuiInputTextFlags_AlwaysInsertMode = ImGuiInputTextFlags_AlwaysOverwrite // [renamed in 1.82] name was not matching behavior //ImGuiInputTextFlags_AlwaysInsertMode = ImGuiInputTextFlags_AlwaysOverwrite // [renamed in 1.82] name was not matching behavior
@@ -1242,14 +1244,16 @@ enum ImGuiTreeNodeFlags_
ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding() before the node. ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding() before the node.
ImGuiTreeNodeFlags_SpanAvailWidth = 1 << 11, // Extend hit box to the right-most edge, even if not framed. This is not the default in order to allow adding other items on the same line without using AllowOverlap mode. ImGuiTreeNodeFlags_SpanAvailWidth = 1 << 11, // Extend hit box to the right-most edge, even if not framed. This is not the default in order to allow adding other items on the same line without using AllowOverlap mode.
ImGuiTreeNodeFlags_SpanFullWidth = 1 << 12, // Extend hit box to the left-most and right-most edges (cover the indent area). ImGuiTreeNodeFlags_SpanFullWidth = 1 << 12, // Extend hit box to the left-most and right-most edges (cover the indent area).
ImGuiTreeNodeFlags_SpanTextWidth = 1 << 13, // Narrow hit box + narrow hovering highlight, will only cover the label text. ImGuiTreeNodeFlags_SpanLabelWidth = 1 << 13, // Narrow hit box + narrow hovering highlight, will only cover the label text.
ImGuiTreeNodeFlags_SpanAllColumns = 1 << 14, // Frame will span all columns of its container table (text will still fit in current column) ImGuiTreeNodeFlags_SpanAllColumns = 1 << 14, // Frame will span all columns of its container table (label will still fit in current column)
ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 15, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop) ImGuiTreeNodeFlags_LabelSpanAllColumns = 1 << 15, // Label will span all columns of its container table
//ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 16, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 16, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible
ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 17, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop)
ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog, ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog,
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiTreeNodeFlags_AllowItemOverlap = ImGuiTreeNodeFlags_AllowOverlap, // Renamed in 1.89.7 ImGuiTreeNodeFlags_AllowItemOverlap = ImGuiTreeNodeFlags_AllowOverlap, // Renamed in 1.89.7
ImGuiTreeNodeFlags_SpanTextWidth = ImGuiTreeNodeFlags_SpanLabelWidth,// Renamed in 1.90.7
#endif #endif
}; };
@@ -1457,6 +1461,7 @@ enum ImGuiDataType_
ImGuiDataType_Float, // float ImGuiDataType_Float, // float
ImGuiDataType_Double, // double ImGuiDataType_Double, // double
ImGuiDataType_Bool, // bool (provided for user convenience, not supported by scalar widgets) ImGuiDataType_Bool, // bool (provided for user convenience, not supported by scalar widgets)
ImGuiDataType_String, // char* (provided for user convenience, not supported by scalar widgets)
ImGuiDataType_COUNT ImGuiDataType_COUNT
}; };
@@ -1864,6 +1869,7 @@ enum ImGuiSliderFlags_
ImGuiSliderFlags_WrapAround = 1 << 8, // Enable wrapping around from max to min and from min to max. Only supported by DragXXX() functions for now. ImGuiSliderFlags_WrapAround = 1 << 8, // Enable wrapping around from max to min and from min to max. Only supported by DragXXX() functions for now.
ImGuiSliderFlags_ClampOnInput = 1 << 9, // Clamp value to min/max bounds when input manually with CTRL+Click. By default CTRL+Click allows going out of bounds. ImGuiSliderFlags_ClampOnInput = 1 << 9, // Clamp value to min/max bounds when input manually with CTRL+Click. By default CTRL+Click allows going out of bounds.
ImGuiSliderFlags_ClampZeroRange = 1 << 10, // Clamp even if min==max==0.0f. Otherwise due to legacy reason DragXXX functions don't clamp with those values. When your clamping limits are dynamic you almost always want to use it. ImGuiSliderFlags_ClampZeroRange = 1 << 10, // Clamp even if min==max==0.0f. Otherwise due to legacy reason DragXXX functions don't clamp with those values. When your clamping limits are dynamic you almost always want to use it.
ImGuiSliderFlags_NoSpeedTweaks = 1 << 11, // Disable keyboard modifiers altering tweak speed. Useful if you want to alter tweak speed yourself based on your own logic.
ImGuiSliderFlags_AlwaysClamp = ImGuiSliderFlags_ClampOnInput | ImGuiSliderFlags_ClampZeroRange, ImGuiSliderFlags_AlwaysClamp = ImGuiSliderFlags_ClampOnInput | ImGuiSliderFlags_ClampZeroRange,
ImGuiSliderFlags_InvalidMask_ = 0x7000000F, // [Internal] We treat using those bits as being potentially a 'float power' argument from the previous API that has got miscast to this enum, and will trigger an assert if needed. ImGuiSliderFlags_InvalidMask_ = 0x7000000F, // [Internal] We treat using those bits as being potentially a 'float power' argument from the previous API that has got miscast to this enum, and will trigger an assert if needed.
}; };
@@ -2531,7 +2537,7 @@ struct ImGuiIO
// Shared state of InputText(), passed as an argument to your callback when a ImGuiInputTextFlags_Callback* flag is used. // Shared state of InputText(), passed as an argument to your callback when a ImGuiInputTextFlags_Callback* flag is used.
// The callback function should return 0 by default. // The callback function should return 0 by default.
// Callbacks (follow a flag name and see comments in ImGuiInputTextFlags_ declarations for more details) // Callbacks (follow a flag name and see comments in ImGuiInputTextFlags_ declarations for more details)
// - ImGuiInputTextFlags_CallbackEdit: Callback on buffer edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active) // - ImGuiInputTextFlags_CallbackEdit: Callback on buffer edit. Note that InputText() already returns true on edit + you can always use IsItemEdited(). The callback is useful to manipulate the underlying buffer while focus is active.
// - ImGuiInputTextFlags_CallbackAlways: Callback on each iteration // - ImGuiInputTextFlags_CallbackAlways: Callback on each iteration
// - ImGuiInputTextFlags_CallbackCompletion: Callback on pressing TAB // - ImGuiInputTextFlags_CallbackCompletion: Callback on pressing TAB
// - ImGuiInputTextFlags_CallbackHistory: Callback on pressing Up/Down arrows // - ImGuiInputTextFlags_CallbackHistory: Callback on pressing Up/Down arrows
@@ -2806,6 +2812,7 @@ struct ImGuiListClipper
// - It is important that we are keeping those disabled by default so they don't leak in user space. // - It is important that we are keeping those disabled by default so they don't leak in user space.
// - This is in order to allow user enabling implicit cast operators between ImVec2/ImVec4 and their own types (using IM_VEC2_CLASS_EXTRA in imconfig.h) // - This is in order to allow user enabling implicit cast operators between ImVec2/ImVec4 and their own types (using IM_VEC2_CLASS_EXTRA in imconfig.h)
// - Add '#define IMGUI_DEFINE_MATH_OPERATORS' before including this file (or in imconfig.h) to access courtesy maths operators for ImVec2 and ImVec4. // - Add '#define IMGUI_DEFINE_MATH_OPERATORS' before including this file (or in imconfig.h) to access courtesy maths operators for ImVec2 and ImVec4.
// - We intentionally provide ImVec2*float but not float*ImVec2: this is rare enough and we want to reduce the surface for possible user mistake.
#ifdef IMGUI_DEFINE_MATH_OPERATORS #ifdef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED #define IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED
IM_MSVC_RUNTIME_CHECKS_OFF IM_MSVC_RUNTIME_CHECKS_OFF
@@ -3007,7 +3014,7 @@ struct ImGuiSelectionBasicStorage
IMGUI_API void Clear(); // Clear selection IMGUI_API void Clear(); // Clear selection
IMGUI_API void Swap(ImGuiSelectionBasicStorage& r); // Swap two selections IMGUI_API void Swap(ImGuiSelectionBasicStorage& r); // Swap two selections
IMGUI_API void SetItemSelected(ImGuiID id, bool selected); // Add/remove an item from selection (generally done by ApplyRequests() function) IMGUI_API void SetItemSelected(ImGuiID id, bool selected); // Add/remove an item from selection (generally done by ApplyRequests() function)
IMGUI_API bool GetNextSelectedItem(void** opaque_it, ImGuiID* out_id); // Iterate selection with 'void* it = NULL; ImGuiId id; while (selection.GetNextSelectedItem(&it, &id)) { ... }' IMGUI_API bool GetNextSelectedItem(void** opaque_it, ImGuiID* out_id); // Iterate selection with 'void* it = NULL; ImGuiID id; while (selection.GetNextSelectedItem(&it, &id)) { ... }'
inline ImGuiID GetStorageIdFromIndex(int idx) { return AdapterIndexToStorageId(this, idx); } // Convert index to item id based on provided adapter. inline ImGuiID GetStorageIdFromIndex(int idx) { return AdapterIndexToStorageId(this, idx); } // Convert index to item id based on provided adapter.
}; };
@@ -3359,7 +3366,7 @@ struct ImFontConfig
unsigned int FontBuilderFlags; // 0 // Settings for custom font builder. THIS IS BUILDER IMPLEMENTATION DEPENDENT. Leave as zero if unsure. unsigned int FontBuilderFlags; // 0 // Settings for custom font builder. THIS IS BUILDER IMPLEMENTATION DEPENDENT. Leave as zero if unsure.
float RasterizerMultiply; // 1.0f // Linearly brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. This is a silly thing we may remove in the future. float RasterizerMultiply; // 1.0f // Linearly brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. This is a silly thing we may remove in the future.
float RasterizerDensity; // 1.0f // DPI scale for rasterization, not altering other font metrics: make it easy to swap between e.g. a 100% and a 400% fonts for a zooming display. IMPORTANT: If you increase this it is expected that you increase font scale accordingly, otherwise quality may look lowered. float RasterizerDensity; // 1.0f // DPI scale for rasterization, not altering other font metrics: make it easy to swap between e.g. a 100% and a 400% fonts for a zooming display. IMPORTANT: If you increase this it is expected that you increase font scale accordingly, otherwise quality may look lowered.
ImWchar EllipsisChar; // -1 // Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used. ImWchar EllipsisChar; // 0 // Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used.
// [Internal] // [Internal]
char Name[40]; // Name (strictly to ease debugging) char Name[40]; // Name (strictly to ease debugging)
+57 -22
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.91.6 // dear imgui, v1.91.7
// (demo code) // (demo code)
// Help: // Help:
@@ -147,11 +147,15 @@ Index of this file:
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access
#elif defined(__GNUC__) #elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating-point with '==' or '!=' is unsafe
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size
#pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'int'/'void*', but argument X has type 'unsigned int'/'ImGuiWindow*'
#pragma GCC diagnostic ignored "-Wformat-security" // warning: format string is not a string literal (potentially insecure) #pragma GCC diagnostic ignored "-Wformat-security" // warning: format string is not a string literal (potentially insecure)
#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value
#pragma GCC diagnostic ignored "-Wmisleading-indentation" // [__GNUC__ >= 6] warning: this 'if' clause does not guard this statement // GCC 6.0+ only. See #883 on GitHub. #pragma GCC diagnostic ignored "-Wmisleading-indentation" // [__GNUC__ >= 6] warning: this 'if' clause does not guard this statement // GCC 6.0+ only. See #883 on GitHub.
#pragma GCC diagnostic ignored "-Wstrict-overflow" // warning: assuming signed overflow does not occur when simplifying division / ..when changing X +- C1 cmp C2 to X cmp C2 -+ C1
#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers
#endif #endif
// Play it nice with Windows users (Update: May 2018, Notepad now supports Unix-style carriage returns!) // Play it nice with Windows users (Update: May 2018, Notepad now supports Unix-style carriage returns!)
@@ -303,6 +307,7 @@ struct ExampleMemberInfo
// Metadata description of ExampleTreeNode struct. // Metadata description of ExampleTreeNode struct.
static const ExampleMemberInfo ExampleTreeNodeMemberInfos[] static const ExampleMemberInfo ExampleTreeNodeMemberInfos[]
{ {
{ "MyName", ImGuiDataType_String, 1, offsetof(ExampleTreeNode, Name) },
{ "MyBool", ImGuiDataType_Bool, 1, offsetof(ExampleTreeNode, DataMyBool) }, { "MyBool", ImGuiDataType_Bool, 1, offsetof(ExampleTreeNode, DataMyBool) },
{ "MyInt", ImGuiDataType_S32, 1, offsetof(ExampleTreeNode, DataMyInt) }, { "MyInt", ImGuiDataType_S32, 1, offsetof(ExampleTreeNode, DataMyInt) },
{ "MyVec2", ImGuiDataType_Float, 2, offsetof(ExampleTreeNode, DataMyVec2) }, { "MyVec2", ImGuiDataType_Float, 2, offsetof(ExampleTreeNode, DataMyVec2) },
@@ -799,18 +804,25 @@ static void ShowDemoWindowMenuBar(ImGuiDemoWindowData* demo_data)
const bool has_debug_tools = false; const bool has_debug_tools = false;
#endif #endif
ImGui::MenuItem("Metrics/Debugger", NULL, &demo_data->ShowMetrics, has_debug_tools); ImGui::MenuItem("Metrics/Debugger", NULL, &demo_data->ShowMetrics, has_debug_tools);
if (ImGui::BeginMenu("Debug Options"))
{
ImGui::BeginDisabled(!has_debug_tools);
ImGui::Checkbox("Highlight ID Conflicts", &io.ConfigDebugHighlightIdConflicts);
ImGui::EndDisabled();
ImGui::Checkbox("Assert on error recovery", &io.ConfigErrorRecoveryEnableAssert);
ImGui::TextDisabled("(see Demo->Configuration for details & more)");
ImGui::EndMenu();
}
ImGui::MenuItem("Debug Log", NULL, &demo_data->ShowDebugLog, has_debug_tools); ImGui::MenuItem("Debug Log", NULL, &demo_data->ShowDebugLog, has_debug_tools);
ImGui::MenuItem("ID Stack Tool", NULL, &demo_data->ShowIDStackTool, has_debug_tools); ImGui::MenuItem("ID Stack Tool", NULL, &demo_data->ShowIDStackTool, has_debug_tools);
bool is_debugger_present = io.ConfigDebugIsDebuggerPresent; bool is_debugger_present = io.ConfigDebugIsDebuggerPresent;
if (ImGui::MenuItem("Item Picker", NULL, false, has_debug_tools && is_debugger_present)) if (ImGui::MenuItem("Item Picker", NULL, false, has_debug_tools))// && is_debugger_present))
ImGui::DebugStartItemPicker(); ImGui::DebugStartItemPicker();
if (!is_debugger_present) if (!is_debugger_present)
ImGui::SetItemTooltip("Requires io.ConfigDebugIsDebuggerPresent=true to be set.\n\nWe otherwise disable the menu option to avoid casual users crashing the application.\n\nYou can however always access the Item Picker in Metrics->Tools."); ImGui::SetItemTooltip("Requires io.ConfigDebugIsDebuggerPresent=true to be set.\n\nWe otherwise disable some extra features to avoid casual users crashing the application.");
ImGui::MenuItem("Style Editor", NULL, &demo_data->ShowStyleEditor); ImGui::MenuItem("Style Editor", NULL, &demo_data->ShowStyleEditor);
ImGui::MenuItem("About Dear ImGui", NULL, &demo_data->ShowAbout); ImGui::MenuItem("About Dear ImGui", NULL, &demo_data->ShowAbout);
ImGui::SeparatorText("Debug Options");
ImGui::MenuItem("Highlight ID Conflicts", NULL, &io.ConfigDebugHighlightIdConflicts, has_debug_tools);
ImGui::EndMenu(); ImGui::EndMenu();
} }
ImGui::EndMenuBar(); ImGui::EndMenuBar();
@@ -1170,7 +1182,7 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data)
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", &base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", &base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", &base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); ImGui::SameLine(); HelpMarker("Extend hit area to all available width instead of allowing more items to be laid out after the node."); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", &base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); ImGui::SameLine(); HelpMarker("Extend hit area to all available width instead of allowing more items to be laid out after the node.");
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &base_flags, ImGuiTreeNodeFlags_SpanFullWidth); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &base_flags, ImGuiTreeNodeFlags_SpanFullWidth);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanTextWidth", &base_flags, ImGuiTreeNodeFlags_SpanTextWidth); ImGui::SameLine(); HelpMarker("Reduce hit area to the text label and a bit of margin."); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanLabelWidth", &base_flags, ImGuiTreeNodeFlags_SpanLabelWidth); ImGui::SameLine(); HelpMarker("Reduce hit area to the text label and a bit of margin.");
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &base_flags, ImGuiTreeNodeFlags_SpanAllColumns); ImGui::SameLine(); HelpMarker("For use in Tables only."); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &base_flags, ImGuiTreeNodeFlags_SpanAllColumns); ImGui::SameLine(); HelpMarker("For use in Tables only.");
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_AllowOverlap", &base_flags, ImGuiTreeNodeFlags_AllowOverlap); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_AllowOverlap", &base_flags, ImGuiTreeNodeFlags_AllowOverlap);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_Framed", &base_flags, ImGuiTreeNodeFlags_Framed); ImGui::SameLine(); HelpMarker("Draw frame with background (e.g. for CollapsingHeader)"); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_Framed", &base_flags, ImGuiTreeNodeFlags_Framed); ImGui::SameLine(); HelpMarker("Draw frame with background (e.g. for CollapsingHeader)");
@@ -1207,9 +1219,9 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data)
ImGui::Text("This is a drag and drop source"); ImGui::Text("This is a drag and drop source");
ImGui::EndDragDropSource(); ImGui::EndDragDropSource();
} }
if (i == 2 && (base_flags & ImGuiTreeNodeFlags_SpanTextWidth)) if (i == 2 && (base_flags & ImGuiTreeNodeFlags_SpanLabelWidth))
{ {
// Item 2 has an additional inline button to help demonstrate SpanTextWidth. // Item 2 has an additional inline button to help demonstrate SpanLabelWidth.
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::SmallButton("button")) {} if (ImGui::SmallButton("button")) {}
} }
@@ -2370,6 +2382,8 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data)
ImGui::SameLine(); HelpMarker("Disable rounding underlying value to match precision of the format string (e.g. %.3f values are rounded to those 3 digits)."); ImGui::SameLine(); HelpMarker("Disable rounding underlying value to match precision of the format string (e.g. %.3f values are rounded to those 3 digits).");
ImGui::CheckboxFlags("ImGuiSliderFlags_NoInput", &flags, ImGuiSliderFlags_NoInput); ImGui::CheckboxFlags("ImGuiSliderFlags_NoInput", &flags, ImGuiSliderFlags_NoInput);
ImGui::SameLine(); HelpMarker("Disable CTRL+Click or Enter key allowing to input text directly into the widget."); ImGui::SameLine(); HelpMarker("Disable CTRL+Click or Enter key allowing to input text directly into the widget.");
ImGui::CheckboxFlags("ImGuiSliderFlags_NoSpeedTweaks", &flags, ImGuiSliderFlags_NoSpeedTweaks);
ImGui::SameLine(); HelpMarker("Disable keyboard modifiers altering tweak speed. Useful if you want to alter tweak speed yourself based on your own logic.");
ImGui::CheckboxFlags("ImGuiSliderFlags_WrapAround", &flags, ImGuiSliderFlags_WrapAround); ImGui::CheckboxFlags("ImGuiSliderFlags_WrapAround", &flags, ImGuiSliderFlags_WrapAround);
ImGui::SameLine(); HelpMarker("Enable wrapping around from max to min and from min to max (only supported by DragXXX() functions)"); ImGui::SameLine(); HelpMarker("Enable wrapping around from max to min and from min to max (only supported by DragXXX() functions)");
@@ -6418,15 +6432,17 @@ static void ShowDemoWindowTables()
IMGUI_DEMO_MARKER("Tables/Tree view"); IMGUI_DEMO_MARKER("Tables/Tree view");
if (ImGui::TreeNode("Tree view")) if (ImGui::TreeNode("Tree view"))
{ {
static ImGuiTableFlags flags = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody; static ImGuiTableFlags table_flags = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
static ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAllColumns; static ImGuiTreeNodeFlags tree_node_flags_base = ImGuiTreeNodeFlags_SpanAllColumns;
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &tree_node_flags, ImGuiTreeNodeFlags_SpanFullWidth); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &tree_node_flags_base, ImGuiTreeNodeFlags_SpanFullWidth);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanTextWidth", &tree_node_flags, ImGuiTreeNodeFlags_SpanTextWidth); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanLabelWidth", &tree_node_flags_base, ImGuiTreeNodeFlags_SpanLabelWidth);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &tree_node_flags, ImGuiTreeNodeFlags_SpanAllColumns); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &tree_node_flags_base, ImGuiTreeNodeFlags_SpanAllColumns);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_LabelSpanAllColumns", &tree_node_flags_base, ImGuiTreeNodeFlags_LabelSpanAllColumns);
ImGui::SameLine(); HelpMarker("Useful if you know that you aren't displaying contents in other columns");
HelpMarker("See \"Columns flags\" section to configure how indentation is applied to individual columns."); HelpMarker("See \"Columns flags\" section to configure how indentation is applied to individual columns.");
if (ImGui::BeginTable("3ways", 3, flags)) if (ImGui::BeginTable("3ways", 3, table_flags))
{ {
// The first column will use the default _WidthStretch when ScrollX is Off and _WidthFixed when ScrollX is On // The first column will use the default _WidthStretch when ScrollX is Off and _WidthFixed when ScrollX is On
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_NoHide); ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_NoHide);
@@ -6447,13 +6463,21 @@ static void ShowDemoWindowTables()
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
const bool is_folder = (node->ChildCount > 0); const bool is_folder = (node->ChildCount > 0);
ImGuiTreeNodeFlags node_flags = tree_node_flags_base;
if (node != &all_nodes[0])
node_flags &= ~ImGuiTreeNodeFlags_LabelSpanAllColumns; // Only demonstrate this on the root node.
if (is_folder) if (is_folder)
{ {
bool open = ImGui::TreeNodeEx(node->Name, tree_node_flags); bool open = ImGui::TreeNodeEx(node->Name, node_flags);
ImGui::TableNextColumn(); if ((node_flags & ImGuiTreeNodeFlags_LabelSpanAllColumns) == 0)
ImGui::TextDisabled("--"); {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TextUnformatted(node->Type); ImGui::TextDisabled("--");
ImGui::TableNextColumn();
ImGui::TextUnformatted(node->Type);
}
if (open) if (open)
{ {
for (int child_n = 0; child_n < node->ChildCount; child_n++) for (int child_n = 0; child_n < node->ChildCount; child_n++)
@@ -6463,7 +6487,7 @@ static void ShowDemoWindowTables()
} }
else else
{ {
ImGui::TreeNodeEx(node->Name, tree_node_flags | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet | ImGuiTreeNodeFlags_NoTreePushOnOpen); ImGui::TreeNodeEx(node->Name, node_flags | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet | ImGuiTreeNodeFlags_NoTreePushOnOpen);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::Text("%d", node->Size); ImGui::Text("%d", node->Size);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
@@ -6473,7 +6497,7 @@ static void ShowDemoWindowTables()
}; };
static const MyTreeNode nodes[] = static const MyTreeNode nodes[] =
{ {
{ "Root", "Folder", -1, 1, 3 }, // 0 { "Root with Long Name", "Folder", -1, 1, 3 }, // 0
{ "Music", "Folder", -1, 4, 2 }, // 1 { "Music", "Folder", -1, 4, 2 }, // 1
{ "Textures", "Folder", -1, 6, 3 }, // 2 { "Textures", "Folder", -1, 6, 3 }, // 2
{ "desktop.ini", "System file", 1024, -1,-1 }, // 3 { "desktop.ini", "System file", 1024, -1,-1 }, // 3
@@ -7761,7 +7785,8 @@ void ImGui::ShowAboutWindow(bool* p_open)
ImGui::TextLinkOpenURL("Funding", "https://github.com/ocornut/imgui/wiki/Funding"); ImGui::TextLinkOpenURL("Funding", "https://github.com/ocornut/imgui/wiki/Funding");
ImGui::Separator(); ImGui::Separator();
ImGui::Text("By Omar Cornut and all Dear ImGui contributors."); ImGui::Text("(c) 2014-2025 Omar Cornut");
ImGui::Text("Developed by Omar Cornut and all Dear ImGui contributors.");
ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information."); ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information.");
ImGui::Text("If your company uses this, please consider funding the project."); ImGui::Text("If your company uses this, please consider funding the project.");
@@ -7939,6 +7964,8 @@ void ImGui::ShowFontSelector(const char* label)
ImGui::PushID((void*)font); ImGui::PushID((void*)font);
if (ImGui::Selectable(font->GetDebugName(), font == font_current)) if (ImGui::Selectable(font->GetDebugName(), font == font_current))
io.FontDefault = font; io.FontDefault = font;
if (font == font_current)
ImGui::SetItemDefaultFocus();
ImGui::PopID(); ImGui::PopID();
} }
ImGui::EndCombo(); ImGui::EndCombo();
@@ -9049,6 +9076,8 @@ struct ExampleAppPropertyEditor
ImGui::Separator(); ImGui::Separator();
if (ImGui::BeginTable("##properties", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY)) if (ImGui::BeginTable("##properties", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY))
{ {
// Push object ID after we entered the table, so table is shared for all objects
ImGui::PushID((int)node->UID);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 2.0f); // Default twice larger ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 2.0f); // Default twice larger
if (node->HasData) if (node->HasData)
@@ -9087,10 +9116,16 @@ struct ExampleAppPropertyEditor
ImGui::SliderScalarN("##Editor", field_desc.DataType, field_ptr, field_desc.DataCount, &v_min, &v_max); ImGui::SliderScalarN("##Editor", field_desc.DataType, field_ptr, field_desc.DataCount, &v_min, &v_max);
break; break;
} }
case ImGuiDataType_String:
{
ImGui::InputText("##Editor", reinterpret_cast<char*>(field_ptr), 28);
break;
}
} }
ImGui::PopID(); ImGui::PopID();
} }
} }
ImGui::PopID();
ImGui::EndTable(); ImGui::EndTable();
} }
} }
+59 -17
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.91.6 // dear imgui, v1.91.7
// (drawing and font code) // (drawing and font code)
/* /*
@@ -67,13 +67,17 @@ Index of this file:
#pragma clang diagnostic ignored "-Wreserved-identifier" // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter #pragma clang diagnostic ignored "-Wreserved-identifier" // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access
#pragma clang diagnostic ignored "-Wnontrivial-memaccess" // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type #pragma clang diagnostic ignored "-Wnontrivial-memaccess" // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
#pragma clang diagnostic ignored "-Wcast-qual" // warning: cast from 'const xxxx *' to 'xxx *' drops const qualifier
#elif defined(__GNUC__) #elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
#pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating-point with '==' or '!=' is unsafe
#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value
#pragma GCC diagnostic ignored "-Wstack-protector" // warning: stack protector not protecting local variables: variable length buffer #pragma GCC diagnostic ignored "-Wstack-protector" // warning: stack protector not protecting local variables: variable length buffer
#pragma GCC diagnostic ignored "-Wstrict-overflow" // warning: assuming signed overflow does not occur when simplifying division / ..when changing X +- C1 cmp C2 to X cmp C2 -+ C1
#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead #pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers
#endif #endif
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@@ -105,13 +109,12 @@ namespace IMGUI_STB_NAMESPACE
#pragma clang diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used #pragma clang diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
#pragma clang diagnostic ignored "-Wmissing-prototypes" #pragma clang diagnostic ignored "-Wmissing-prototypes"
#pragma clang diagnostic ignored "-Wimplicit-fallthrough" #pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#pragma clang diagnostic ignored "-Wcast-qual" // warning: cast from 'const xxxx *' to 'xxx *' drops const qualifier
#endif #endif
#if defined(__GNUC__) #if defined(__GNUC__)
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wtype-limits" // warning: comparison is always true due to limited range of data type [-Wtype-limits] #pragma GCC diagnostic ignored "-Wtype-limits" // warning: comparison is always true due to limited range of data type [-Wtype-limits]
#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" // warning: this statement may fall through
#endif #endif
#ifndef STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds) #ifndef STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds)
@@ -2383,12 +2386,44 @@ ImFontConfig::ImFontConfig()
GlyphMaxAdvanceX = FLT_MAX; GlyphMaxAdvanceX = FLT_MAX;
RasterizerMultiply = 1.0f; RasterizerMultiply = 1.0f;
RasterizerDensity = 1.0f; RasterizerDensity = 1.0f;
EllipsisChar = (ImWchar)-1; EllipsisChar = 0;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] ImFontAtlas // [SECTION] ImFontAtlas
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// - Default texture data encoded in ASCII
// - ImFontAtlas::ClearInputData()
// - ImFontAtlas::ClearTexData()
// - ImFontAtlas::ClearFonts()
// - ImFontAtlas::Clear()
// - ImFontAtlas::GetTexDataAsAlpha8()
// - ImFontAtlas::GetTexDataAsRGBA32()
// - ImFontAtlas::AddFont()
// - ImFontAtlas::AddFontDefault()
// - ImFontAtlas::AddFontFromFileTTF()
// - ImFontAtlas::AddFontFromMemoryTTF()
// - ImFontAtlas::AddFontFromMemoryCompressedTTF()
// - ImFontAtlas::AddFontFromMemoryCompressedBase85TTF()
// - ImFontAtlas::AddCustomRectRegular()
// - ImFontAtlas::AddCustomRectFontGlyph()
// - ImFontAtlas::CalcCustomRectUV()
// - ImFontAtlas::GetMouseCursorTexData()
// - ImFontAtlas::Build()
// - ImFontAtlasBuildMultiplyCalcLookupTable()
// - ImFontAtlasBuildMultiplyRectAlpha8()
// - ImFontAtlasBuildWithStbTruetype()
// - ImFontAtlasGetBuilderForStbTruetype()
// - ImFontAtlasUpdateConfigDataPointers()
// - ImFontAtlasBuildSetupFont()
// - ImFontAtlasBuildPackCustomRects()
// - ImFontAtlasBuildRender8bppRectFromString()
// - ImFontAtlasBuildRender32bppRectFromString()
// - ImFontAtlasBuildRenderDefaultTexData()
// - ImFontAtlasBuildRenderLinesTexData()
// - ImFontAtlasBuildInit()
// - ImFontAtlasBuildFinish()
//-----------------------------------------------------------------------------
// A work of art lies ahead! (. = white layer, X = black layer, others are blank) // A work of art lies ahead! (. = white layer, X = black layer, others are blank)
// The 2x2 white texels on the top left are the ones we'll use everywhere in Dear ImGui to render filled shapes. // The 2x2 white texels on the top left are the ones we'll use everywhere in Dear ImGui to render filled shapes.
@@ -2570,9 +2605,6 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
// - We may support it better later and remove this rounding. // - We may support it better later and remove this rounding.
new_font_cfg.SizePixels = ImTrunc(new_font_cfg.SizePixels); new_font_cfg.SizePixels = ImTrunc(new_font_cfg.SizePixels);
if (new_font_cfg.DstFont->EllipsisChar == (ImWchar)-1)
new_font_cfg.DstFont->EllipsisChar = font_cfg->EllipsisChar;
// Pointers to ConfigData and BuilderData are otherwise dangling // Pointers to ConfigData and BuilderData are otherwise dangling
ImFontAtlasUpdateConfigDataPointers(this); ImFontAtlasUpdateConfigDataPointers(this);
@@ -3333,6 +3365,16 @@ void ImFontAtlasBuildFinish(ImFontAtlas* atlas)
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// [SECTION] ImFontAtlas: glyph ranges helpers // [SECTION] ImFontAtlas: glyph ranges helpers
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// - GetGlyphRangesDefault()
// - GetGlyphRangesGreek()
// - GetGlyphRangesKorean()
// - GetGlyphRangesChineseFull()
// - GetGlyphRangesChineseSimplifiedCommon()
// - GetGlyphRangesJapanese()
// - GetGlyphRangesCyrillic()
// - GetGlyphRangesThai()
// - GetGlyphRangesVietnamese()
//-----------------------------------------------------------------------------
// Retrieve list of range (2 int per range, values are inclusive) // Retrieve list of range (2 int per range, values are inclusive)
const ImWchar* ImFontAtlas::GetGlyphRangesDefault() const ImWchar* ImFontAtlas::GetGlyphRangesDefault()
@@ -3641,8 +3683,8 @@ ImFont::ImFont()
{ {
FontSize = 0.0f; FontSize = 0.0f;
FallbackAdvanceX = 0.0f; FallbackAdvanceX = 0.0f;
FallbackChar = (ImWchar)-1; FallbackChar = 0;
EllipsisChar = (ImWchar)-1; EllipsisChar = 0;
EllipsisWidth = EllipsisCharStep = 0.0f; EllipsisWidth = EllipsisCharStep = 0.0f;
EllipsisCharCount = 0; EllipsisCharCount = 0;
FallbackGlyph = NULL; FallbackGlyph = NULL;
@@ -3681,7 +3723,7 @@ static ImWchar FindFirstExistingGlyph(ImFont* font, const ImWchar* candidate_cha
for (int n = 0; n < candidate_chars_count; n++) for (int n = 0; n < candidate_chars_count; n++)
if (font->FindGlyphNoFallback(candidate_chars[n]) != NULL) if (font->FindGlyphNoFallback(candidate_chars[n]) != NULL)
return candidate_chars[n]; return candidate_chars[n];
return (ImWchar)-1; return 0;
} }
void ImFont::BuildLookupTable() void ImFont::BuildLookupTable()
@@ -3748,23 +3790,23 @@ void ImFont::BuildLookupTable()
// Setup Ellipsis character. It is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis). // Setup Ellipsis character. It is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis).
// However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character. // However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character.
// FIXME: Note that 0x2026 is rarely included in our font ranges. Because of this we are more likely to use three individual dots. // FIXME: Note that 0x2026 is rarely included in our font ranges. Because of this we are more likely to use three individual dots.
const ImWchar ellipsis_chars[] = { (ImWchar)0x2026, (ImWchar)0x0085 }; const ImWchar ellipsis_chars[] = { ConfigData->EllipsisChar, (ImWchar)0x2026, (ImWchar)0x0085 };
const ImWchar dots_chars[] = { (ImWchar)'.', (ImWchar)0xFF0E }; const ImWchar dots_chars[] = { (ImWchar)'.', (ImWchar)0xFF0E };
if (EllipsisChar == (ImWchar)-1) if (EllipsisChar == 0)
EllipsisChar = FindFirstExistingGlyph(this, ellipsis_chars, IM_ARRAYSIZE(ellipsis_chars)); EllipsisChar = FindFirstExistingGlyph(this, ellipsis_chars, IM_ARRAYSIZE(ellipsis_chars));
const ImWchar dot_char = FindFirstExistingGlyph(this, dots_chars, IM_ARRAYSIZE(dots_chars)); const ImWchar dot_char = FindFirstExistingGlyph(this, dots_chars, IM_ARRAYSIZE(dots_chars));
if (EllipsisChar != (ImWchar)-1) if (EllipsisChar != 0)
{ {
EllipsisCharCount = 1; EllipsisCharCount = 1;
EllipsisWidth = EllipsisCharStep = FindGlyph(EllipsisChar)->X1; EllipsisWidth = EllipsisCharStep = FindGlyph(EllipsisChar)->X1;
} }
else if (dot_char != (ImWchar)-1) else if (dot_char != 0)
{ {
const ImFontGlyph* glyph = FindGlyph(dot_char); const ImFontGlyph* dot_glyph = FindGlyph(dot_char);
EllipsisChar = dot_char; EllipsisChar = dot_char;
EllipsisCharCount = 3; EllipsisCharCount = 3;
EllipsisCharStep = (glyph->X1 - glyph->X0) + 1.0f; EllipsisCharStep = (float)(int)(dot_glyph->X1 - dot_glyph->X0) + 1.0f;
EllipsisWidth = EllipsisCharStep * 3.0f - 1.0f; EllipsisWidth = ImMax(dot_glyph->AdvanceX, dot_glyph->X0 + EllipsisCharStep * 3.0f - 1.0f); // FIXME: Slightly odd for normally mono-space fonts but since this is used for trailing contents.
} }
} }
+25 -15
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.91.6 // dear imgui, v1.91.7
// (internal structures/api) // (internal structures/api)
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility. // You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
@@ -101,6 +101,7 @@ Index of this file:
#elif defined(__GNUC__) #elif defined(__GNUC__)
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating-point with '==' or '!=' is unsafe
#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead #pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
#pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated #pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
#endif #endif
@@ -139,6 +140,7 @@ struct ImGuiContext; // Main Dear ImGui context
struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine
struct ImGuiDataVarInfo; // Variable information (e.g. to access style variables from an enum) struct ImGuiDataVarInfo; // Variable information (e.g. to access style variables from an enum)
struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum
struct ImGuiDeactivatedItemData; // Data for IsItemDeactivated()/IsItemDeactivatedAfterEdit() function.
struct ImGuiDockContext; // Docking system context struct ImGuiDockContext; // Docking system context
struct ImGuiDockRequest; // Docking system dock/undock queued request struct ImGuiDockRequest; // Docking system dock/undock queued request
struct ImGuiDockNode; // Docking system node (hold a list of Windows OR two child dock nodes) struct ImGuiDockNode; // Docking system node (hold a list of Windows OR two child dock nodes)
@@ -471,7 +473,7 @@ static inline double ImRsqrt(double x) { return 1.0 / sqrt(x); }
template<typename T> static inline T ImMin(T lhs, T rhs) { return lhs < rhs ? lhs : rhs; } template<typename T> static inline T ImMin(T lhs, T rhs) { return lhs < rhs ? lhs : rhs; }
template<typename T> static inline T ImMax(T lhs, T rhs) { return lhs >= rhs ? lhs : rhs; } template<typename T> static inline T ImMax(T lhs, T rhs) { return lhs >= rhs ? lhs : rhs; }
template<typename T> static inline T ImClamp(T v, T mn, T mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } template<typename T> static inline T ImClamp(T v, T mn, T mx) { return (v < mn) ? mn : (v > mx) ? mx : v; }
template<typename T> static inline T ImLerp(T a, T b, float t) { return (T)(a + (b - a) * t); } template<typename T> static inline T ImLerp(T a, T b, float t) { return (T)(a + (b - a) * (T)t); }
template<typename T> static inline void ImSwap(T& a, T& b) { T tmp = a; a = b; b = tmp; } template<typename T> static inline void ImSwap(T& a, T& b) { T tmp = a; a = b; b = tmp; }
template<typename T> static inline T ImAddClampOverflow(T a, T b, T mn, T mx) { if (b < 0 && (a < mn - b)) return mn; if (b > 0 && (a > mx - b)) return mx; return a + b; } template<typename T> static inline T ImAddClampOverflow(T a, T b, T mn, T mx) { if (b < 0 && (a < mn - b)) return mn; if (b > 0 && (a > mx - b)) return mx; return a + b; }
template<typename T> static inline T ImSubClampOverflow(T a, T b, T mn, T mx) { if (b > 0 && (a < mn + b)) return mn; if (b < 0 && (a > mx + b)) return mx; return a - b; } template<typename T> static inline T ImSubClampOverflow(T a, T b, T mn, T mx) { if (b > 0 && (a < mn + b)) return mn; if (b < 0 && (a > mx + b)) return mx; return a - b; }
@@ -837,8 +839,7 @@ struct ImGuiDataTypeInfo
// Extend ImGuiDataType_ // Extend ImGuiDataType_
enum ImGuiDataTypePrivate_ enum ImGuiDataTypePrivate_
{ {
ImGuiDataType_String = ImGuiDataType_COUNT + 1, ImGuiDataType_Pointer = ImGuiDataType_COUNT + 1,
ImGuiDataType_Pointer,
ImGuiDataType_ID, ImGuiDataType_ID,
}; };
@@ -924,7 +925,7 @@ enum ImGuiButtonFlagsPrivate_
ImGuiButtonFlags_PressedOnRelease = 1 << 7, // return true on release (default requires click+release) ImGuiButtonFlags_PressedOnRelease = 1 << 7, // return true on release (default requires click+release)
ImGuiButtonFlags_PressedOnDoubleClick = 1 << 8, // return true on double-click (default requires click+release) ImGuiButtonFlags_PressedOnDoubleClick = 1 << 8, // return true on double-click (default requires click+release)
ImGuiButtonFlags_PressedOnDragDropHold = 1 << 9, // return true when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers) ImGuiButtonFlags_PressedOnDragDropHold = 1 << 9, // return true when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers)
//ImGuiButtonFlags_Repeat = 1 << 10, // hold to repeat //ImGuiButtonFlags_Repeat = 1 << 10, // hold to repeat -> use ImGuiItemFlags_ButtonRepeat instead.
ImGuiButtonFlags_FlattenChildren = 1 << 11, // allow interactions even if a child window is overlapping ImGuiButtonFlags_FlattenChildren = 1 << 11, // allow interactions even if a child window is overlapping
ImGuiButtonFlags_AllowOverlap = 1 << 12, // require previous frame HoveredId to either match id or be null before being usable. ImGuiButtonFlags_AllowOverlap = 1 << 12, // require previous frame HoveredId to either match id or be null before being usable.
//ImGuiButtonFlags_DontClosePopups = 1 << 13, // disable automatically closing parent popup on press //ImGuiButtonFlags_DontClosePopups = 1 << 13, // disable automatically closing parent popup on press
@@ -1081,7 +1082,7 @@ struct IMGUI_API ImGuiGroupData
ImVec2 BackupCurrLineSize; ImVec2 BackupCurrLineSize;
float BackupCurrLineTextBaseOffset; float BackupCurrLineTextBaseOffset;
ImGuiID BackupActiveIdIsAlive; ImGuiID BackupActiveIdIsAlive;
bool BackupActiveIdPreviousFrameIsAlive; bool BackupDeactivatedIdIsAlive;
bool BackupHoveredIdIsAlive; bool BackupHoveredIdIsAlive;
bool BackupIsSameLine; bool BackupIsSameLine;
bool EmitItem; bool EmitItem;
@@ -1132,8 +1133,10 @@ struct IMGUI_API ImGuiInputTextState
{ {
ImGuiContext* Ctx; // parent UI context (needs to be set explicitly by parent). ImGuiContext* Ctx; // parent UI context (needs to be set explicitly by parent).
ImStbTexteditState* Stb; // State for stb_textedit.h ImStbTexteditState* Stb; // State for stb_textedit.h
ImGuiInputTextFlags Flags; // copy of InputText() flags. may be used to check if e.g. ImGuiInputTextFlags_Password is set.
ImGuiID ID; // widget id owning the text state ImGuiID ID; // widget id owning the text state
int TextLen; // UTF-8 length of the string in TextA (in bytes) int TextLen; // UTF-8 length of the string in TextA (in bytes)
const char* TextSrc; // == TextA.Data unless read-only, in which case == buf passed to InputText(). Field only set and valid _inside_ the call InputText() call.
ImVector<char> TextA; // main UTF8 buffer. TextA.Size is a buffer size! Should always be >= buf_size passed by user (and of course >= CurLenA + 1). ImVector<char> TextA; // main UTF8 buffer. TextA.Size is a buffer size! Should always be >= buf_size passed by user (and of course >= CurLenA + 1).
ImVector<char> TextToRevertTo; // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered) ImVector<char> TextToRevertTo; // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered)
ImVector<char> CallbackTextBackup; // temporary storage for callback to support automatic reconcile of undo-stack ImVector<char> CallbackTextBackup; // temporary storage for callback to support automatic reconcile of undo-stack
@@ -1143,9 +1146,8 @@ struct IMGUI_API ImGuiInputTextState
bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!) bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!)
bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection
bool Edited; // edited this frame bool Edited; // edited this frame
ImGuiInputTextFlags Flags; // copy of InputText() flags. may be used to check if e.g. ImGuiInputTextFlags_Password is set. bool WantReloadUserBuf; // force a reload of user buf so it may be modified externally. may be automatic in future version.
bool ReloadUserBuf; // force a reload of user buf so it may be modified externally. may be automatic in future version. int ReloadSelectionStart;
int ReloadSelectionStart; // POSITIONS ARE IN IMWCHAR units *NOT* UTF-8 this is why this is not exposed yet.
int ReloadSelectionEnd; int ReloadSelectionEnd;
ImGuiInputTextState(); ImGuiInputTextState();
@@ -1265,11 +1267,11 @@ struct ImGuiNextItemData
struct ImGuiLastItemData struct ImGuiLastItemData
{ {
ImGuiID ID; ImGuiID ID;
ImGuiItemFlags ItemFlags; // See ImGuiItemFlags_ ImGuiItemFlags ItemFlags; // See ImGuiItemFlags_ (called 'InFlags' before v1.91.4).
ImGuiItemStatusFlags StatusFlags; // See ImGuiItemStatusFlags_ ImGuiItemStatusFlags StatusFlags; // See ImGuiItemStatusFlags_
ImRect Rect; // Full rectangle ImRect Rect; // Full rectangle
ImRect NavRect; // Navigation scoring rectangle (not displayed) ImRect NavRect; // Navigation scoring rectangle (not displayed)
// Rarely used fields are not explicitly cleared, only valid when the corresponding ImGuiItemStatusFlags ar set. // Rarely used fields are not explicitly cleared, only valid when the corresponding ImGuiItemStatusFlags are set.
ImRect DisplayRect; // Display rectangle. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasDisplayRect) is set. ImRect DisplayRect; // Display rectangle. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasDisplayRect) is set.
ImRect ClipRect; // Clip rectangle at the time of submitting item. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasClipRect) is set.. ImRect ClipRect; // Clip rectangle at the time of submitting item. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasClipRect) is set..
ImGuiKeyChord Shortcut; // Shortcut at the time of submitting item. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasShortcut) is set.. ImGuiKeyChord Shortcut; // Shortcut at the time of submitting item. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasShortcut) is set..
@@ -1332,6 +1334,15 @@ struct ImGuiPtrOrIndex
ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; } ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; }
}; };
// Data used by IsItemDeactivated()/IsItemDeactivatedAfterEdit() functions
struct ImGuiDeactivatedItemData
{
ImGuiID ID;
int ElapseFrame;
bool HasBeenEditedBefore;
bool IsAlive;
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Popup support // [SECTION] Popup support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -2239,9 +2250,9 @@ struct ImGuiContext
int FrameCountEnded; int FrameCountEnded;
int FrameCountPlatformEnded; int FrameCountPlatformEnded;
int FrameCountRendered; int FrameCountRendered;
ImGuiID WithinEndChildID; // Set within EndChild()
bool WithinFrameScope; // Set by NewFrame(), cleared by EndFrame() bool WithinFrameScope; // Set by NewFrame(), cleared by EndFrame()
bool WithinFrameScopeWithImplicitWindow; // Set by NewFrame(), cleared by EndFrame() when the implicit debug window has been pushed bool WithinFrameScopeWithImplicitWindow; // Set by NewFrame(), cleared by EndFrame() when the implicit debug window has been pushed
bool WithinEndChild; // Set within EndChild()
bool GcCompactAll; // Request full GC bool GcCompactAll; // Request full GC
bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log() bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log()
void* TestEngine; // Test engine user data void* TestEngine; // Test engine user data
@@ -2301,9 +2312,8 @@ struct ImGuiContext
ImGuiWindow* ActiveIdWindow; ImGuiWindow* ActiveIdWindow;
ImGuiInputSource ActiveIdSource; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad ImGuiInputSource ActiveIdSource; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad
ImGuiID ActiveIdPreviousFrame; ImGuiID ActiveIdPreviousFrame;
bool ActiveIdPreviousFrameIsAlive; ImGuiDeactivatedItemData DeactivatedItemData;
bool ActiveIdPreviousFrameHasBeenEditedBefore; ImGuiDataTypeStorage ActiveIdValueOnActivation; // Backup of initial value at the time of activation. ONLY SET BY SPECIFIC WIDGETS: DragXXX and SliderXXX.
ImGuiWindow* ActiveIdPreviousFrameWindow;
ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation. ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation.
float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation. float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation.
+42 -11
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.91.6 // dear imgui, v1.91.7
// (tables and columns code) // (tables and columns code)
/* /*
@@ -232,7 +232,11 @@ Index of this file:
#pragma clang diagnostic ignored "-Wnontrivial-memaccess" // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type #pragma clang diagnostic ignored "-Wnontrivial-memaccess" // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
#elif defined(__GNUC__) #elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating-point with '==' or '!=' is unsafe
#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked
#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
#pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'int'/'void*', but argument X has type 'unsigned int'/'ImGuiWindow*'
#pragma GCC diagnostic ignored "-Wstrict-overflow"
#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead #pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
#endif #endif
@@ -1333,7 +1337,11 @@ void ImGui::EndTable()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiTable* table = g.CurrentTable; ImGuiTable* table = g.CurrentTable;
IM_ASSERT(table != NULL && "Only call EndTable() if BeginTable() returns true!"); if (table == NULL)
{
IM_ASSERT_USER_ERROR(table != NULL, "EndTable() call should only be done while in BeginTable() scope!");
return;
}
// This assert would be very useful to catch a common error... unfortunately it would probably trigger in some // This assert would be very useful to catch a common error... unfortunately it would probably trigger in some
// cases, and for consistency user may sometimes output empty tables (and still benefit from e.g. outer border) // cases, and for consistency user may sometimes output empty tables (and still benefit from e.g. outer border)
@@ -1556,8 +1564,12 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiTable* table = g.CurrentTable; ImGuiTable* table = g.CurrentTable;
IM_ASSERT(table != NULL && "Need to call TableSetupColumn() after BeginTable()!"); if (table == NULL)
IM_ASSERT(table->IsLayoutLocked == false && "Need to call call TableSetupColumn() before first row!"); {
IM_ASSERT_USER_ERROR(table != NULL, "Call should only be done while in BeginTable() scope!");
return;
}
IM_ASSERT(table->IsLayoutLocked == false && "Need to call TableSetupColumn() before first row!");
IM_ASSERT((flags & ImGuiTableColumnFlags_StatusMask_) == 0 && "Illegal to pass StatusMask values to TableSetupColumn()"); IM_ASSERT((flags & ImGuiTableColumnFlags_StatusMask_) == 0 && "Illegal to pass StatusMask values to TableSetupColumn()");
if (table->DeclColumnsCount >= table->ColumnsCount) if (table->DeclColumnsCount >= table->ColumnsCount)
{ {
@@ -1630,7 +1642,11 @@ void ImGui::TableSetupScrollFreeze(int columns, int rows)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiTable* table = g.CurrentTable; ImGuiTable* table = g.CurrentTable;
IM_ASSERT(table != NULL && "Need to call TableSetupColumn() after BeginTable()!"); if (table == NULL)
{
IM_ASSERT_USER_ERROR(table != NULL, "Call should only be done while in BeginTable() scope!");
return;
}
IM_ASSERT(table->IsLayoutLocked == false && "Need to call TableSetupColumn() before first row!"); IM_ASSERT(table->IsLayoutLocked == false && "Need to call TableSetupColumn() before first row!");
IM_ASSERT(columns >= 0 && columns < IMGUI_TABLE_MAX_COLUMNS); IM_ASSERT(columns >= 0 && columns < IMGUI_TABLE_MAX_COLUMNS);
IM_ASSERT(rows >= 0 && rows < 128); // Arbitrary limit IM_ASSERT(rows >= 0 && rows < 128); // Arbitrary limit
@@ -1707,9 +1723,11 @@ void ImGui::TableSetColumnEnabled(int column_n, bool enabled)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiTable* table = g.CurrentTable; ImGuiTable* table = g.CurrentTable;
IM_ASSERT(table != NULL); if (table == NULL)
if (!table) {
IM_ASSERT_USER_ERROR(table != NULL, "Call should only be done while in BeginTable() scope!");
return; return;
}
IM_ASSERT(table->Flags & ImGuiTableFlags_Hideable); // See comments above IM_ASSERT(table->Flags & ImGuiTableFlags_Hideable); // See comments above
if (column_n < 0) if (column_n < 0)
column_n = table->CurrentColumn; column_n = table->CurrentColumn;
@@ -3030,7 +3048,11 @@ void ImGui::TableHeadersRow()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiTable* table = g.CurrentTable; ImGuiTable* table = g.CurrentTable;
IM_ASSERT(table != NULL && "Need to call TableHeadersRow() after BeginTable()!"); if (table == NULL)
{
IM_ASSERT_USER_ERROR(table != NULL, "Call should only be done while in BeginTable() scope!");
return;
}
// Call layout if not already done. This is automatically done by TableNextRow: we do it here _only_ to make // Call layout if not already done. This is automatically done by TableNextRow: we do it here _only_ to make
// it easier to debug-step in TableUpdateLayout(). Your own version of this function doesn't need this. // it easier to debug-step in TableUpdateLayout(). Your own version of this function doesn't need this.
@@ -3075,7 +3097,12 @@ void ImGui::TableHeader(const char* label)
return; return;
ImGuiTable* table = g.CurrentTable; ImGuiTable* table = g.CurrentTable;
IM_ASSERT(table != NULL && "Need to call TableHeader() after BeginTable()!"); if (table == NULL)
{
IM_ASSERT_USER_ERROR(table != NULL, "Call should only be done while in BeginTable() scope!");
return;
}
IM_ASSERT(table->CurrentColumn != -1); IM_ASSERT(table->CurrentColumn != -1);
const int column_n = table->CurrentColumn; const int column_n = table->CurrentColumn;
ImGuiTableColumn* column = &table->Columns[column_n]; ImGuiTableColumn* column = &table->Columns[column_n];
@@ -3250,7 +3277,11 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label
ImGuiTable* table = g.CurrentTable; ImGuiTable* table = g.CurrentTable;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
ImDrawList* draw_list = window->DrawList; ImDrawList* draw_list = window->DrawList;
IM_ASSERT(table != NULL && "Need to call TableHeadersRow() after BeginTable()!"); if (table == NULL)
{
IM_ASSERT_USER_ERROR(table != NULL, "Call should only be done while in BeginTable() scope!");
return;
}
IM_ASSERT(table->CurrentRow == -1 && "Must be first row"); IM_ASSERT(table->CurrentRow == -1 && "Must be first row");
if (max_label_width == 0.0f) if (max_label_width == 0.0f)
@@ -3295,7 +3326,7 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label
const ImVec2 align = g.Style.TableAngledHeadersTextAlign; const ImVec2 align = g.Style.TableAngledHeadersTextAlign;
// Draw background and labels in first pass, then all borders. // Draw background and labels in first pass, then all borders.
float max_x = 0.0f; float max_x = -FLT_MAX;
for (int pass = 0; pass < 2; pass++) for (int pass = 0; pass < 2; pass++)
for (int order_n = 0; order_n < data_count; order_n++) for (int order_n = 0; order_n < data_count; order_n++)
{ {
+146 -117
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.91.6 // dear imgui, v1.91.7
// (widgets code) // (widgets code)
/* /*
@@ -82,9 +82,14 @@ Index of this file:
#pragma clang diagnostic ignored "-Wnontrivial-memaccess" // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type #pragma clang diagnostic ignored "-Wnontrivial-memaccess" // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
#elif defined(__GNUC__) #elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating-point with '==' or '!=' is unsafe
#pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'int'/'void*', but argument X has type 'unsigned int'/'ImGuiWindow*'
#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked
#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
#pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated #pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
#pragma GCC diagnostic ignored "-Wstrict-overflow" // warning: assuming signed overflow does not occur when simplifying division / ..when changing X +- C1 cmp C2 to X cmp C2 -+ C1
#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers
#endif #endif
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@@ -472,7 +477,7 @@ void ImGui::BulletTextV(const char* fmt, va_list args)
// - PressedOnDragDropHold can generally be associated with any flag. // - PressedOnDragDropHold can generally be associated with any flag.
// - PressedOnDoubleClick can be associated by PressedOnClickRelease/PressedOnRelease, in which case the second release event won't be reported. // - PressedOnDoubleClick can be associated by PressedOnClickRelease/PressedOnRelease, in which case the second release event won't be reported.
//------------------------------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------------------------
// The behavior of the return-value changes when ImGuiButtonFlags_Repeat is set: // The behavior of the return-value changes when ImGuiItemFlags_ButtonRepeat is set:
// Repeat+ Repeat+ Repeat+ Repeat+ // Repeat+ Repeat+ Repeat+ Repeat+
// PressedOnClickRelease PressedOnClick PressedOnRelease PressedOnDoubleClick // PressedOnClickRelease PressedOnClick PressedOnRelease PressedOnDoubleClick
//------------------------------------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------------------------------------
@@ -2172,6 +2177,7 @@ static const ImGuiDataTypeInfo GDataTypeInfo[] =
{ sizeof(float), "float", "%.3f","%f" }, // ImGuiDataType_Float (float are promoted to double in va_arg) { sizeof(float), "float", "%.3f","%f" }, // ImGuiDataType_Float (float are promoted to double in va_arg)
{ sizeof(double), "double","%f", "%lf" }, // ImGuiDataType_Double { sizeof(double), "double","%f", "%lf" }, // ImGuiDataType_Double
{ sizeof(bool), "bool", "%d", "%d" }, // ImGuiDataType_Bool { sizeof(bool), "bool", "%d", "%d" }, // ImGuiDataType_Bool
{ 0, "char*","%s", "%s" }, // ImGuiDataType_String
}; };
IM_STATIC_ASSERT(IM_ARRAYSIZE(GDataTypeInfo) == ImGuiDataType_COUNT); IM_STATIC_ASSERT(IM_ARRAYSIZE(GDataTypeInfo) == ImGuiDataType_COUNT);
@@ -2440,9 +2446,9 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid() && IsMouseDragPastThreshold(0, g.IO.MouseDragThreshold * DRAG_MOUSE_THRESHOLD_FACTOR)) if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid() && IsMouseDragPastThreshold(0, g.IO.MouseDragThreshold * DRAG_MOUSE_THRESHOLD_FACTOR))
{ {
adjust_delta = g.IO.MouseDelta[axis]; adjust_delta = g.IO.MouseDelta[axis];
if (g.IO.KeyAlt) if (g.IO.KeyAlt && !(flags & ImGuiSliderFlags_NoSpeedTweaks))
adjust_delta *= 1.0f / 100.0f; adjust_delta *= 1.0f / 100.0f;
if (g.IO.KeyShift) if (g.IO.KeyShift && !(flags & ImGuiSliderFlags_NoSpeedTweaks))
adjust_delta *= 10.0f; adjust_delta *= 10.0f;
} }
else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad) else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
@@ -2450,7 +2456,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0; const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0;
const bool tweak_slow = IsKeyDown((g.NavInputSource == ImGuiInputSource_Gamepad) ? ImGuiKey_NavGamepadTweakSlow : ImGuiKey_NavKeyboardTweakSlow); const bool tweak_slow = IsKeyDown((g.NavInputSource == ImGuiInputSource_Gamepad) ? ImGuiKey_NavGamepadTweakSlow : ImGuiKey_NavKeyboardTweakSlow);
const bool tweak_fast = IsKeyDown((g.NavInputSource == ImGuiInputSource_Gamepad) ? ImGuiKey_NavGamepadTweakFast : ImGuiKey_NavKeyboardTweakFast); const bool tweak_fast = IsKeyDown((g.NavInputSource == ImGuiInputSource_Gamepad) ? ImGuiKey_NavGamepadTweakFast : ImGuiKey_NavKeyboardTweakFast);
const float tweak_factor = tweak_slow ? 1.0f / 10.0f : tweak_fast ? 10.0f : 1.0f; const float tweak_factor = (flags & ImGuiSliderFlags_NoSpeedTweaks) ? 1.0f : tweak_slow ? 1.0f / 10.0f : tweak_fast ? 10.0f : 1.0f;
adjust_delta = GetNavTweakPressedAmount(axis) * tweak_factor; adjust_delta = GetNavTweakPressedAmount(axis) * tweak_factor;
v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision));
} }
@@ -2638,6 +2644,10 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
temp_input_is_active = true; temp_input_is_active = true;
} }
// Store initial value (not used by main lib but available as a convenience but some mods e.g. to revert)
if (make_active)
memcpy(&g.ActiveIdValueOnActivation, p_data, DataTypeGetInfo(data_type)->Size);
if (make_active && !temp_input_is_active) if (make_active && !temp_input_is_active)
{ {
SetActiveID(id, window); SetActiveID(id, window);
@@ -3228,6 +3238,10 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
if ((clicked && g.IO.KeyCtrl) || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput))) if ((clicked && g.IO.KeyCtrl) || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput)))
temp_input_is_active = true; temp_input_is_active = true;
// Store initial value (not used by main lib but available as a convenience but some mods e.g. to revert)
if (make_active)
memcpy(&g.ActiveIdValueOnActivation, p_data, DataTypeGetInfo(data_type)->Size);
if (make_active && !temp_input_is_active) if (make_active && !temp_input_is_active)
{ {
SetActiveID(id, window); SetActiveID(id, window);
@@ -3936,12 +3950,12 @@ static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, c
namespace ImStb namespace ImStb
{ {
static int STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj) { return obj->TextLen; } static int STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj) { return obj->TextLen; }
static char STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx) { IM_ASSERT(idx <= obj->TextLen); return obj->TextA[idx]; } static char STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx) { IM_ASSERT(idx <= obj->TextLen); return obj->TextSrc[idx]; }
static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { unsigned int c; ImTextCharFromUtf8(&c, obj->TextA.Data + line_start_idx + char_idx, obj->TextA.Data + obj->TextLen); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance((ImWchar)c) * g.FontScale; } static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { unsigned int c; ImTextCharFromUtf8(&c, obj->TextSrc + line_start_idx + char_idx, obj->TextSrc + obj->TextLen); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance((ImWchar)c) * g.FontScale; }
static char STB_TEXTEDIT_NEWLINE = '\n'; static char STB_TEXTEDIT_NEWLINE = '\n';
static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx) static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
{ {
const char* text = obj->TextA.Data; const char* text = obj->TextSrc;
const char* text_remaining = NULL; const char* text_remaining = NULL;
const ImVec2 size = InputTextCalcTextSize(obj->Ctx, text + line_start_idx, text + obj->TextLen, &text_remaining, NULL, true); const ImVec2 size = InputTextCalcTextSize(obj->Ctx, text + line_start_idx, text + obj->TextLen, &text_remaining, NULL, true);
r->x0 = 0.0f; r->x0 = 0.0f;
@@ -3960,15 +3974,15 @@ static int IMSTB_TEXTEDIT_GETNEXTCHARINDEX_IMPL(ImGuiInputTextState* obj, int id
if (idx >= obj->TextLen) if (idx >= obj->TextLen)
return obj->TextLen + 1; return obj->TextLen + 1;
unsigned int c; unsigned int c;
return idx + ImTextCharFromUtf8(&c, obj->TextA.Data + idx, obj->TextA.Data + obj->TextLen); return idx + ImTextCharFromUtf8(&c, obj->TextSrc + idx, obj->TextSrc + obj->TextLen);
} }
static int IMSTB_TEXTEDIT_GETPREVCHARINDEX_IMPL(ImGuiInputTextState* obj, int idx) static int IMSTB_TEXTEDIT_GETPREVCHARINDEX_IMPL(ImGuiInputTextState* obj, int idx)
{ {
if (idx <= 0) if (idx <= 0)
return -1; return -1;
const char* p = ImTextFindPreviousUtf8Codepoint(obj->TextA.Data, obj->TextA.Data + idx); const char* p = ImTextFindPreviousUtf8Codepoint(obj->TextSrc, obj->TextSrc + idx);
return (int)(p - obj->TextA.Data); return (int)(p - obj->TextSrc);
} }
static bool ImCharIsSeparatorW(unsigned int c) static bool ImCharIsSeparatorW(unsigned int c)
@@ -3991,10 +4005,10 @@ static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx)
if ((obj->Flags & ImGuiInputTextFlags_Password) || idx <= 0) if ((obj->Flags & ImGuiInputTextFlags_Password) || idx <= 0)
return 0; return 0;
const char* curr_p = obj->TextA.Data + idx; const char* curr_p = obj->TextSrc + idx;
const char* prev_p = ImTextFindPreviousUtf8Codepoint(obj->TextA.Data, curr_p); const char* prev_p = ImTextFindPreviousUtf8Codepoint(obj->TextSrc, curr_p);
unsigned int curr_c; ImTextCharFromUtf8(&curr_c, curr_p, obj->TextA.Data + obj->TextLen); unsigned int curr_c; ImTextCharFromUtf8(&curr_c, curr_p, obj->TextSrc + obj->TextLen);
unsigned int prev_c; ImTextCharFromUtf8(&prev_c, prev_p, obj->TextA.Data + obj->TextLen); unsigned int prev_c; ImTextCharFromUtf8(&prev_c, prev_p, obj->TextSrc + obj->TextLen);
bool prev_white = ImCharIsBlankW(prev_c); bool prev_white = ImCharIsBlankW(prev_c);
bool prev_separ = ImCharIsSeparatorW(prev_c); bool prev_separ = ImCharIsSeparatorW(prev_c);
@@ -4007,10 +4021,10 @@ static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx)
if ((obj->Flags & ImGuiInputTextFlags_Password) || idx <= 0) if ((obj->Flags & ImGuiInputTextFlags_Password) || idx <= 0)
return 0; return 0;
const char* curr_p = obj->TextA.Data + idx; const char* curr_p = obj->TextSrc + idx;
const char* prev_p = ImTextFindPreviousUtf8Codepoint(obj->TextA.Data, curr_p); const char* prev_p = ImTextFindPreviousUtf8Codepoint(obj->TextSrc, curr_p);
unsigned int prev_c; ImTextCharFromUtf8(&prev_c, curr_p, obj->TextA.Data + obj->TextLen); unsigned int prev_c; ImTextCharFromUtf8(&prev_c, curr_p, obj->TextSrc + obj->TextLen);
unsigned int curr_c; ImTextCharFromUtf8(&curr_c, prev_p, obj->TextA.Data + obj->TextLen); unsigned int curr_c; ImTextCharFromUtf8(&curr_c, prev_p, obj->TextSrc + obj->TextLen);
bool prev_white = ImCharIsBlankW(prev_c); bool prev_white = ImCharIsBlankW(prev_c);
bool prev_separ = ImCharIsSeparatorW(prev_c); bool prev_separ = ImCharIsSeparatorW(prev_c);
@@ -4047,16 +4061,13 @@ static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(ImGuiInputTextState* obj, int idx)
static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n) static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n)
{ {
// Offset remaining text (+ copy zero terminator)
IM_ASSERT(obj->TextSrc == obj->TextA.Data);
char* dst = obj->TextA.Data + pos; char* dst = obj->TextA.Data + pos;
char* src = obj->TextA.Data + pos + n;
memmove(dst, src, obj->TextLen - n - pos + 1);
obj->Edited = true; obj->Edited = true;
obj->TextLen -= n; obj->TextLen -= n;
// Offset remaining text (FIXME-OPT: Use memmove)
const char* src = obj->TextA.Data + pos + n;
while (char c = *src++)
*dst++ = c;
*dst = '\0';
} }
static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const char* new_text, int new_text_len) static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const char* new_text, int new_text_len)
@@ -4069,11 +4080,13 @@ static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const ch
return false; return false;
// Grow internal buffer if needed // Grow internal buffer if needed
IM_ASSERT(obj->TextSrc == obj->TextA.Data);
if (new_text_len + text_len + 1 > obj->TextA.Size) if (new_text_len + text_len + 1 > obj->TextA.Size)
{ {
if (!is_resizable) if (!is_resizable)
return false; return false;
obj->TextA.resize(text_len + ImClamp(new_text_len, 32, ImMax(256, new_text_len)) + 1); obj->TextA.resize(text_len + ImClamp(new_text_len, 32, ImMax(256, new_text_len)) + 1);
obj->TextSrc = obj->TextA.Data;
} }
char* text = obj->TextA.Data; char* text = obj->TextA.Data;
@@ -4171,26 +4184,25 @@ int ImGuiInputTextState::GetCursorPos() const { return Stb->cursor
int ImGuiInputTextState::GetSelectionStart() const { return Stb->select_start; } int ImGuiInputTextState::GetSelectionStart() const { return Stb->select_start; }
int ImGuiInputTextState::GetSelectionEnd() const { return Stb->select_end; } int ImGuiInputTextState::GetSelectionEnd() const { return Stb->select_end; }
void ImGuiInputTextState::SelectAll() { Stb->select_start = 0; Stb->cursor = Stb->select_end = TextLen; Stb->has_preferred_x = 0; } void ImGuiInputTextState::SelectAll() { Stb->select_start = 0; Stb->cursor = Stb->select_end = TextLen; Stb->has_preferred_x = 0; }
void ImGuiInputTextState::ReloadUserBufAndSelectAll() { ReloadUserBuf = true; ReloadSelectionStart = 0; ReloadSelectionEnd = INT_MAX; } void ImGuiInputTextState::ReloadUserBufAndSelectAll() { WantReloadUserBuf = true; ReloadSelectionStart = 0; ReloadSelectionEnd = INT_MAX; }
void ImGuiInputTextState::ReloadUserBufAndKeepSelection() { ReloadUserBuf = true; ReloadSelectionStart = Stb->select_start; ReloadSelectionEnd = Stb->select_end; } void ImGuiInputTextState::ReloadUserBufAndKeepSelection() { WantReloadUserBuf = true; ReloadSelectionStart = Stb->select_start; ReloadSelectionEnd = Stb->select_end; }
void ImGuiInputTextState::ReloadUserBufAndMoveToEnd() { ReloadUserBuf = true; ReloadSelectionStart = ReloadSelectionEnd = INT_MAX; } void ImGuiInputTextState::ReloadUserBufAndMoveToEnd() { WantReloadUserBuf = true; ReloadSelectionStart = ReloadSelectionEnd = INT_MAX; }
ImGuiInputTextCallbackData::ImGuiInputTextCallbackData() ImGuiInputTextCallbackData::ImGuiInputTextCallbackData()
{ {
memset(this, 0, sizeof(*this)); memset(this, 0, sizeof(*this));
} }
// Public API to manipulate UTF-8 text // Public API to manipulate UTF-8 text from within a callback.
// We expose UTF-8 to the user (unlike the STB_TEXTEDIT_* functions which are manipulating wchar)
// FIXME: The existence of this rarely exercised code path is a bit of a nuisance. // FIXME: The existence of this rarely exercised code path is a bit of a nuisance.
// Historically they existed because STB_TEXTEDIT_INSERTCHARS() etc. worked on our ImWchar
// buffer, but nowadays they both work on UTF-8 data. Should aim to merge both.
void ImGuiInputTextCallbackData::DeleteChars(int pos, int bytes_count) void ImGuiInputTextCallbackData::DeleteChars(int pos, int bytes_count)
{ {
IM_ASSERT(pos + bytes_count <= BufTextLen); IM_ASSERT(pos + bytes_count <= BufTextLen);
char* dst = Buf + pos; char* dst = Buf + pos;
const char* src = Buf + pos + bytes_count; const char* src = Buf + pos + bytes_count;
while (char c = *src++) memmove(dst, src, BufTextLen - bytes_count - pos + 1);
*dst++ = c;
*dst = '\0';
if (CursorPos >= pos + bytes_count) if (CursorPos >= pos + bytes_count)
CursorPos -= bytes_count; CursorPos -= bytes_count;
@@ -4215,13 +4227,13 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
if (!is_resizable) if (!is_resizable)
return; return;
// Contrary to STB_TEXTEDIT_INSERTCHARS() this is working in the UTF8 buffer, hence the mildly similar code (until we remove the U16 buffer altogether!)
ImGuiContext& g = *Ctx; ImGuiContext& g = *Ctx;
ImGuiInputTextState* edit_state = &g.InputTextState; ImGuiInputTextState* edit_state = &g.InputTextState;
IM_ASSERT(edit_state->ID != 0 && g.ActiveId == edit_state->ID); IM_ASSERT(edit_state->ID != 0 && g.ActiveId == edit_state->ID);
IM_ASSERT(Buf == edit_state->TextA.Data); IM_ASSERT(Buf == edit_state->TextA.Data);
int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1; int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1;
edit_state->TextA.resize(new_buf_size + 1); edit_state->TextA.resize(new_buf_size + 1);
edit_state->TextSrc = edit_state->TextA.Data;
Buf = edit_state->TextA.Data; Buf = edit_state->TextA.Data;
BufSize = edit_state->BufCapacity = new_buf_size; BufSize = edit_state->BufCapacity = new_buf_size;
} }
@@ -4339,26 +4351,23 @@ static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, Im
return true; return true;
} }
// Find the shortest single replacement we can make to get the new text from the old text. // Find the shortest single replacement we can make to get from old_buf to new_buf
// Important: needs to be run before TextW is rewritten with the new characters because calling STB_TEXTEDIT_GETCHAR() at the end. // Note that this doesn't directly alter state->TextA, state->TextLen. They are expected to be made valid separately.
// FIXME: Ideally we should transition toward (1) making InsertChars()/DeleteChars() update undo-stack (2) discourage (and keep reconcile) or obsolete (and remove reconcile) accessing buffer directly. // FIXME: Ideally we should transition toward (1) making InsertChars()/DeleteChars() update undo-stack (2) discourage (and keep reconcile) or obsolete (and remove reconcile) accessing buffer directly.
static void InputTextReconcileUndoStateAfterUserCallback(ImGuiInputTextState* state, const char* new_buf_a, int new_length_a) static void InputTextReconcileUndoState(ImGuiInputTextState* state, const char* old_buf, int old_length, const char* new_buf, int new_length)
{ {
const char* old_buf = state->CallbackTextBackup.Data; const int shorter_length = ImMin(old_length, new_length);
const int old_length = state->CallbackTextBackup.Size - 1;
const int shorter_length = ImMin(old_length, new_length_a);
int first_diff; int first_diff;
for (first_diff = 0; first_diff < shorter_length; first_diff++) for (first_diff = 0; first_diff < shorter_length; first_diff++)
if (old_buf[first_diff] != new_buf_a[first_diff]) if (old_buf[first_diff] != new_buf[first_diff])
break; break;
if (first_diff == old_length && first_diff == new_length_a) if (first_diff == old_length && first_diff == new_length)
return; return;
int old_last_diff = old_length - 1; int old_last_diff = old_length - 1;
int new_last_diff = new_length_a - 1; int new_last_diff = new_length - 1;
for (; old_last_diff >= first_diff && new_last_diff >= first_diff; old_last_diff--, new_last_diff--) for (; old_last_diff >= first_diff && new_last_diff >= first_diff; old_last_diff--, new_last_diff--)
if (old_buf[old_last_diff] != new_buf_a[new_last_diff]) if (old_buf[old_last_diff] != new_buf[new_last_diff])
break; break;
const int insert_len = new_last_diff - first_diff + 1; const int insert_len = new_last_diff - first_diff + 1;
@@ -4387,6 +4396,7 @@ void ImGui::InputTextDeactivateHook(ImGuiID id)
else else
{ {
IM_ASSERT(state->TextA.Data != 0); IM_ASSERT(state->TextA.Data != 0);
IM_ASSERT(state->TextA[state->TextLen] == 0);
g.InputTextDeactivatedState.TextA.resize(state->TextLen + 1); g.InputTextDeactivatedState.TextA.resize(state->TextLen + 1);
memcpy(g.InputTextDeactivatedState.TextA.Data, state->TextA.Data, state->TextLen + 1); memcpy(g.InputTextDeactivatedState.TextA.Data, state->TextA.Data, state->TextLen + 1);
} }
@@ -4510,64 +4520,67 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX; float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX;
const bool init_reload_from_user_buf = (state != NULL && state->ReloadUserBuf); const bool init_reload_from_user_buf = (state != NULL && state->WantReloadUserBuf);
const bool init_changed_specs = (state != NULL && state->Stb->single_line != !is_multiline); // state != NULL means its our state. const bool init_changed_specs = (state != NULL && state->Stb->single_line != !is_multiline); // state != NULL means its our state.
const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav); const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav);
const bool init_state = (init_make_active || user_scroll_active); const bool init_state = (init_make_active || user_scroll_active);
if ((init_state && g.ActiveId != id) || init_changed_specs || init_reload_from_user_buf) if (init_reload_from_user_buf)
{
int new_len = (int)strlen(buf);
IM_ASSERT(new_len + 1 <= buf_size && "Is your input buffer properly zero-terminated?");
state->WantReloadUserBuf = false;
InputTextReconcileUndoState(state, state->TextA.Data, state->TextLen, buf, new_len);
state->TextA.resize(buf_size + 1); // we use +1 to make sure that .Data is always pointing to at least an empty string.
state->TextLen = new_len;
memcpy(state->TextA.Data, buf, state->TextLen + 1);
state->Stb->select_start = state->ReloadSelectionStart;
state->Stb->cursor = state->Stb->select_end = state->ReloadSelectionEnd;
state->CursorClamp();
}
else if ((init_state && g.ActiveId != id) || init_changed_specs)
{ {
// Access state even if we don't own it yet. // Access state even if we don't own it yet.
state = &g.InputTextState; state = &g.InputTextState;
state->CursorAnimReset(); state->CursorAnimReset();
state->ReloadUserBuf = false;
// Backup state of deactivating item so they'll have a chance to do a write to output buffer on the same frame they report IsItemDeactivatedAfterEdit (#4714) // Backup state of deactivating item so they'll have a chance to do a write to output buffer on the same frame they report IsItemDeactivatedAfterEdit (#4714)
InputTextDeactivateHook(state->ID); InputTextDeactivateHook(state->ID);
// Take a copy of the initial buffer value.
// From the moment we focused we are normally ignoring the content of 'buf' (unless we are in read-only mode) // From the moment we focused we are normally ignoring the content of 'buf' (unless we are in read-only mode)
const int buf_len = (int)strlen(buf); const int buf_len = (int)strlen(buf);
if (!init_reload_from_user_buf) IM_ASSERT(buf_len + 1 <= buf_size && "Is your input buffer properly zero-terminated?");
{ state->TextToRevertTo.resize(buf_len + 1); // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string.
// Take a copy of the initial buffer value. memcpy(state->TextToRevertTo.Data, buf, buf_len + 1);
state->TextToRevertTo.resize(buf_len + 1); // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string.
memcpy(state->TextToRevertTo.Data, buf, buf_len + 1);
}
// Preserve cursor position and undo/redo stack if we come back to same widget // Preserve cursor position and undo/redo stack if we come back to same widget
// FIXME: Since we reworked this on 2022/06, may want to differentiate recycle_cursor vs recycle_undostate? // FIXME: Since we reworked this on 2022/06, may want to differentiate recycle_cursor vs recycle_undostate?
bool recycle_state = (state->ID == id && !init_changed_specs && !init_reload_from_user_buf); bool recycle_state = (state->ID == id && !init_changed_specs);
if (recycle_state && (state->TextLen != buf_len || (strncmp(state->TextA.Data, buf, buf_len) != 0))) if (recycle_state && (state->TextLen != buf_len || (state->TextA.Data == NULL || strncmp(state->TextA.Data, buf, buf_len) != 0)))
recycle_state = false; recycle_state = false;
// Start edition // Start edition
state->ID = id; state->ID = id;
state->TextA.resize(buf_size + 1); // we use +1 to make sure that .Data is always pointing to at least an empty string. state->TextLen = buf_len;
state->TextLen = (int)strlen(buf); if (!is_readonly)
memcpy(state->TextA.Data, buf, state->TextLen + 1); {
state->TextA.resize(buf_size + 1); // we use +1 to make sure that .Data is always pointing to at least an empty string.
memcpy(state->TextA.Data, buf, state->TextLen + 1);
}
// Find initial scroll position for right alignment // Find initial scroll position for right alignment
state->Scroll = ImVec2(0.0f, 0.0f); state->Scroll = ImVec2(0.0f, 0.0f);
if (flags & ImGuiInputTextFlags_ElideLeft) if (flags & ImGuiInputTextFlags_ElideLeft)
state->Scroll.x += ImMax(0.0f, CalcTextSize(buf).x - frame_size.x + style.FramePadding.x * 2.0f); state->Scroll.x += ImMax(0.0f, CalcTextSize(buf).x - frame_size.x + style.FramePadding.x * 2.0f);
// Recycle existing cursor/selection/undo stack but clamp position
// Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler.
if (recycle_state) if (recycle_state)
{
// Recycle existing cursor/selection/undo stack but clamp position
// Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler.
state->CursorClamp(); state->CursorClamp();
}
else else
{
stb_textedit_initialize_state(state->Stb, !is_multiline); stb_textedit_initialize_state(state->Stb, !is_multiline);
}
if (init_reload_from_user_buf) if (!is_multiline)
{
state->Stb->select_start = state->ReloadSelectionStart;
state->Stb->cursor = state->Stb->select_end = state->ReloadSelectionEnd;
state->CursorClamp();
}
else if (!is_multiline)
{ {
if (flags & ImGuiInputTextFlags_AutoSelectAll) if (flags & ImGuiInputTextFlags_AutoSelectAll)
select_all = true; select_all = true;
@@ -4617,7 +4630,15 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Expose scroll in a manner that is agnostic to us using a child window // Expose scroll in a manner that is agnostic to us using a child window
if (is_multiline && state != NULL) if (is_multiline && state != NULL)
state->Scroll.y = draw_window->Scroll.y; state->Scroll.y = draw_window->Scroll.y;
// Read-only mode always ever read from source buffer. Refresh TextLen when active.
if (is_readonly && state != NULL)
state->TextLen = (int)strlen(buf);
//if (is_readonly && state != NULL)
// state->TextA.clear(); // Uncomment to facilitate debugging, but we otherwise prefer to keep/amortize th allocation.
} }
if (state != NULL)
state->TextSrc = is_readonly ? buf : state->TextA.Data;
// We have an edge case if ActiveId was set through another widget (e.g. widget being swapped), clear id immediately (don't wait until the end of the function) // We have an edge case if ActiveId was set through another widget (e.g. widget being swapped), clear id immediately (don't wait until the end of the function)
if (g.ActiveId == id && state == NULL) if (g.ActiveId == id && state == NULL)
@@ -4882,13 +4903,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Cut, Copy // Cut, Copy
if (g.PlatformIO.Platform_SetClipboardTextFn != NULL) if (g.PlatformIO.Platform_SetClipboardTextFn != NULL)
{ {
// SetClipboardText() only takes null terminated strings + state->TextSrc may point to read-only user buffer, so we need to make a copy.
const int ib = state->HasSelection() ? ImMin(state->Stb->select_start, state->Stb->select_end) : 0; const int ib = state->HasSelection() ? ImMin(state->Stb->select_start, state->Stb->select_end) : 0;
const int ie = state->HasSelection() ? ImMax(state->Stb->select_start, state->Stb->select_end) : state->TextLen; const int ie = state->HasSelection() ? ImMax(state->Stb->select_start, state->Stb->select_end) : state->TextLen;
g.TempBuffer.reserve(ie - ib + 1);
char backup = state->TextA.Data[ie]; memcpy(g.TempBuffer.Data, state->TextSrc + ib, ie - ib);
state->TextA.Data[ie] = 0; // A bit of a hack since SetClipboardText only takes null terminated strings g.TempBuffer.Data[ie - ib] = 0;
SetClipboardText(state->TextA.Data + ib); SetClipboardText(g.TempBuffer.Data);
state->TextA.Data[ie] = backup;
} }
if (is_cut) if (is_cut)
{ {
@@ -4904,25 +4925,27 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
{ {
// Filter pasted buffer // Filter pasted buffer
const int clipboard_len = (int)strlen(clipboard); const int clipboard_len = (int)strlen(clipboard);
char* clipboard_filtered = (char*)IM_ALLOC(clipboard_len + 1); ImVector<char> clipboard_filtered;
int clipboard_filtered_len = 0; clipboard_filtered.reserve(clipboard_len + 1);
for (const char* s = clipboard; *s != 0; ) for (const char* s = clipboard; *s != 0; )
{ {
unsigned int c; unsigned int c;
int len = ImTextCharFromUtf8(&c, s, NULL); int in_len = ImTextCharFromUtf8(&c, s, NULL);
s += len; s += in_len;
if (!InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, true)) if (!InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, true))
continue; continue;
memcpy(clipboard_filtered + clipboard_filtered_len, s - len, len); char c_utf8[5];
clipboard_filtered_len += len; ImTextCharToUtf8(c_utf8, c);
int out_len = (int)strlen(c_utf8);
clipboard_filtered.resize(clipboard_filtered.Size + out_len);
memcpy(clipboard_filtered.Data + clipboard_filtered.Size - out_len, c_utf8, out_len);
} }
clipboard_filtered[clipboard_filtered_len] = 0; if (clipboard_filtered.Size > 0) // If everything was filtered, ignore the pasting operation
if (clipboard_filtered_len > 0) // If everything was filtered, ignore the pasting operation
{ {
stb_textedit_paste(state, state->Stb, clipboard_filtered, clipboard_filtered_len); clipboard_filtered.push_back(0);
stb_textedit_paste(state, state->Stb, clipboard_filtered.Data, clipboard_filtered.Size - 1);
state->CursorFollow = true; state->CursorFollow = true;
} }
MemFree(clipboard_filtered);
} }
} }
@@ -4960,19 +4983,17 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
} }
} }
// When using 'ImGuiInputTextFlags_EnterReturnsTrue' as a special case we reapply the live buffer back to the input buffer // FIXME-OPT: We always reapply the live buffer back to the input buffer before clearing ActiveId,
// before clearing ActiveId, even though strictly speaking it wasn't modified on this frame. // even though strictly speaking it wasn't modified on this frame. Should mark dirty state from the stb_textedit callbacks.
// If we didn't do that, code like InputInt() with ImGuiInputTextFlags_EnterReturnsTrue would fail. // If we do that, need to ensure that as special case, 'validated == true' also writes back.
// This also allows the user to use InputText() with ImGuiInputTextFlags_EnterReturnsTrue without maintaining any user-side storage // This also allows the user to use InputText() without maintaining any user-side storage.
// (please note that if you use this property along ImGuiInputTextFlags_CallbackResize you can end up with your temporary string object // (please note that if you use this property along ImGuiInputTextFlags_CallbackResize you can end up with your temporary string object
// unnecessarily allocating once a frame, either store your string data, either if you don't then don't use ImGuiInputTextFlags_CallbackResize). // unnecessarily allocating once a frame, either store your string data, either if you don't then don't use ImGuiInputTextFlags_CallbackResize).
const bool apply_edit_back_to_user_buffer = !revert_edit || (validated && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0); const bool apply_edit_back_to_user_buffer = true;// !revert_edit || (validated && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0);
if (apply_edit_back_to_user_buffer) if (apply_edit_back_to_user_buffer)
{ {
// Apply new value immediately - copy modified buffer back // Apply current edited text immediately.
// Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer // Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer
// FIXME: We actually always render 'buf' when calling DrawList->AddText, making the comment above incorrect.
// FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks.
// User callback // User callback
if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackEdit | ImGuiInputTextFlags_CallbackAlways)) != 0) if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackEdit | ImGuiInputTextFlags_CallbackAlways)) != 0)
@@ -5015,10 +5036,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
callback_data.UserData = callback_user_data; callback_data.UserData = callback_user_data;
// FIXME-OPT: Undo stack reconcile needs a backup of the data until we rework API, see #7925 // FIXME-OPT: Undo stack reconcile needs a backup of the data until we rework API, see #7925
state->CallbackTextBackup.resize(state->TextLen + 1);
memcpy(state->CallbackTextBackup.Data, state->TextA.Data, state->TextLen + 1);
char* callback_buf = is_readonly ? buf : state->TextA.Data; char* callback_buf = is_readonly ? buf : state->TextA.Data;
IM_ASSERT(callback_buf == state->TextSrc);
state->CallbackTextBackup.resize(state->TextLen + 1);
memcpy(state->CallbackTextBackup.Data, callback_buf, state->TextLen + 1);
callback_data.EventKey = event_key; callback_data.EventKey = event_key;
callback_data.Buf = callback_buf; callback_data.Buf = callback_buf;
callback_data.BufTextLen = state->TextLen; callback_data.BufTextLen = state->TextLen;
@@ -5045,7 +5067,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
{ {
// Callback may update buffer and thus set buf_dirty even in read-only mode. // Callback may update buffer and thus set buf_dirty even in read-only mode.
IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text! IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
InputTextReconcileUndoStateAfterUserCallback(state, callback_data.Buf, callback_data.BufTextLen); // FIXME: Move the rest of this block inside function and rename to InputTextReconcileStateAfterUserCallback() ? InputTextReconcileUndoState(state, state->CallbackTextBackup.Data, state->CallbackTextBackup.Size - 1, callback_data.Buf, callback_data.BufTextLen);
state->TextLen = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen() state->TextLen = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen()
state->CursorAnimReset(); state->CursorAnimReset();
} }
@@ -5053,9 +5075,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
} }
// Will copy result string if modified // Will copy result string if modified
if (!is_readonly && strcmp(state->TextA.Data, buf) != 0) if (!is_readonly && strcmp(state->TextSrc, buf) != 0)
{ {
apply_new_text = state->TextA.Data; apply_new_text = state->TextSrc;
apply_new_text_length = state->TextLen; apply_new_text_length = state->TextLen;
value_changed = true; value_changed = true;
} }
@@ -5149,7 +5171,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// - Measure text height (for scrollbar) // - Measure text height (for scrollbar)
// We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort) // We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort)
// FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8. // FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8.
const char* text_begin = state->TextA.Data; const char* text_begin = buf_display;
const char* text_end = text_begin + state->TextLen; const char* text_end = text_begin + state->TextLen;
ImVec2 cursor_offset, select_start_offset; ImVec2 cursor_offset, select_start_offset;
@@ -5330,6 +5352,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
g.LastItemData.StatusFlags = item_data_backup.StatusFlags; g.LastItemData.StatusFlags = item_data_backup.StatusFlags;
} }
} }
if (state)
state->TextSrc = NULL;
// Log as text // Log as text
if (g.LogEnabled && (!is_password || is_displaying_hint)) if (g.LogEnabled && (!is_password || is_displaying_hint))
@@ -6515,10 +6539,11 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
// We vertically grow up to current line height up the typical widget height. // We vertically grow up to current line height up the typical widget height.
const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y * 2), label_size.y + padding.y * 2); const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y * 2), label_size.y + padding.y * 2);
const bool span_all_columns = (flags & ImGuiTreeNodeFlags_SpanAllColumns) != 0 && (g.CurrentTable != NULL); const bool span_all_columns = (flags & ImGuiTreeNodeFlags_SpanAllColumns) != 0 && (g.CurrentTable != NULL);
const bool span_all_columns_label = (flags & ImGuiTreeNodeFlags_LabelSpanAllColumns) != 0 && (g.CurrentTable != NULL);
ImRect frame_bb; ImRect frame_bb;
frame_bb.Min.x = span_all_columns ? window->ParentWorkRect.Min.x : (flags & ImGuiTreeNodeFlags_SpanFullWidth) ? window->WorkRect.Min.x : window->DC.CursorPos.x; frame_bb.Min.x = span_all_columns ? window->ParentWorkRect.Min.x : (flags & ImGuiTreeNodeFlags_SpanFullWidth) ? window->WorkRect.Min.x : window->DC.CursorPos.x;
frame_bb.Min.y = window->DC.CursorPos.y; frame_bb.Min.y = window->DC.CursorPos.y;
frame_bb.Max.x = span_all_columns ? window->ParentWorkRect.Max.x : (flags & ImGuiTreeNodeFlags_SpanTextWidth) ? window->DC.CursorPos.x + text_width + padding.x : window->WorkRect.Max.x; frame_bb.Max.x = span_all_columns ? window->ParentWorkRect.Max.x : (flags & ImGuiTreeNodeFlags_SpanLabelWidth) ? window->DC.CursorPos.x + text_width + padding.x : window->WorkRect.Max.x;
frame_bb.Max.y = window->DC.CursorPos.y + frame_height; frame_bb.Max.y = window->DC.CursorPos.y + frame_height;
if (display_frame) if (display_frame)
{ {
@@ -6532,7 +6557,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
// For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing
ImRect interact_bb = frame_bb; ImRect interact_bb = frame_bb;
if ((flags & (ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_SpanTextWidth | ImGuiTreeNodeFlags_SpanAllColumns)) == 0) if ((flags & (ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_SpanLabelWidth | ImGuiTreeNodeFlags_SpanAllColumns)) == 0)
interact_bb.Max.x = frame_bb.Min.x + text_width + (label_size.x > 0.0f ? style.ItemSpacing.x * 2.0f : 0.0f); interact_bb.Max.x = frame_bb.Min.x + text_width + (label_size.x > 0.0f ? style.ItemSpacing.x * 2.0f : 0.0f);
// Compute open and multi-select states before ItemAdd() as it clear NextItem data. // Compute open and multi-select states before ItemAdd() as it clear NextItem data.
@@ -6540,7 +6565,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
bool is_open = TreeNodeUpdateNextOpen(storage_id, flags); bool is_open = TreeNodeUpdateNextOpen(storage_id, flags);
bool is_visible; bool is_visible;
if (span_all_columns) if (span_all_columns || span_all_columns_label)
{ {
// Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable.. // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable..
const float backup_clip_rect_min_x = window->ClipRect.Min.x; const float backup_clip_rect_min_x = window->ClipRect.Min.x;
@@ -6581,7 +6606,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
return is_open; return is_open;
} }
if (span_all_columns) if (span_all_columns || span_all_columns_label)
{ {
TablePushBackgroundChannel(); TablePushBackgroundChannel();
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasClipRect; g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasClipRect;
@@ -6734,7 +6759,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
LogSetNextTextDecoration(">", NULL); LogSetNextTextDecoration(">", NULL);
} }
if (span_all_columns) if (span_all_columns && !span_all_columns_label)
TablePopBackgroundChannel(); TablePopBackgroundChannel();
// Label // Label
@@ -6742,6 +6767,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size); RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size);
else else
RenderText(text_pos, label, label_end, false); RenderText(text_pos, label, label_end, false);
if (span_all_columns_label)
TablePopBackgroundChannel();
} }
if (store_tree_node_stack_data && is_open) if (store_tree_node_stack_data && is_open)
@@ -7500,6 +7528,12 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int sel
if (flags & ImGuiMultiSelectFlags_BoxSelect2d) if (flags & ImGuiMultiSelectFlags_BoxSelect2d)
flags &= ~ImGuiMultiSelectFlags_BoxSelect1d; flags &= ~ImGuiMultiSelectFlags_BoxSelect1d;
// FIXME: Workaround to the fact we override CursorMaxPos, meaning size measurement are lost. (#8250)
// They should perhaps be stacked properly?
if (ImGuiTable* table = g.CurrentTable)
if (table->CurrentColumn != -1)
TableEndCell(table); // This is currently safe to call multiple time. If that properly is lost we can extract the "save measurement" part of it.
// FIXME: BeginFocusScope() // FIXME: BeginFocusScope()
const ImGuiID id = window->IDStack.back(); const ImGuiID id = window->IDStack.back();
ms->Clear(); ms->Clear();
@@ -8213,15 +8247,10 @@ void ImGuiSelectionExternalStorage::ApplyRequests(ImGuiMultiSelectIO* ms_io)
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// This is essentially a thin wrapper to using BeginChild/EndChild with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label. // This is essentially a thin wrapper to using BeginChild/EndChild with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label.
// This handle some subtleties with capturing info from the label, but for 99% uses it could essentially be rewritten as: // This handle some subtleties with capturing info from the label.
// if (ImGui::BeginChild("...", ImVec2(ImGui::CalcItemWidth(), ImGui::GetTextLineHeight() * 7.5f), ImGuiChildFlags_FrameStyle)) // If you don't need a label you can pretty much directly use ImGui::BeginChild() with ImGuiChildFlags_FrameStyle.
// { .... }
// ImGui::EndChild();
// ImGui::SameLine();
// ImGui::AlignTextToFramePadding();
// ImGui::Text("Label");
// Tip: To have a list filling the entire window width, use size.x = -FLT_MIN and pass an non-visible label e.g. "##empty" // Tip: To have a list filling the entire window width, use size.x = -FLT_MIN and pass an non-visible label e.g. "##empty"
// Tip: If your vertical size is calculated from an item count (e.g. 10 * item_height) consider adding a fractional part to facilitate seeing scrolling boundaries (e.g. 10.25 * item_height). // Tip: If your vertical size is calculated from an item count (e.g. 10 * item_height) consider adding a fractional part to facilitate seeing scrolling boundaries (e.g. 10.5f * item_height).
bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg) bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;