Updated ImGui.

This commit is contained in:
Бранимир Караџић 2019-03-06 09:50:12 -08:00
parent 701fc43149
commit ed3171a047
5 changed files with 315 additions and 221 deletions

View File

@ -2554,10 +2554,6 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name)
NavLastIds[0] = NavLastIds[1] = 0;
NavRectRel[0] = NavRectRel[1] = ImRect();
NavLastChildNavWindow = NULL;
FocusIdxAllCounter = FocusIdxTabCounter = -1;
FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = INT_MAX;
FocusIdxAllRequestNext = FocusIdxTabRequestNext = INT_MAX;
}
ImGuiWindow::~ImGuiWindow()
@ -2897,26 +2893,39 @@ bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged
return false;
}
bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop)
// Process TAB/Shift+TAB. Be mindful that this function may _clear_ the ActiveID when tabbing out.
bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id)
{
ImGuiContext& g = *GImGui;
// Increment counters
const bool is_tab_stop = (window->DC.ItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0;
window->FocusIdxAllCounter++;
window->DC.FocusCounterAll++;
if (is_tab_stop)
window->FocusIdxTabCounter++;
window->DC.FocusCounterTab++;
// Process keyboard input at this point: TAB/Shift-TAB to tab out of the currently focused item.
// Note that we can always TAB out of a widget that doesn't allow tabbing in.
if (tab_stop && (g.ActiveId == id) && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab))
window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (is_tab_stop ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items.
if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent)
return true;
if (is_tab_stop && window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent)
// Process TAB/Shift-TAB to tab *OUT* of the currently focused item.
// (Note that we can always TAB out of a widget that doesn't allow tabbing in)
if (g.ActiveId == id && g.FocusTabPressed && !(g.ActiveIdBlockNavInputFlags & (1 << ImGuiNavInput_KeyTab_)) && g.FocusRequestNextWindow == NULL)
{
g.NavJustTabbedId = id;
return true;
g.FocusRequestNextWindow = window;
g.FocusRequestNextCounterTab = window->DC.FocusCounterTab + (g.IO.KeyShift ? (is_tab_stop ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items.
}
// Handle focus requests
if (g.FocusRequestCurrWindow == window)
{
if (window->DC.FocusCounterAll == g.FocusRequestCurrCounterAll)
return true;
if (is_tab_stop && window->DC.FocusCounterTab == g.FocusRequestCurrCounterTab)
{
g.NavJustTabbedId = id;
return true;
}
// If another item is about to be focused, we clear our own active id
if (g.ActiveId == id)
ClearActiveID();
}
return false;
@ -2924,8 +2933,8 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop
void ImGui::FocusableItemUnregister(ImGuiWindow* window)
{
window->FocusIdxAllCounter--;
window->FocusIdxTabCounter--;
window->DC.FocusCounterAll--;
window->DC.FocusCounterTab--;
}
ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_x, float default_y)
@ -3515,13 +3524,34 @@ void ImGui::NewFrame()
UpdateMouseWheel();
// Pressing TAB activate widget focus
if (g.ActiveId == 0 && g.NavWindow != NULL && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab, false))
g.FocusTabPressed = (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab));
if (g.ActiveId == 0 && g.FocusTabPressed)
{
// Note that SetKeyboardFocusHere() sets the Next fields mid-frame. To be consistent we also
// manipulate the Next fields even, even though they will be turned into Curr fields by the code below.
g.FocusRequestNextWindow = g.NavWindow;
g.FocusRequestNextCounterAll = INT_MAX;
if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX)
g.NavWindow->FocusIdxTabRequestNext = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1);
g.FocusRequestNextCounterTab = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1);
else
g.NavWindow->FocusIdxTabRequestNext = g.IO.KeyShift ? -1 : 0;
g.FocusRequestNextCounterTab = g.IO.KeyShift ? -1 : 0;
}
// Turn queued focus request into current one
g.FocusRequestCurrWindow = NULL;
g.FocusRequestCurrCounterAll = g.FocusRequestCurrCounterTab = INT_MAX;
if (g.FocusRequestNextWindow != NULL)
{
ImGuiWindow* window = g.FocusRequestNextWindow;
g.FocusRequestCurrWindow = window;
if (g.FocusRequestNextCounterAll != INT_MAX && window->DC.FocusCounterAll != -1)
g.FocusRequestCurrCounterAll = ImModPositive(g.FocusRequestNextCounterAll, window->DC.FocusCounterAll + 1);
if (g.FocusRequestNextCounterTab != INT_MAX && window->DC.FocusCounterTab != -1)
g.FocusRequestCurrCounterTab = ImModPositive(g.FocusRequestNextCounterTab, window->DC.FocusCounterTab + 1);
g.FocusRequestNextWindow = NULL;
g.FocusRequestNextCounterAll = g.FocusRequestNextCounterTab = INT_MAX;
}
g.NavIdTabCounter = INT_MAX;
// Mark all windows as not visible
@ -5168,12 +5198,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Lock window rounding for the frame (so that altering them doesn't cause inconsistencies)
window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding;
// Prepare for item focus requests
window->FocusIdxAllRequestCurrent = (window->FocusIdxAllRequestNext == INT_MAX || window->FocusIdxAllCounter == -1) ? INT_MAX : (window->FocusIdxAllRequestNext + (window->FocusIdxAllCounter+1)) % (window->FocusIdxAllCounter+1);
window->FocusIdxTabRequestCurrent = (window->FocusIdxTabRequestNext == INT_MAX || window->FocusIdxTabCounter == -1) ? INT_MAX : (window->FocusIdxTabRequestNext + (window->FocusIdxTabCounter+1)) % (window->FocusIdxTabCounter+1);
window->FocusIdxAllCounter = window->FocusIdxTabCounter = -1;
window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = INT_MAX;
// Apply scrolling
window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window, true);
window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
@ -5348,6 +5372,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->DC.ChildWindows.resize(0);
window->DC.LayoutType = ImGuiLayoutType_Vertical;
window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical;
window->DC.FocusCounterAll = window->DC.FocusCounterTab = -1;
window->DC.ItemFlags = parent_window ? parent_window->DC.ItemFlags : ImGuiItemFlags_Default_;
window->DC.ItemWidth = window->ItemWidthDefault;
window->DC.TextWrapPos = -1.0f; // disabled
@ -6460,9 +6485,11 @@ void ImGui::ActivateItem(ImGuiID id)
void ImGui::SetKeyboardFocusHere(int offset)
{
IM_ASSERT(offset >= -1); // -1 is allowed but not below
ImGuiWindow* window = GetCurrentWindow();
window->FocusIdxAllRequestNext = window->FocusIdxAllCounter + 1 + offset;
window->FocusIdxTabRequestNext = INT_MAX;
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
g.FocusRequestNextWindow = window;
g.FocusRequestNextCounterAll = window->DC.FocusCounterAll + 1 + offset;
g.FocusRequestNextCounterTab = INT_MAX;
}
void ImGui::SetItemDefaultFocus()
@ -7371,7 +7398,7 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con
g.NavWindow = window; // Always refresh g.NavWindow, because some operations such as FocusItem() don't have a window.
g.NavLayer = window->DC.NavLayerCurrent;
g.NavIdIsAlive = true;
g.NavIdTabCounter = window->FocusIdxTabCounter;
g.NavIdTabCounter = window->DC.FocusCounterTab;
window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; // Store item bounding box (relative to window position)
}
}
@ -7611,6 +7638,7 @@ static void ImGui::NavUpdate()
NAV_MAP_KEY(ImGuiKey_RightArrow,ImGuiNavInput_KeyRight_);
NAV_MAP_KEY(ImGuiKey_UpArrow, ImGuiNavInput_KeyUp_ );
NAV_MAP_KEY(ImGuiKey_DownArrow, ImGuiNavInput_KeyDown_ );
NAV_MAP_KEY(ImGuiKey_Tab, ImGuiNavInput_KeyTab_ );
if (g.IO.KeyCtrl)
g.IO.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f;
if (g.IO.KeyShift)

View File

@ -298,7 +298,7 @@ namespace ImGui
IMGUI_API void SetScrollX(float scroll_x); // set scrolling amount [0..GetScrollMaxX()]
IMGUI_API void SetScrollY(float scroll_y); // set scrolling amount [0..GetScrollMaxY()]
IMGUI_API void SetScrollHereY(float center_y_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_y_ratio=0.0: top, 0.5: center, 1.0: bottom. When using to make a "default/current item" visible, consider using SetItemDefaultFocus() instead.
IMGUI_API void SetScrollFromPosY(float local_y, float center_y_ratio = 0.5f); // adjust scrolling amount to make given position valid. use GetCursorPos() or GetCursorStartPos()+offset to get valid positions.
IMGUI_API void SetScrollFromPosY(float local_y, float center_y_ratio = 0.5f); // adjust scrolling amount to make given position visible. Generally GetCursorStartPos() + offset to compute a valid position.
// Parameters stacks (shared)
IMGUI_API void PushFont(ImFont* font); // use NULL as a shortcut to push default font
@ -451,6 +451,7 @@ namespace ImGui
// - Most of the ImGuiInputTextFlags flags are only useful for InputText() and not for InputFloatX, InputIntX, InputDouble etc.
IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0,0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool InputTextWithHint(const char* label, const char* hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, const char* format = "%.3f", ImGuiInputTextFlags flags = 0);
IMGUI_API bool InputFloat2(const char* label, float v[2], const char* format = "%.3f", ImGuiInputTextFlags flags = 0);
IMGUI_API bool InputFloat3(const char* label, float v[3], const char* format = "%.3f", ImGuiInputTextFlags flags = 0);
@ -968,6 +969,7 @@ enum ImGuiNavInput_
// [Internal] Don't use directly! This is used internally to differentiate keyboard from gamepad inputs for behaviors that require to differentiate them.
// Keyboard behavior that have no corresponding gamepad mapping (e.g. CTRL+TAB) will be directly reading from io.KeysDown[] instead of io.NavInputs[].
ImGuiNavInput_KeyMenu_, // toggle menu // = io.KeyAlt
ImGuiNavInput_KeyTab_, // tab // = Tab key
ImGuiNavInput_KeyLeft_, // move left // = Arrow keys
ImGuiNavInput_KeyRight_, // move right
ImGuiNavInput_KeyUp_, // move up

View File

@ -126,7 +126,7 @@ static void ShowExampleAppCustomRendering(bool* p_open);
static void ShowExampleMenuFile();
// Helper to display a little (?) mark which shows a tooltip when hovered.
static void ShowHelpMarker(const char* desc)
static void HelpMarker(const char* desc)
{
ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered())
@ -311,9 +311,9 @@ void ImGui::ShowDemoWindow(bool* p_open)
{
ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad);
ImGui::SameLine(); ShowHelpMarker("Required back-end to feed in gamepad inputs in io.NavInputs[] and set io.BackendFlags |= ImGuiBackendFlags_HasGamepad.\n\nRead instructions in imgui.cpp for details.");
ImGui::SameLine(); HelpMarker("Required back-end to feed in gamepad inputs in io.NavInputs[] and set io.BackendFlags |= ImGuiBackendFlags_HasGamepad.\n\nRead instructions in imgui.cpp for details.");
ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos);
ImGui::SameLine(); ShowHelpMarker("Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos.");
ImGui::SameLine(); HelpMarker("Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos.");
ImGui::CheckboxFlags("io.ConfigFlags: NoMouse", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NoMouse);
if (io.ConfigFlags & ImGuiConfigFlags_NoMouse) // Create a way to restore this flag otherwise we could be stuck completely!
{
@ -326,21 +326,21 @@ void ImGui::ShowDemoWindow(bool* p_open)
io.ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
}
ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange);
ImGui::SameLine(); ShowHelpMarker("Instruct back-end to not alter mouse cursor shape and visibility.");
ImGui::SameLine(); HelpMarker("Instruct back-end to not alter mouse cursor shape and visibility.");
ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
ImGui::SameLine(); ShowHelpMarker("Set to false to disable blinking cursor, for users who consider it distracting");
ImGui::SameLine(); HelpMarker("Set to false to disable blinking cursor, for users who consider it distracting");
ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges);
ImGui::SameLine(); ShowHelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback.");
ImGui::SameLine(); HelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback.");
ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly);
ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
ImGui::SameLine(); ShowHelpMarker("Instruct Dear ImGui to render a mouse cursor for you. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something).");
ImGui::SameLine(); HelpMarker("Instruct Dear ImGui to render a mouse cursor for you. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something).");
ImGui::TreePop();
ImGui::Separator();
}
if (ImGui::TreeNode("Backend Flags"))
{
ShowHelpMarker("Those flags are set by the back-ends (imgui_impl_xxx files) to specify their capabilities.");
HelpMarker("Those flags are set by the back-ends (imgui_impl_xxx files) to specify their capabilities.");
ImGuiBackendFlags backend_flags = io.BackendFlags; // Make a local copy to avoid modifying the back-end flags.
ImGui::CheckboxFlags("io.BackendFlags: HasGamepad", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasGamepad);
ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasMouseCursors);
@ -359,7 +359,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
if (ImGui::TreeNode("Capture/Logging"))
{
ImGui::TextWrapped("The logging API redirects all text output so you can easily capture the content of a window or a block. Tree nodes can be automatically expanded.");
ShowHelpMarker("Try opening any of the contents below in this window and then click one of the \"Log To\" button.");
HelpMarker("Try opening any of the contents below in this window and then click one of the \"Log To\" button.");
ImGui::LogButtons();
ImGui::TextWrapped("You can also call ImGui::LogText() to output directly to the log without a visual output.");
if (ImGui::Button("Copy \"Hello, world!\" to clipboard"))
@ -476,17 +476,20 @@ static void ShowDemoWindowWidgets()
const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
static int item_current = 0;
ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items));
ImGui::SameLine(); ShowHelpMarker("Refer to the \"Combo\" section below for an explanation of the full BeginCombo/EndCombo API, and demonstration of various flags.\n");
ImGui::SameLine(); HelpMarker("Refer to the \"Combo\" section below for an explanation of the full BeginCombo/EndCombo API, and demonstration of various flags.\n");
}
{
static char str0[128] = "Hello, world!";
static int i0 = 123;
ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
ImGui::SameLine(); ShowHelpMarker("USER:\nHold SHIFT or use mouse to select text.\n" "CTRL+Left/Right to word jump.\n" "CTRL+A or double-click to select all.\n" "CTRL+X,CTRL+C,CTRL+V clipboard.\n" "CTRL+Z,CTRL+Y undo/redo.\n" "ESCAPE to revert.\n\nPROGRAMMER:\nYou can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated in imgui_demo.cpp).");
ImGui::SameLine(); HelpMarker("USER:\nHold SHIFT or use mouse to select text.\n" "CTRL+Left/Right to word jump.\n" "CTRL+A or double-click to select all.\n" "CTRL+X,CTRL+C,CTRL+V clipboard.\n" "CTRL+Z,CTRL+Y undo/redo.\n" "ESCAPE to revert.\n\nPROGRAMMER:\nYou can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated in imgui_demo.cpp).");
static char str1[128] = "";
ImGui::InputTextWithHint("input text (w/ hint)", "enter text here", str1, IM_ARRAYSIZE(str1));
static int i0 = 123;
ImGui::InputInt("input int", &i0);
ImGui::SameLine(); ShowHelpMarker("You can apply arithmetic operators +,*,/ on numerical values.\n e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\nUse +- to subtract.\n");
ImGui::SameLine(); HelpMarker("You can apply arithmetic operators +,*,/ on numerical values.\n e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\nUse +- to subtract.\n");
static float f0 = 0.001f;
ImGui::InputFloat("input float", &f0, 0.01f, 1.0f, "%.3f");
@ -496,7 +499,7 @@ static void ShowDemoWindowWidgets()
static float f1 = 1.e10f;
ImGui::InputFloat("input scientific", &f1, 0.0f, 0.0f, "%e");
ImGui::SameLine(); ShowHelpMarker("You can input value using the scientific notation,\n e.g. \"1e+8\" becomes \"100000000\".\n");
ImGui::SameLine(); HelpMarker("You can input value using the scientific notation,\n e.g. \"1e+8\" becomes \"100000000\".\n");
static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
ImGui::InputFloat3("input float3", vec4a);
@ -505,7 +508,7 @@ static void ShowDemoWindowWidgets()
{
static int i1 = 50, i2 = 42;
ImGui::DragInt("drag int", &i1, 1);
ImGui::SameLine(); ShowHelpMarker("Click and drag to edit value.\nHold SHIFT/ALT for faster/slower edit.\nDouble-click or CTRL+click to input value.");
ImGui::SameLine(); HelpMarker("Click and drag to edit value.\nHold SHIFT/ALT for faster/slower edit.\nDouble-click or CTRL+click to input value.");
ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%");
@ -517,7 +520,7 @@ static void ShowDemoWindowWidgets()
{
static int i1=0;
ImGui::SliderInt("slider int", &i1, -1, 3);
ImGui::SameLine(); ShowHelpMarker("CTRL+click to input value.");
ImGui::SameLine(); HelpMarker("CTRL+click to input value.");
static float f1=0.123f, f2=0.0f;
ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f");
@ -530,7 +533,7 @@ static void ShowDemoWindowWidgets()
static float col1[3] = { 1.0f,0.0f,0.2f };
static float col2[4] = { 0.4f,0.7f,0.0f,0.5f };
ImGui::ColorEdit3("color 1", col1);
ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nClick and hold to use drag and drop.\nRight-click on the colored square to show options.\nCTRL+click on individual component to input value.\n");
ImGui::SameLine(); HelpMarker("Click on the colored square to open a color picker.\nClick and hold to use drag and drop.\nRight-click on the colored square to show options.\nCTRL+click on individual component to input value.\n");
ImGui::ColorEdit4("color 2", col2);
}
@ -573,7 +576,7 @@ static void ShowDemoWindowWidgets()
if (ImGui::TreeNode("Advanced, with Selectable nodes"))
{
ShowHelpMarker("This is a more standard looking tree with selectable nodes.\nClick to select, CTRL+Click to toggle, click on arrows or double-click to open.");
HelpMarker("This is a more standard looking tree with selectable nodes.\nClick to select, CTRL+Click to toggle, click on arrows or double-click to open.");
static bool align_label_with_current_x_position = false;
ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position);
ImGui::Text("Hello!");
@ -660,7 +663,7 @@ static void ShowDemoWindowWidgets()
ImGui::TextColored(ImVec4(1.0f,0.0f,1.0f,1.0f), "Pink");
ImGui::TextColored(ImVec4(1.0f,1.0f,0.0f,1.0f), "Yellow");
ImGui::TextDisabled("Disabled");
ImGui::SameLine(); ShowHelpMarker("The TextDisabled color is stored in ImGuiStyle.");
ImGui::SameLine(); HelpMarker("The TextDisabled color is stored in ImGuiStyle.");
ImGui::TreePop();
}
@ -767,6 +770,7 @@ static void ShowDemoWindowWidgets()
// Expose flags as checkbox for the demo
static ImGuiComboFlags flags = 0;
ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", (unsigned int*)&flags, ImGuiComboFlags_PopupAlignLeft);
ImGui::SameLine(); HelpMarker("Only makes a difference if the popup is larger than the combo");
if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", (unsigned int*)&flags, ImGuiComboFlags_NoArrowButton))
flags &= ~ImGuiComboFlags_NoPreview; // Clear the other flag, as we cannot combine both
if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", (unsigned int*)&flags, ImGuiComboFlags_NoPreview))
@ -837,7 +841,7 @@ static void ShowDemoWindowWidgets()
}
if (ImGui::TreeNode("Selection State: Multiple Selection"))
{
ShowHelpMarker("Hold CTRL and click to select multiple items.");
HelpMarker("Hold CTRL and click to select multiple items.");
static bool selection[5] = { false, false, false, false, false };
for (int n = 0; n < 5; n++)
{
@ -897,7 +901,7 @@ static void ShowDemoWindowWidgets()
}
if (ImGui::TreeNode("Alignment"))
{
ShowHelpMarker("Alignment applies when a selectable is larger than its text content.\nBy default, Selectables uses style.SelectableTextAlign but it can be overriden on a per-item basis using PushStyleVar().");
HelpMarker("Alignment applies when a selectable is larger than its text content.\nBy default, Selectables uses style.SelectableTextAlign but it can be overriden on a per-item basis using PushStyleVar().");
static bool selected[3*3] = { true, false, true, false, true, false, true, false, true };
for (int y = 0; y < 3; y++)
{
@ -930,7 +934,8 @@ static void ShowDemoWindowWidgets()
ImGui::Text("Password input");
static char bufpass[64] = "password123";
ImGui::InputText("password", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank);
ImGui::SameLine(); ShowHelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
ImGui::SameLine(); HelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
ImGui::InputTextWithHint("password (w/ hint)", "<password>", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank);
ImGui::InputText("password (clear)", bufpass, 64, ImGuiInputTextFlags_CharsNoBlank);
ImGui::TreePop();
@ -940,7 +945,6 @@ static void ShowDemoWindowWidgets()
{
// Note: we are using a fixed-sized buffer for simplicity here. See ImGuiInputTextFlags_CallbackResize
// and the code in misc/cpp/imgui_stdlib.h for how to setup InputText() for dynamically resizing strings.
static bool read_only = false;
static char text[1024*16] =
"/*\n"
" The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
@ -953,9 +957,11 @@ static void ShowDemoWindowWidgets()
"label:\n"
"\tlock cmpxchg8b eax\n";
ShowHelpMarker("You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputTextMultiline() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example. (This is not demonstrated in imgui_demo.cpp)");
ImGui::Checkbox("Read-only", &read_only);
ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput | (read_only ? ImGuiInputTextFlags_ReadOnly : 0);
static ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput;
HelpMarker("You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputTextMultiline() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example. (This is not demonstrated in imgui_demo.cpp)");
ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", (unsigned int*)&flags, ImGuiInputTextFlags_ReadOnly);
ImGui::CheckboxFlags("ImGuiInputTextFlags_AllowTabInput", (unsigned int*)&flags, ImGuiInputTextFlags_AllowTabInput);
ImGui::CheckboxFlags("ImGuiInputTextFlags_CtrlEnterForNewLine", (unsigned int*)&flags, ImGuiInputTextFlags_CtrlEnterForNewLine);
ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 16), flags);
ImGui::TreePop();
}
@ -1036,12 +1042,12 @@ static void ShowDemoWindowWidgets()
ImGui::Checkbox("With Alpha Preview", &alpha_preview);
ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview);
ImGui::Checkbox("With Drag and Drop", &drag_and_drop);
ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); ShowHelpMarker("Right-click on the individual color widget to show options.");
ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); ShowHelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets.");
ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); HelpMarker("Right-click on the individual color widget to show options.");
ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); HelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets.");
int misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (drag_and_drop ? 0 : ImGuiColorEditFlags_NoDragDrop) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions);
ImGui::Text("Color widget:");
ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nCTRL+click on individual component to input value.\n");
ImGui::SameLine(); HelpMarker("Click on the colored square to open a color picker.\nCTRL+click on individual component to input value.\n");
ImGui::ColorEdit3("MyColor##1", (float*)&color, misc_flags);
ImGui::Text("Color widget HSV with Alpha:");
@ -1051,7 +1057,7 @@ static void ShowDemoWindowWidgets()
ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | misc_flags);
ImGui::Text("Color button with Picker:");
ImGui::SameLine(); ShowHelpMarker("With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\nWith the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only be used for the tooltip and picker popup.");
ImGui::SameLine(); HelpMarker("With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\nWith the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only be used for the tooltip and picker popup.");
ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags);
ImGui::Text("Color button with Custom Picker Popup:");
@ -1143,9 +1149,9 @@ static void ShowDemoWindowWidgets()
}
}
ImGui::Combo("Display Mode", &display_mode, "Auto/Current\0None\0RGB Only\0HSV Only\0Hex Only\0");
ImGui::SameLine(); ShowHelpMarker("ColorEdit defaults to displaying RGB inputs if you don't specify a display mode, but the user can change it with a right-click.\n\nColorPicker defaults to displaying RGB+HSV+Hex if you don't specify a display mode.\n\nYou can change the defaults using SetColorEditOptions().");
ImGui::SameLine(); HelpMarker("ColorEdit defaults to displaying RGB inputs if you don't specify a display mode, but the user can change it with a right-click.\n\nColorPicker defaults to displaying RGB+HSV+Hex if you don't specify a display mode.\n\nYou can change the defaults using SetColorEditOptions().");
ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0Hue bar + SV rect\0Hue wheel + SV triangle\0");
ImGui::SameLine(); ShowHelpMarker("User can right-click the picker to change mode.");
ImGui::SameLine(); HelpMarker("User can right-click the picker to change mode.");
ImGuiColorEditFlags flags = misc_flags;
if (!alpha) flags |= ImGuiColorEditFlags_NoAlpha; // This is by default if you call ColorPicker3() instead of ColorPicker4()
if (alpha_bar) flags |= ImGuiColorEditFlags_AlphaBar;
@ -1159,7 +1165,7 @@ static void ShowDemoWindowWidgets()
ImGui::ColorPicker4("MyColor##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL);
ImGui::Text("Programmatically set defaults:");
ImGui::SameLine(); ShowHelpMarker("SetColorEditOptions() is designed to allow you to set boot-time default.\nWe don't have Push/Pop functions because you can force options on a per-widget basis if needed, and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid encouraging you to persistently save values that aren't forward-compatible.");
ImGui::SameLine(); HelpMarker("SetColorEditOptions() is designed to allow you to set boot-time default.\nWe don't have Push/Pop functions because you can force options on a per-widget basis if needed, and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid encouraging you to persistently save values that aren't forward-compatible.");
if (ImGui::Button("Default: Uint8 + HSV + Hue Bar"))
ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_PickerHueBar);
if (ImGui::Button("Default: Float + HDR + Hue Wheel"))
@ -1224,7 +1230,7 @@ static void ShowDemoWindowWidgets()
const float drag_speed = 0.2f;
static bool drag_clamp = false;
ImGui::Text("Drags:");
ImGui::Checkbox("Clamp integers to 0..50", &drag_clamp); ImGui::SameLine(); ShowHelpMarker("As with every widgets in dear imgui, we never modify values unless there is a user interaction.\nYou can override the clamping limits by using CTRL+Click to input a value.");
ImGui::Checkbox("Clamp integers to 0..50", &drag_clamp); ImGui::SameLine(); HelpMarker("As with every widgets in dear imgui, we never modify values unless there is a user interaction.\nYou can override the clamping limits by using CTRL+Click to input a value.");
ImGui::DragScalar("drag s8", ImGuiDataType_S8, &s8_v, drag_speed, drag_clamp ? &s8_zero : NULL, drag_clamp ? &s8_fifty : NULL);
ImGui::DragScalar("drag u8", ImGuiDataType_U8, &u8_v, drag_speed, drag_clamp ? &u8_zero : NULL, drag_clamp ? &u8_fifty : NULL, "%u ms");
ImGui::DragScalar("drag s16", ImGuiDataType_S16, &s16_v, drag_speed, drag_clamp ? &s16_zero : NULL, drag_clamp ? &s16_fifty : NULL);
@ -1234,7 +1240,7 @@ static void ShowDemoWindowWidgets()
ImGui::DragScalar("drag s64", ImGuiDataType_S64, &s64_v, drag_speed, drag_clamp ? &s64_zero : NULL, drag_clamp ? &s64_fifty : NULL);
ImGui::DragScalar("drag u64", ImGuiDataType_U64, &u64_v, drag_speed, drag_clamp ? &u64_zero : NULL, drag_clamp ? &u64_fifty : NULL);
ImGui::DragScalar("drag float", ImGuiDataType_Float, &f32_v, 0.005f, &f32_zero, &f32_one, "%f", 1.0f);
ImGui::DragScalar("drag float ^2", ImGuiDataType_Float, &f32_v, 0.005f, &f32_zero, &f32_one, "%f", 2.0f); ImGui::SameLine(); ShowHelpMarker("You can use the 'power' parameter to increase tweaking precision on one side of the range.");
ImGui::DragScalar("drag float ^2", ImGuiDataType_Float, &f32_v, 0.005f, &f32_zero, &f32_one, "%f", 2.0f); ImGui::SameLine(); HelpMarker("You can use the 'power' parameter to increase tweaking precision on one side of the range.");
ImGui::DragScalar("drag double", ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, NULL, "%.10f grams", 1.0f);
ImGui::DragScalar("drag double ^2", ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, &f64_one, "0 < %.10f < 1", 2.0f);
@ -1583,7 +1589,7 @@ static void ShowDemoWindowLayout()
if (ImGui::TreeNode("Child windows"))
{
ShowHelpMarker("Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window.");
HelpMarker("Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window.");
static bool disable_mouse_wheel = false;
static bool disable_menu = false;
ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel);
@ -1667,31 +1673,31 @@ static void ShowDemoWindowLayout()
{
static float f = 0.0f;
ImGui::Text("PushItemWidth(100)");
ImGui::SameLine(); ShowHelpMarker("Fixed width.");
ImGui::SameLine(); HelpMarker("Fixed width.");
ImGui::PushItemWidth(100);
ImGui::DragFloat("float##1", &f);
ImGui::PopItemWidth();
ImGui::Text("PushItemWidth(GetWindowWidth() * 0.5f)");
ImGui::SameLine(); ShowHelpMarker("Half of window width.");
ImGui::SameLine(); HelpMarker("Half of window width.");
ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f);
ImGui::DragFloat("float##2", &f);
ImGui::PopItemWidth();
ImGui::Text("PushItemWidth(GetContentRegionAvailWidth() * 0.5f)");
ImGui::SameLine(); ShowHelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
ImGui::SameLine(); HelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() * 0.5f);
ImGui::DragFloat("float##3", &f);
ImGui::PopItemWidth();
ImGui::Text("PushItemWidth(-100)");
ImGui::SameLine(); ShowHelpMarker("Align to right edge minus 100");
ImGui::SameLine(); HelpMarker("Align to right edge minus 100");
ImGui::PushItemWidth(-100);
ImGui::DragFloat("float##4", &f);
ImGui::PopItemWidth();
ImGui::Text("PushItemWidth(-1)");
ImGui::SameLine(); ShowHelpMarker("Align to right edge");
ImGui::SameLine(); HelpMarker("Align to right edge");
ImGui::PushItemWidth(-1);
ImGui::DragFloat("float##5", &f);
ImGui::PopItemWidth();
@ -1860,7 +1866,7 @@ static void ShowDemoWindowLayout()
if (ImGui::TreeNode("Groups"))
{
ShowHelpMarker("Using ImGui::BeginGroup()/EndGroup() to layout items. BeginGroup() basically locks the horizontal position. EndGroup() bundles the whole group so that you can use functions such as IsItemHovered() on it.");
HelpMarker("Using ImGui::BeginGroup()/EndGroup() to layout items. BeginGroup() basically locks the horizontal position. EndGroup() bundles the whole group so that you can use functions such as IsItemHovered() on it.");
ImGui::BeginGroup();
{
ImGui::BeginGroup();
@ -1904,7 +1910,7 @@ static void ShowDemoWindowLayout()
if (ImGui::TreeNode("Text Baseline Alignment"))
{
ShowHelpMarker("This is testing the vertical alignment that gets applied on text to keep it aligned with widgets. Lines only composed of text or \"small\" widgets fit in less vertical spaces than lines with normal widgets.");
HelpMarker("This is testing the vertical alignment that gets applied on text to keep it aligned with widgets. Lines only composed of text or \"small\" widgets fit in less vertical spaces than lines with normal widgets.");
ImGui::Text("One\nTwo\nThree"); ImGui::SameLine();
ImGui::Text("Hello\nWorld"); ImGui::SameLine();
@ -1959,7 +1965,7 @@ static void ShowDemoWindowLayout()
if (ImGui::TreeNode("Scrolling"))
{
ShowHelpMarker("Use SetScrollHereY() or SetScrollFromPosY() to scroll to a given position.");
HelpMarker("Use SetScrollHereY() or SetScrollFromPosY() to scroll to a given position.");
static bool track = true;
static int track_line = 50, scroll_to_px = 200;
@ -2001,7 +2007,7 @@ static void ShowDemoWindowLayout()
if (ImGui::TreeNode("Horizontal Scrolling"))
{
ShowHelpMarker("Horizontal scrolling for a window has to be enabled explicitly via the ImGuiWindowFlags_HorizontalScrollbar flag.\n\nYou may want to explicitly specify content width by calling SetNextWindowContentWidth() before Begin().");
HelpMarker("Horizontal scrolling for a window has to be enabled explicitly via the ImGuiWindowFlags_HorizontalScrollbar flag.\n\nYou may want to explicitly specify content width by calling SetNextWindowContentWidth() before Begin().");
static int lines = 7;
ImGui::SliderInt("Lines", &lines, 1, 15);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
@ -2173,7 +2179,7 @@ static void ShowDemoWindowPopups()
// We can also use OpenPopupOnItemClick() which is the same as BeginPopupContextItem() but without the Begin call.
// So here we will make it that clicking on the text field with the right mouse button (1) will toggle the visibility of the popup above.
ImGui::Text("(You can also right-click me to the same popup as above.)");
ImGui::Text("(You can also right-click me to open the same popup as above.)");
ImGui::OpenPopupOnItemClick("item context menu", 1);
// When used after an item that has an ID (here the Button), we can skip providing an ID to BeginPopupContextItem().
@ -2454,7 +2460,7 @@ static void ShowDemoWindowColumns()
}
bool node_open = ImGui::TreeNode("Tree within single cell");
ImGui::SameLine(); ShowHelpMarker("NB: Tree node must be poped before ending the cell. There's no storage of state per-cell.");
ImGui::SameLine(); HelpMarker("NB: Tree node must be poped before ending the cell. There's no storage of state per-cell.");
if (node_open)
{
ImGui::Columns(2, "tree items");
@ -2537,7 +2543,7 @@ static void ShowDemoWindowMisc()
ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
ImGui::PushAllowKeyboardFocus(false);
ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
//ImGui::SameLine(); ShowHelperMarker("Use ImGui::PushAllowKeyboardFocus(bool)\nto disable tabbing through certain widgets.");
//ImGui::SameLine(); HelpMarker("Use ImGui::PushAllowKeyboardFocus(bool)\nto disable tabbing through certain widgets.");
ImGui::PopAllowKeyboardFocus();
ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
ImGui::TreePop();
@ -2615,7 +2621,7 @@ static void ShowDemoWindowMisc()
ImGui::Text("Current mouse cursor = %d: %s", ImGui::GetMouseCursor(), mouse_cursors_names[ImGui::GetMouseCursor()]);
ImGui::Text("Hover to see mouse cursors:");
ImGui::SameLine(); ShowHelpMarker("Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. If software cursor rendering (io.MouseDrawCursor) is set ImGui will draw the right cursor for you, otherwise your backend needs to handle it.");
ImGui::SameLine(); HelpMarker("Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. If software cursor rendering (io.MouseDrawCursor) is set ImGui will draw the right cursor for you, otherwise your backend needs to handle it.");
for (int i = 0; i < ImGuiMouseCursor_COUNT; i++)
{
char label[32];
@ -2793,7 +2799,7 @@ void ImGui::ShowFontSelector(const char* label)
ImGui::EndCombo();
}
ImGui::SameLine();
ShowHelpMarker(
HelpMarker(
"- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n"
"- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
"- Read FAQ and documentation in misc/fonts/ for more details.\n"
@ -2836,7 +2842,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
if (ImGui::Button("Revert Ref"))
style = *ref;
ImGui::SameLine();
ShowHelpMarker("Save/Revert in local non-persistent storage. Default Colors definition are not affected. Use \"Export Colors\" below to save them somewhere.");
HelpMarker("Save/Revert in local non-persistent storage. Default Colors definition are not affected. Use \"Export Colors\" below to save them somewhere.");
ImGui::Separator();
@ -2869,9 +2875,9 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f");
ImGui::Text("Alignment");
ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); ShowHelpMarker("Alignment applies when a button is larger than its text content.");
ImGui::SliderFloat2("SelectableTextAlign", (float*)&style.SelectableTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); ShowHelpMarker("Alignment applies when a selectable is larger than its text content.");
ImGui::Text("Safe Area Padding"); ImGui::SameLine(); ShowHelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content.");
ImGui::SliderFloat2("SelectableTextAlign", (float*)&style.SelectableTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); HelpMarker("Alignment applies when a selectable is larger than its text content.");
ImGui::Text("Safe Area Padding"); ImGui::SameLine(); HelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f");
ImGui::EndTabItem();
}
@ -2906,7 +2912,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
ImGui::RadioButton("Opaque", &alpha_flags, 0); ImGui::SameLine();
ImGui::RadioButton("Alpha", &alpha_flags, ImGuiColorEditFlags_AlphaPreview); ImGui::SameLine();
ImGui::RadioButton("Both", &alpha_flags, ImGuiColorEditFlags_AlphaPreviewHalf); ImGui::SameLine();
ShowHelpMarker("In the color list:\nLeft-click on colored square to open color picker,\nRight-click to open edit options menu.");
HelpMarker("In the color list:\nLeft-click on colored square to open color picker,\nRight-click to open edit options menu.");
ImGui::BeginChild("##colors", ImVec2(0, 0), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened);
ImGui::PushItemWidth(-160);
@ -2938,7 +2944,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
{
ImGuiIO& io = ImGui::GetIO();
ImFontAtlas* atlas = io.Fonts;
ShowHelpMarker("Read FAQ and misc/fonts/README.txt for details on font loading.");
HelpMarker("Read FAQ and misc/fonts/README.txt for details on font loading.");
ImGui::PushItemWidth(120);
for (int i = 0; i < atlas->Fonts.Size; i++)
{
@ -2952,7 +2958,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
ImGui::Text("The quick brown fox jumps over the lazy dog");
ImGui::PopFont();
ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f"); // Scale only this font
ImGui::SameLine(); ShowHelpMarker("Note than the default embedded font is NOT meant to be scaled.\n\nFont are currently rendered into bitmaps at a given size at the time of building the atlas. You may oversample them to get some flexibility with scaling. You can also render at multiple sizes and select which one to use at runtime.\n\n(Glimmer of hope: the atlas system should hopefully be rewritten in the future to make scaling more natural and automatic.)");
ImGui::SameLine(); HelpMarker("Note than the default embedded font is NOT meant to be scaled.\n\nFont are currently rendered into bitmaps at a given size at the time of building the atlas. You may oversample them to get some flexibility with scaling. You can also render at multiple sizes and select which one to use at runtime.\n\n(Glimmer of hope: the atlas system should hopefully be rewritten in the future to make scaling more natural and automatic.)");
ImGui::InputFloat("Font offset", &font->DisplayOffset.y, 1, 1, "%.0f");
ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar);
@ -3021,7 +3027,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
if (ImGui::BeginTabItem("Rendering"))
{
ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines); ImGui::SameLine(); ShowHelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well.");
ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines); ImGui::SameLine(); HelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well.");
ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill);
ImGui::PushItemWidth(100);
ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, "%.2f", 2.0f);
@ -3695,7 +3701,7 @@ static void ShowExampleAppPropertyEditor(bool* p_open)
return;
}
ShowHelpMarker("This example shows how you may implement a property editor using two columns.\nAll objects/fields data are dummies here.\nRemember that in many simple cases, you can use ImGui::SameLine(xxx) to position\nyour cursor horizontally instead of using the Columns() API.");
HelpMarker("This example shows how you may implement a property editor using two columns.\nAll objects/fields data are dummies here.\nRemember that in many simple cases, you can use ImGui::SameLine(xxx) to position\nyour cursor horizontally instead of using the Columns() API.");
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2,2));
ImGui::Columns(2);

View File

@ -83,6 +83,7 @@ struct ImGuiWindowSettings; // Storage for window settings stored in .in
// Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists.
typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // Enum: Horizontal or vertical
typedef int ImGuiButtonFlags; // -> enum ImGuiButtonFlags_ // Flags: for ButtonEx(), ButtonBehavior()
typedef int ImGuiDragFlags; // -> enum ImGuiDragFlags_ // Flags: for DragBehavior()
typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag()
typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for DC.LastItemStatusFlags
typedef int ImGuiNavHighlightFlags; // -> enum ImGuiNavHighlightFlags_ // Flags: for RenderNavHighlight()
@ -90,7 +91,7 @@ typedef int ImGuiNavDirSourceFlags; // -> enum ImGuiNavDirSourceFlags_ // Flags:
typedef int ImGuiNavMoveFlags; // -> enum ImGuiNavMoveFlags_ // Flags: for navigation requests
typedef int ImGuiSeparatorFlags; // -> enum ImGuiSeparatorFlags_ // Flags: for Separator() - internal
typedef int ImGuiSliderFlags; // -> enum ImGuiSliderFlags_ // Flags: for SliderBehavior()
typedef int ImGuiDragFlags; // -> enum ImGuiDragFlags_ // Flags: for DragBehavior()
typedef int ImGuiTextFlags; // -> enum ImGuiTextFlags_ // Flags: for TextEx()
//-------------------------------------------------------------------------
// STB libraries includes
@ -247,6 +248,7 @@ static inline float ImLengthSqr(const ImVec4& lhs)
static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = lhs.x*lhs.x + lhs.y*lhs.y; if (d > 0.0f) return 1.0f / ImSqrt(d); return fail_value; }
static inline float ImFloor(float f) { return (float)(int)f; }
static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)v.x, (float)(int)v.y); }
static inline int ImModPositive(int a, int b) { return (a + b) % b; }
static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; }
@ -381,6 +383,12 @@ enum ImGuiItemStatusFlags_
#endif
};
enum ImGuiTextFlags_
{
ImGuiTextFlags_None = 0,
ImGuiTextFlags_NoWidthForLargeClippedText = 1 << 0
};
// FIXME: this is in development, not exposed/functional as a generic feature yet.
// Horizontal/Vertical enums are fixed to 0/1 so they may be used to index ImVec2
enum ImGuiLayoutType_
@ -884,6 +892,15 @@ struct ImGuiContext
ImGuiNavMoveResult NavMoveResultLocalVisibleSet; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag)
ImGuiNavMoveResult NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag)
// Tabbing system (older than Nav, active even if Nav is disabled. FIXME-NAV: This needs a redesign!)
ImGuiWindow* FocusRequestCurrWindow; //
ImGuiWindow* FocusRequestNextWindow; //
int FocusRequestCurrCounterAll; // Any item being requested for focus, stored as an index (we on layout to be stable between the frame pressing TAB and the next frame, semi-ouch)
int FocusRequestCurrCounterTab; // Tab item being requested for focus, stored as an index
int FocusRequestNextCounterAll; // Stored for next frame
int FocusRequestNextCounterTab; // "
bool FocusTabPressed; //
// Render
ImDrawData DrawData; // Main ImDrawData instance to pass render information to the user
ImDrawDataBuilder DrawDataBuilder;
@ -1030,6 +1047,11 @@ struct ImGuiContext
NavMoveRequestForward = ImGuiNavForward_None;
NavMoveDir = NavMoveDirLast = NavMoveClipDir = ImGuiDir_None;
FocusRequestCurrWindow = FocusRequestNextWindow = NULL;
FocusRequestCurrCounterAll = FocusRequestCurrCounterTab = INT_MAX;
FocusRequestNextCounterAll = FocusRequestNextCounterTab = INT_MAX;
FocusTabPressed = false;
DimBgRatio = 0.0f;
BackgroundDrawList._Data = &DrawListSharedData;
BackgroundDrawList._OwnerName = "##Background"; // Give it a name for debugging
@ -1115,6 +1137,8 @@ struct IMGUI_API ImGuiWindowTempData
ImGuiStorage* StateStorage;
ImGuiLayoutType LayoutType;
ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin()
int FocusCounterAll; // Counter for focus/tabbing system. Start at -1 and increase as assigned via FocusableItemRegister() (FIXME-NAV: Needs redesign)
int FocusCounterTab; // (same, but only count widgets which you can Tab through)
// We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings.
ImGuiItemFlags ItemFlags; // == ItemFlagsStack.back() [empty == ImGuiItemFlags_Default]
@ -1150,8 +1174,10 @@ struct IMGUI_API ImGuiWindowTempData
MenuBarOffset = ImVec2(0.0f, 0.0f);
StateStorage = NULL;
LayoutType = ParentLayoutType = ImGuiLayoutType_Vertical;
ItemWidth = 0.0f;
FocusCounterAll = FocusCounterTab = -1;
ItemFlags = ImGuiItemFlags_Default_;
ItemWidth = 0.0f;
TextWrapPos = -1.0f;
memset(StackSizesBackup, 0, sizeof(StackSizesBackup));
@ -1236,15 +1262,6 @@ struct IMGUI_API ImGuiWindow
ImGuiID NavLastIds[ImGuiNavLayer_COUNT]; // Last known NavId for this window, per layer (0/1)
ImRect NavRectRel[ImGuiNavLayer_COUNT]; // Reference rectangle, in window relative space
// Navigation / Focus
// FIXME-NAV: Merge all this with the new Nav system, at least the request variables should be moved to ImGuiContext
int FocusIdxAllCounter; // Start at -1 and increase as assigned via FocusItemRegister()
int FocusIdxTabCounter; // (same, but only count widgets which you can Tab through)
int FocusIdxAllRequestCurrent; // Item being requested for focus
int FocusIdxTabRequestCurrent; // Tab-able item being requested for focus
int FocusIdxAllRequestNext; // Item being requested for focus, for next update (relies on layout to be stable between the frame pressing TAB and the next frame)
int FocusIdxTabRequestNext; // "
public:
ImGuiWindow(ImGuiContext* context, const char* name);
~ImGuiWindow();
@ -1414,7 +1431,7 @@ namespace ImGui
IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL);
IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id);
IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged);
IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop = true); // Return true if focus is requested
IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id); // Return true if focus is requested
IMGUI_API void FocusableItemUnregister(ImGuiWindow* window);
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y);
IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
@ -1501,6 +1518,7 @@ namespace ImGui
IMGUI_API void RenderPixelEllipsis(ImDrawList* draw_list, ImVec2 pos, int count, ImU32 col);
// Widgets
IMGUI_API void TextEx(const char* text, const char* text_end = NULL, ImGuiTextFlags flags = 0);
IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0,0), ImGuiButtonFlags flags = 0);
IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos, float radius);
IMGUI_API bool CollapseButton(ImGuiID id, const ImVec2& pos);
@ -1527,7 +1545,7 @@ namespace ImGui
template<typename T, typename SIGNED_T> IMGUI_API T RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, T v);
// InputText
IMGUI_API bool InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format);
// Color

View File

@ -132,7 +132,7 @@ static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const
// - BulletTextV()
//-------------------------------------------------------------------------
void ImGui::TextUnformatted(const char* text, const char* text_end)
void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
@ -146,7 +146,7 @@ void ImGui::TextUnformatted(const char* text, const char* text_end)
const ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrentLineTextBaseOffset);
const float wrap_pos_x = window->DC.TextWrapPos;
const bool wrap_enabled = wrap_pos_x >= 0.0f;
const bool wrap_enabled = (wrap_pos_x >= 0.0f);
if (text_end - text > 2000 && !wrap_enabled)
{
// Long text!
@ -156,69 +156,66 @@ void ImGui::TextUnformatted(const char* text, const char* text_end)
// - We use memchr(), pay attention that well optimized versions of those str/mem functions are much faster than a casually written loop.
const char* line = text;
const float line_height = GetTextLineHeight();
const ImRect clip_rect = window->ClipRect;
ImVec2 text_size(0,0);
if (text_pos.y <= clip_rect.Max.y)
// Lines to skip (can't skip when logging text)
ImVec2 pos = text_pos;
if (!g.LogEnabled)
{
ImVec2 pos = text_pos;
// Lines to skip (can't skip when logging text)
if (!g.LogEnabled)
int lines_skippable = (int)((window->ClipRect.Min.y - text_pos.y) / line_height);
if (lines_skippable > 0)
{
int lines_skippable = (int)((clip_rect.Min.y - text_pos.y) / line_height);
if (lines_skippable > 0)
{
int lines_skipped = 0;
while (line < text_end && lines_skipped < lines_skippable)
{
const char* line_end = (const char*)memchr(line, '\n', text_end - line);
if (!line_end)
line_end = text_end;
line = line_end + 1;
lines_skipped++;
}
pos.y += lines_skipped * line_height;
}
}
// Lines to render
if (line < text_end)
{
ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height));
while (line < text_end)
{
if (IsClippedEx(line_rect, 0, false))
break;
const char* line_end = (const char*)memchr(line, '\n', text_end - line);
if (!line_end)
line_end = text_end;
const ImVec2 line_size = CalcTextSize(line, line_end, false);
text_size.x = ImMax(text_size.x, line_size.x);
RenderText(pos, line, line_end, false);
line = line_end + 1;
line_rect.Min.y += line_height;
line_rect.Max.y += line_height;
pos.y += line_height;
}
// Count remaining lines
int lines_skipped = 0;
while (line < text_end)
while (line < text_end && lines_skipped < lines_skippable)
{
const char* line_end = (const char*)memchr(line, '\n', text_end - line);
if (!line_end)
line_end = text_end;
if ((flags & ImGuiTextFlags_NoWidthForLargeClippedText) == 0)
text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x);
line = line_end + 1;
lines_skipped++;
}
pos.y += lines_skipped * line_height;
}
text_size.y += (pos - text_pos).y;
}
// Lines to render
if (line < text_end)
{
ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height));
while (line < text_end)
{
if (IsClippedEx(line_rect, 0, false))
break;
const char* line_end = (const char*)memchr(line, '\n', text_end - line);
if (!line_end)
line_end = text_end;
text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x);
RenderText(pos, line, line_end, false);
line = line_end + 1;
line_rect.Min.y += line_height;
line_rect.Max.y += line_height;
pos.y += line_height;
}
// Count remaining lines
int lines_skipped = 0;
while (line < text_end)
{
const char* line_end = (const char*)memchr(line, '\n', text_end - line);
if (!line_end)
line_end = text_end;
if ((flags & ImGuiTextFlags_NoWidthForLargeClippedText) == 0)
text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x);
line = line_end + 1;
lines_skipped++;
}
pos.y += lines_skipped * line_height;
}
text_size.y = (pos - text_pos).y;
ImRect bb(text_pos, text_pos + text_size);
ItemSize(text_size);
ItemAdd(bb, 0);
@ -228,7 +225,6 @@ void ImGui::TextUnformatted(const char* text, const char* text_end)
const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f;
const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width);
// Account of baseline offset
ImRect bb(text_pos, text_pos + text_size);
ItemSize(text_size);
if (!ItemAdd(bb, 0))
@ -239,6 +235,11 @@ void ImGui::TextUnformatted(const char* text, const char* text_end)
}
}
void ImGui::TextUnformatted(const char* text, const char* text_end)
{
TextEx(text, text_end, ImGuiTextFlags_NoWidthForLargeClippedText);
}
void ImGui::Text(const char* fmt, ...)
{
va_list args;
@ -255,7 +256,7 @@ void ImGui::TextV(const char* fmt, va_list args)
ImGuiContext& g = *GImGui;
const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
TextUnformatted(g.TempBuffer, text_end);
TextEx(g.TempBuffer, text_end, ImGuiTextFlags_NoWidthForLargeClippedText);
}
void ImGui::TextColored(const ImVec4& col, const char* fmt, ...)
@ -1154,7 +1155,7 @@ void ImGui::Separator()
// Those flags should eventually be overridable by the user
ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal;
IM_ASSERT(ImIsPowerOfTwo((int)(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical)))); // Check that only 1 option is selected
IM_ASSERT(ImIsPowerOfTwo(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical))); // Check that only 1 option is selected
if (flags & ImGuiSeparatorFlags_Vertical)
{
VerticalSeparator();
@ -1949,14 +1950,14 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, floa
// Tabbing or CTRL-clicking on Drag turns it into an input box
bool start_text_input = false;
const bool tab_focus_requested = FocusableItemRegister(window, id);
if (tab_focus_requested || (hovered && (g.IO.MouseClicked[0] || g.IO.MouseDoubleClicked[0])) || g.NavActivateId == id || (g.NavInputId == id && g.ScalarAsInputTextId != id))
const bool focus_requested = FocusableItemRegister(window, id);
if (focus_requested || (hovered && (g.IO.MouseClicked[0] || g.IO.MouseDoubleClicked[0])) || g.NavActivateId == id || (g.NavInputId == id && g.ScalarAsInputTextId != id))
{
SetActiveID(id, window);
SetFocusID(id, window);
FocusWindow(window);
g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
if (tab_focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0] || g.NavInputId == id)
if (focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0] || g.NavInputId == id)
{
start_text_input = true;
g.ScalarAsInputTextId = 0;
@ -2014,7 +2015,7 @@ bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* v, int
}
PopID();
TextUnformatted(label, FindRenderedTextEnd(label));
TextEx(label, FindRenderedTextEnd(label));
EndGroup();
return value_changed;
}
@ -2057,7 +2058,7 @@ bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_cu
PopItemWidth();
SameLine(0, g.Style.ItemInnerSpacing.x);
TextUnformatted(label, FindRenderedTextEnd(label));
TextEx(label, FindRenderedTextEnd(label));
EndGroup();
PopID();
return value_changed;
@ -2102,7 +2103,7 @@ bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_
PopItemWidth();
SameLine(0, g.Style.ItemInnerSpacing.x);
TextUnformatted(label, FindRenderedTextEnd(label));
TextEx(label, FindRenderedTextEnd(label));
EndGroup();
PopID();
@ -2399,15 +2400,15 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, co
// Tabbing or CTRL-clicking on Slider turns it into an input box
bool start_text_input = false;
const bool tab_focus_requested = FocusableItemRegister(window, id);
const bool focus_requested = FocusableItemRegister(window, id);
const bool hovered = ItemHoverable(frame_bb, id);
if (tab_focus_requested || (hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || (g.NavInputId == id && g.ScalarAsInputTextId != id))
if (focus_requested || (hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || (g.NavInputId == id && g.ScalarAsInputTextId != id))
{
SetActiveID(id, window);
SetFocusID(id, window);
FocusWindow(window);
g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
if (tab_focus_requested || g.IO.KeyCtrl || g.NavInputId == id)
if (focus_requested || g.IO.KeyCtrl || g.NavInputId == id)
{
start_text_input = true;
g.ScalarAsInputTextId = 0;
@ -2470,7 +2471,7 @@ bool ImGui::SliderScalarN(const char* label, ImGuiDataType data_type, void* v, i
}
PopID();
TextUnformatted(label, FindRenderedTextEnd(label));
TextEx(label, FindRenderedTextEnd(label));
EndGroup();
return value_changed;
}
@ -2706,7 +2707,7 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const c
DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, data_ptr, format);
ImStrTrimBlanks(data_buf);
ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | ((data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImGuiInputTextFlags_CharsScientific : ImGuiInputTextFlags_CharsDecimal);
bool value_changed = InputTextEx(label, data_buf, IM_ARRAYSIZE(data_buf), bb.GetSize(), flags);
bool value_changed = InputTextEx(label, NULL, data_buf, IM_ARRAYSIZE(data_buf), bb.GetSize(), flags);
if (g.ScalarAsInputTextId == 0)
{
// First frame we started displaying the InputText widget, we expect it to take the active id.
@ -2769,7 +2770,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p
value_changed = true;
}
SameLine(0, style.ItemInnerSpacing.x);
TextUnformatted(label, FindRenderedTextEnd(label));
TextEx(label, FindRenderedTextEnd(label));
style.FramePadding = backup_frame_padding;
PopID();
@ -2807,7 +2808,7 @@ bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* v, in
}
PopID();
TextUnformatted(label, FindRenderedTextEnd(label));
TextEx(label, FindRenderedTextEnd(label));
EndGroup();
return value_changed;
}
@ -2897,9 +2898,10 @@ bool ImGui::InputDouble(const char* label, double* v, double step, double step_f
}
//-------------------------------------------------------------------------
// [SECTION] Widgets: InputText, InputTextMultiline
// [SECTION] Widgets: InputText, InputTextMultiline, InputTextWithHint
//-------------------------------------------------------------------------
// - InputText()
// - InputTextWithHint()
// - InputTextMultiline()
// - InputTextEx() [Internal]
//-------------------------------------------------------------------------
@ -2907,12 +2909,18 @@ bool ImGui::InputDouble(const char* label, double* v, double step, double step_f
bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
{
IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline()
return InputTextEx(label, buf, (int)buf_size, ImVec2(0,0), flags, callback, user_data);
return InputTextEx(label, NULL, buf, (int)buf_size, ImVec2(0,0), flags, callback, user_data);
}
bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
{
return InputTextEx(label, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data);
return InputTextEx(label, NULL, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data);
}
bool ImGui::InputTextWithHint(const char* label, const char* hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
{
IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline()
return InputTextEx(label, hint, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data);
}
static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end)
@ -3207,7 +3215,7 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f
// - If you want to use ImGui::InputText() with std::string, see misc/cpp/imgui_stdlib.h
// (FIXME: Rather confusing and messy function, among the worse part of our codebase, expecting to rewrite a V2 at some point.. Partly because we are
// doing UTF8 > U16 > UTF8 conversions on the go to easily interface with stb_textedit. Ideally should stay in UTF-8 all the time. See https://github.com/nothings/stb/issues/188)
bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* callback_user_data)
bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* callback_user_data)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
@ -3266,30 +3274,13 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
if (hovered)
g.MouseCursor = ImGuiMouseCursor_TextInput;
// Password pushes a temporary font with only a fallback glyph
if (is_password)
{
const ImFontGlyph* glyph = g.Font->FindGlyph('*');
ImFont* password_font = &g.InputTextPasswordFont;
password_font->FontSize = g.Font->FontSize;
password_font->Scale = g.Font->Scale;
password_font->DisplayOffset = g.Font->DisplayOffset;
password_font->Ascent = g.Font->Ascent;
password_font->Descent = g.Font->Descent;
password_font->ContainerAtlas = g.Font->ContainerAtlas;
password_font->FallbackGlyph = glyph;
password_font->FallbackAdvanceX = glyph->AdvanceX;
IM_ASSERT(password_font->Glyphs.empty() && password_font->IndexAdvanceX.empty() && password_font->IndexLookup.empty());
PushFont(password_font);
}
// NB: we are only allowed to access 'edit_state' if we are the active widget.
ImGuiInputTextState* state = NULL;
if (g.InputTextState.ID == id)
state = &g.InputTextState;
const bool focus_requested = FocusableItemRegister(window, id, (flags & (ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_AllowTabInput)) == 0); // Using completion callback disable keyboard tabbing
const bool focus_requested_by_code = focus_requested && (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent);
const bool focus_requested = FocusableItemRegister(window, id);
const bool focus_requested_by_code = focus_requested && (g.FocusRequestCurrWindow == window && g.FocusRequestCurrCounterAll == window->DC.FocusCounterAll);
const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code;
const bool user_clicked = hovered && io.MouseClicked[0];
@ -3351,7 +3342,10 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
SetActiveID(id, window);
SetFocusID(id, window);
FocusWindow(window);
IM_ASSERT(ImGuiNavInput_COUNT < 32);
g.ActiveIdBlockNavInputFlags = (1 << ImGuiNavInput_Cancel);
if (flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_AllowTabInput)) // Disable keyboard tabbing out
g.ActiveIdBlockNavInputFlags |= (1 << ImGuiNavInput_KeyTab_);
if (!is_multiline && !(flags & ImGuiInputTextFlags_CallbackHistory))
g.ActiveIdAllowNavDirFlags = ((1 << ImGuiDir_Up) | (1 << ImGuiDir_Down));
}
@ -3364,10 +3358,6 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
if (g.ActiveId == id && io.MouseClicked[0] && !init_state && !init_make_active) //-V560
clear_active_id = true;
bool value_changed = false;
bool enter_pressed = false;
int backup_current_text_length = 0;
// When read-only we always use the live data passed to the function
// FIXME-OPT: Because our selection/cursor code currently needs the wide text we need to convert it when active, which is not ideal :(
if (is_readonly && state != NULL)
@ -3384,7 +3374,41 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
}
}
// Lock the decision of whether we are going to take the path displaying the cursor or selection
const bool render_cursor = (g.ActiveId == id) || (state && user_scroll_active);
const bool render_selection = state && state->HasSelection() && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor);
bool value_changed = false;
bool enter_pressed = false;
// Select the buffer to render.
const char* buf_display = ((render_cursor || render_selection || g.ActiveId == id) && !is_readonly && state && state->TextAIsValid) ? state->TextA.Data : buf;
const char* buf_display_end = NULL; // We have specialized paths below for setting the length
const bool is_displaying_hint = (hint != NULL && buf_display[0] == 0);
if (is_displaying_hint)
{
buf_display = hint;
buf_display_end = hint + strlen(hint);
}
// Password pushes a temporary font with only a fallback glyph
if (is_password && !is_displaying_hint)
{
const ImFontGlyph* glyph = g.Font->FindGlyph('*');
ImFont* password_font = &g.InputTextPasswordFont;
password_font->FontSize = g.Font->FontSize;
password_font->Scale = g.Font->Scale;
password_font->DisplayOffset = g.Font->DisplayOffset;
password_font->Ascent = g.Font->Ascent;
password_font->Descent = g.Font->Descent;
password_font->ContainerAtlas = g.Font->ContainerAtlas;
password_font->FallbackGlyph = glyph;
password_font->FallbackAdvanceX = glyph->AdvanceX;
IM_ASSERT(password_font->Glyphs.empty() && password_font->IndexAdvanceX.empty() && password_font->IndexLookup.empty());
PushFont(password_font);
}
// Process mouse inputs and character inputs
int backup_current_text_length = 0;
if (g.ActiveId == id)
{
IM_ASSERT(state != NULL);
@ -3731,15 +3755,15 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
// without any carriage return, which would makes ImFont::RenderText() reserve too many vertices and probably crash. Avoid it altogether.
// Note that we only use this limit on single-line InputText(), so a pathologically large line on a InputTextMultiline() would still crash.
const int buf_display_max_length = 2 * 1024 * 1024;
const char* buf_display = NULL;
const char* buf_display_end = NULL;
// Render text. We currently only render selection when the widget is active or while scrolling.
// FIXME: We could remove the '&& render_cursor' to keep rendering selection when inactive.
const bool render_cursor = (g.ActiveId == id) || (state && user_scroll_active);
const bool render_selection = state && state->HasSelection() && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor);
if (render_cursor || render_selection)
{
IM_ASSERT(state != NULL);
if (!is_displaying_hint)
buf_display_end = buf_display + state->CurLenA;
// Render text (with cursor and selection)
// This is going to be messy. We need to:
// - Display the text (this alone can be more easily clipped)
@ -3747,7 +3771,6 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
// - 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)
// FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8.
IM_ASSERT(state != NULL);
const ImWchar* text_begin = state->TextW.Data;
ImVec2 cursor_offset, select_start_offset;
@ -3872,10 +3895,11 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
}
// We test for 'buf_display_max_length' as a way to avoid some pathological cases (e.g. single-line 1 MB string) which would make ImDrawList crash.
buf_display = (!is_readonly && state->TextAIsValid) ? state->TextA.Data : buf;
buf_display_end = buf_display + state->CurLenA;
if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos - draw_scroll, GetColorU32(ImGuiCol_Text), buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect);
{
ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);
draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos - draw_scroll, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect);
}
// Draw blinking cursor
if (render_cursor)
@ -3895,15 +3919,18 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
else
{
// Render text only (no selection, no cursor)
buf_display = (g.ActiveId == id && !is_readonly && state->TextAIsValid) ? state->TextA.Data : buf;
if (is_multiline)
text_size = ImVec2(size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_display_end) * g.FontSize); // We don't need width
else if (g.ActiveId == id)
else if (!is_displaying_hint && g.ActiveId == id)
buf_display_end = buf_display + state->CurLenA;
else
else if (!is_displaying_hint)
buf_display_end = buf_display + strlen(buf_display);
if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos, GetColorU32(ImGuiCol_Text), buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect);
{
ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);
draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect);
}
}
if (is_multiline)
@ -3913,11 +3940,11 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
EndGroup();
}
if (is_password)
if (is_password && !is_displaying_hint)
PopFont();
// Log as text
if (g.LogEnabled && !is_password)
if (g.LogEnabled && !(is_password && !is_displaying_hint))
LogRenderedText(&draw_pos, buf_display, buf_display_end);
if (label_size.x > 0)
@ -4098,7 +4125,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
picker_active_window = g.CurrentWindow;
if (label != label_display_end)
{
TextUnformatted(label, label_display_end);
TextEx(label, label_display_end);
Spacing();
}
ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags__PickerMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar;
@ -4113,7 +4140,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
if (label != label_display_end && !(flags & ImGuiColorEditFlags_NoLabel))
{
SameLine(0, style.ItemInnerSpacing.x);
TextUnformatted(label, label_display_end);
TextEx(label, label_display_end);
}
// Convert back
@ -4254,7 +4281,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
// Read stored options
if (!(flags & ImGuiColorEditFlags__PickerMask))
flags |= ((g.ColorEditOptions & ImGuiColorEditFlags__PickerMask) ? g.ColorEditOptions : ImGuiColorEditFlags__OptionsDefault) & ImGuiColorEditFlags__PickerMask;
IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__PickerMask))); // Check that only 1 is selected
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__PickerMask)); // Check that only 1 is selected
if (!(flags & ImGuiColorEditFlags_NoOptions))
flags |= (g.ColorEditOptions & ImGuiColorEditFlags_AlphaBar);
@ -4373,7 +4400,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
{
if ((flags & ImGuiColorEditFlags_NoSidePreview))
SameLine(0, style.ItemInnerSpacing.x);
TextUnformatted(label, label_display_end);
TextEx(label, label_display_end);
}
}
@ -4601,7 +4628,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, &col, sizeof(float) * 4, ImGuiCond_Once);
ColorButton(desc_id, col, flags);
SameLine();
TextUnformatted("Color");
TextEx("Color");
EndDragDropSource();
}
@ -4625,9 +4652,9 @@ void ImGui::SetColorEditOptions(ImGuiColorEditFlags flags)
flags |= ImGuiColorEditFlags__OptionsDefault & ImGuiColorEditFlags__DataTypeMask;
if ((flags & ImGuiColorEditFlags__PickerMask) == 0)
flags |= ImGuiColorEditFlags__OptionsDefault & ImGuiColorEditFlags__PickerMask;
IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__DisplayMask))); // Check only 1 option is selected
IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__DataTypeMask))); // Check only 1 option is selected
IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__PickerMask))); // Check only 1 option is selected
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__DisplayMask)); // Check only 1 option is selected
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__DataTypeMask)); // Check only 1 option is selected
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__PickerMask)); // Check only 1 option is selected
g.ColorEditOptions = flags;
}
@ -4642,7 +4669,7 @@ void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags
const char* text_end = text ? FindRenderedTextEnd(text, NULL) : text;
if (text_end > text)
{
TextUnformatted(text, text_end);
TextEx(text, text_end);
Separator();
}
@ -5190,7 +5217,20 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
bb.Min.y -= spacing_U;
bb.Max.x += spacing_R;
bb.Max.y += spacing_D;
if (!ItemAdd(bb, id))
bool item_add;
if (flags & ImGuiSelectableFlags_Disabled)
{
ImGuiItemFlags backup_item_flags = window->DC.ItemFlags;
window->DC.ItemFlags |= ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus;
item_add = ItemAdd(bb, id);
window->DC.ItemFlags = backup_item_flags;
}
else
{
item_add = ItemAdd(bb, id);
}
if (!item_add)
{
if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet)
PushColumnClipRect();