1
0
mirror of https://github.com/ocornut/imgui.git synced 2024-11-24 15:50:25 +01:00

Merge branch 'master' into docking

# Conflicts:
#	imgui.cpp
This commit is contained in:
ocornut 2024-09-09 16:54:40 +02:00
commit 7694e89e89
14 changed files with 195 additions and 109 deletions

View File

@ -218,7 +218,7 @@ jobs:
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx12/example_win32_directx12.vcxproj /p:Platform=x64 /p:Configuration=Release' run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx12/example_win32_directx12.vcxproj /p:Platform=x64 /p:Configuration=Release'
Linux: Linux:
runs-on: ubuntu-22.04 runs-on: ubuntu-24.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -324,6 +324,18 @@ jobs:
EOF EOF
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
- name: Build example_null (with C++20)
run: |
cat > example_single_file.cpp <<'EOF'
#define IMGUI_DISABLE_OBSOLETE_KEYIO
#define IMGUI_IMPLEMENTATION
#include "misc/single_file/imgui_single_file.h"
#include "examples/example_null/main.cpp"
EOF
g++ -I. -std=c++20 -Wall -Wformat -o example_single_file example_single_file.cpp
- name: Build example_null (with IMGUI_DISABLE_DEMO_WINDOWS and IMGUI_DISABLE_DEBUG_TOOLS) - name: Build example_null (with IMGUI_DISABLE_DEMO_WINDOWS and IMGUI_DISABLE_DEBUG_TOOLS)
run: | run: |
cat > example_single_file.cpp <<'EOF' cat > example_single_file.cpp <<'EOF'
@ -381,6 +393,18 @@ jobs:
EOF EOF
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
- name: Build example_null (C++26, Clang)
run: |
cat > example_single_file.cpp <<'EOF'
#define IMGUI_IMPLEMENTATION
#define IMGUI_DISABLE_DEMO_WINDOWS
#include "misc/single_file/imgui_single_file.h"
#include "examples/example_null/main.cpp"
EOF
clang++ -I. -std=c++26 -Wall -Wformat -fno-exceptions -fno-threadsafe-statics -lc -lm -o example_single_file example_single_file.cpp
- name: Build example_null (without c++ runtime, Clang) - name: Build example_null (without c++ runtime, Clang)
run: | run: |
cat > example_single_file.cpp <<'EOF' cat > example_single_file.cpp <<'EOF'
@ -433,6 +457,17 @@ jobs:
EOF EOF
clang++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp clang++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
- name: Build example_null (single file build, c++20)
run: |
cat > example_single_file.cpp <<'EOF'
#define IMGUI_IMPLEMENTATION
#include "misc/single_file/imgui_single_file.h"
#include "examples/example_null/main.cpp"
EOF
clang++ -I. -std=c++20 -Wall -Wformat -o example_single_file example_single_file.cpp
- name: Build example_null (without c++ runtime) - name: Build example_null (without c++ runtime)
run: | run: |
cat > example_single_file.cpp <<'EOF' cat > example_single_file.cpp <<'EOF'
@ -481,7 +516,7 @@ jobs:
xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_ios CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_ios CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
Emscripten: Emscripten:
runs-on: ubuntu-22.04 runs-on: ubuntu-24.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -508,7 +543,7 @@ jobs:
make -C examples/example_glfw_wgpu -f Makefile.emscripten make -C examples/example_glfw_wgpu -f Makefile.emscripten
Android: Android:
runs-on: ubuntu-22.04 runs-on: ubuntu-24.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

View File

@ -135,7 +135,7 @@ Generally:
It is unlikely you will add value to your project by creating your own backend. It is unlikely you will add value to your project by creating your own backend.
Also: Also:
The [multi-viewports feature](https://github.com/ocornut/imgui/issues/1542) of the 'docking' branch allows The [multi-viewports feature](https://github.com/ocornut/imgui/wiki/Multi-Viewports) of the 'docking' branch allows
Dear ImGui windows to be seamlessly detached from the main application window. This is achieved using an Dear ImGui windows to be seamlessly detached from the main application window. This is achieved using an
extra layer to the Platform and Renderer backends, which allows Dear ImGui to communicate platform-specific extra layer to the Platform and Renderer backends, which allows Dear ImGui to communicate platform-specific
requests such as: "create an additional OS window", "create a render context", "get the OS position of this requests such as: "create an additional OS window", "create a render context", "get the OS position of this

View File

@ -35,6 +35,18 @@ HOW TO UPDATE?
and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users. and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users.
- Please report any issue! - Please report any issue!
-----------------------------------------------------------------------
VERSION 1.91.2 WIP (In Progress)
-----------------------------------------------------------------------
Breaking changes:
Other changes:
- Nav: pressing any keyboard key while holding Alt disable toggling nav layer on Alt release. (#4439)
- InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow.
- TextLinkOpenURL(): modified tooltip to display a verb "Open 'xxxx'". (#7885, #7660)
----------------------------------------------------------------------- -----------------------------------------------------------------------
VERSION 1.91.1 (Released 2024-09-04) VERSION 1.91.1 (Released 2024-09-04)
----------------------------------------------------------------------- -----------------------------------------------------------------------

View File

@ -77,9 +77,9 @@ or view this file with any Markdown viewer.
### Q: Which version should I get? ### Q: Which version should I get?
I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported. I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported.
You may use the [docking](https://github.com/ocornut/imgui/tree/docking) branch which includes: You may use the ['docking'](https://github.com/ocornut/imgui/tree/docking) branch which includes:
- [Docking features](https://github.com/ocornut/imgui/issues/2109) - [Docking features](https://github.com/ocornut/imgui/wiki/Docking)
- [Multi-viewport features](https://github.com/ocornut/imgui/issues/1542) - [Multi-viewport features](https://github.com/ocornut/imgui/wiki/Multi-Viewports)
Many projects are using this branch and it is kept in sync with master regularly. Many projects are using this branch and it is kept in sync with master regularly.
@ -654,7 +654,7 @@ You may take a look at:
- [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) - [Quotes](https://github.com/ocornut/imgui/wiki/Quotes)
- [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui)
- [Funding & Sponsors](https://github.com/ocornut/imgui/wiki/Funding) - [Funding & Sponsors](https://github.com/ocornut/imgui/wiki/Funding)
- [Gallery](https://github.com/ocornut/imgui/issues/7503) - [Gallery](https://github.com/ocornut/imgui/issues?q=label%3Agallery)
##### [Return to Index](#index) ##### [Return to Index](#index)
@ -700,7 +700,7 @@ There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/ci
- Individuals: you can support continued maintenance and development via PayPal donations. See [README](https://github.com/ocornut/imgui/blob/master/docs/README.md). - Individuals: you can support continued maintenance and development via PayPal donations. See [README](https://github.com/ocornut/imgui/blob/master/docs/README.md).
- If you are experienced with Dear ImGui and C++, look at [GitHub Issues](https://github.com/ocornut/imgui/issues), [GitHub Discussions](https://github.com/ocornut/imgui/discussions), the [Wiki](https://github.com/ocornut/imgui/wiki), read [docs/TODO.txt](https://github.com/ocornut/imgui/blob/master/docs/TODO.txt), and see how you want to help and can help! - If you are experienced with Dear ImGui and C++, look at [GitHub Issues](https://github.com/ocornut/imgui/issues), [GitHub Discussions](https://github.com/ocornut/imgui/discussions), the [Wiki](https://github.com/ocornut/imgui/wiki), read [docs/TODO.txt](https://github.com/ocornut/imgui/blob/master/docs/TODO.txt), and see how you want to help and can help!
- Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere, etc. - Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere, etc.
You may post screenshots or links in the [gallery threads](https://github.com/ocornut/imgui/issues/7503). Visuals are ideal as they inspire other programmers. Disclosing your use of Dear ImGui helps the library grow credibility, and helps other teams and programmers with taking decisions. You may post screenshots or links in the [gallery threads](https://github.com/ocornut/imgui/issues?q=label%3Agallery). Visuals are ideal as they inspire other programmers. Disclosing your use of Dear ImGui helps the library grow credibility, and helps other teams and programmers with taking decisions.
- If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues or sometimes incomplete PR. - If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues or sometimes incomplete PR.
##### [Return to Index](#index) ##### [Return to Index](#index)

View File

@ -141,7 +141,7 @@ Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas.
Examples projects using Dear ImGui: [Tracy](https://github.com/wolfpld/tracy) (profiler), [ImHex](https://github.com/WerWolv/ImHex) (hex editor/data analysis), [RemedyBG](https://remedybg.itch.io/remedybg) (debugger) and [hundreds of others](https://github.com/ocornut/imgui/wiki/Software-using-Dear-ImGui). Examples projects using Dear ImGui: [Tracy](https://github.com/wolfpld/tracy) (profiler), [ImHex](https://github.com/WerWolv/ImHex) (hex editor/data analysis), [RemedyBG](https://remedybg.itch.io/remedybg) (debugger) and [hundreds of others](https://github.com/ocornut/imgui/wiki/Software-using-Dear-ImGui).
For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues/7503)! For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues?q=label%3Agallery)!
For a list of third-party widgets and extensions, check out the [Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page. For a list of third-party widgets and extensions, check out the [Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page.
@ -170,11 +170,11 @@ Private support is available for paying business customers (E-mail: _contact @ d
**Which version should I get?** **Which version should I get?**
We occasionally tag [Releases](https://github.com/ocornut/imgui/releases) (with nice releases notes) but it is generally safe and recommended to sync to latest `master` or `docking` branch. The library is fairly stable and regressions tend to be fixed fast when reported. Advanced users may want to use the `docking` branch with [Multi-Viewport](https://github.com/ocornut/imgui/issues/1542) and [Docking](https://github.com/ocornut/imgui/issues/2109) features. This branch is kept in sync with master regularly. We occasionally tag [Releases](https://github.com/ocornut/imgui/releases) (with nice releases notes) but it is generally safe and recommended to sync to latest `master` or `docking` branch. The library is fairly stable and regressions tend to be fixed fast when reported. Advanced users may want to use the `docking` branch with [Multi-Viewport](https://github.com/ocornut/imgui/wiki/Multi-Viewports) and [Docking](https://github.com/ocornut/imgui/wiki/Docking) features. This branch is kept in sync with master regularly.
**Who uses Dear ImGui?** **Who uses Dear ImGui?**
See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes), [Funding & Sponsors](https://github.com/ocornut/imgui/wiki/Funding), and [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for an idea of who is using Dear ImGui. Please add your game/software if you can! Also, see the [Gallery Threads](https://github.com/ocornut/imgui/issues/7503)! See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes), [Funding & Sponsors](https://github.com/ocornut/imgui/wiki/Funding), and [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for an idea of who is using Dear ImGui. Please add your game/software if you can! Also, see the [Gallery Threads](https://github.com/ocornut/imgui/issues?q=label%3Agallery)!
How to help How to help
----------- -----------

View File

@ -1,6 +1,6 @@
# #
# Cross Platform Makefile # Cross Platform Makefile
# Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X # Compatible with MSYS2/MINGW, Ubuntu 14.04.1+ and Mac OS X
# #
# Important: This is a "null backend" application, with no visible output or interaction! # Important: This is a "null backend" application, with no visible output or interaction!
# This is used for testing purpose and continuous integration, and has little use for end-user. # This is used for testing purpose and continuous integration, and has little use for end-user.

View File

@ -1,4 +1,4 @@
// dear imgui, v1.91.1 // dear imgui, v1.91.2 WIP
// (main code and documentation) // (main code and documentation)
// Help: // Help:
@ -10,7 +10,7 @@
// - FAQ ........................ https://dearimgui.com/faq (in repository as docs/FAQ.md) // - FAQ ........................ https://dearimgui.com/faq (in repository as docs/FAQ.md)
// - Homepage ................... https://github.com/ocornut/imgui // - Homepage ................... https://github.com/ocornut/imgui
// - Releases & changelog ....... https://github.com/ocornut/imgui/releases // - Releases & changelog ....... https://github.com/ocornut/imgui/releases
// - Gallery .................... https://github.com/ocornut/imgui/issues/7503 (please post your screenshots/video there!) // - Gallery .................... https://github.com/ocornut/imgui/issues?q=label%3Agallery (please post your screenshots/video there!)
// - Wiki ....................... https://github.com/ocornut/imgui/wiki (lots of good stuff there) // - Wiki ....................... https://github.com/ocornut/imgui/wiki (lots of good stuff there)
// - Getting Started https://github.com/ocornut/imgui/wiki/Getting-Started (how to integrate in an existing app by adding ~25 lines of code) // - Getting Started https://github.com/ocornut/imgui/wiki/Getting-Started (how to integrate in an existing app by adding ~25 lines of code)
// - Third-party Extensions https://github.com/ocornut/imgui/wiki/Useful-Extensions (ImPlot & many more) // - Third-party Extensions https://github.com/ocornut/imgui/wiki/Useful-Extensions (ImPlot & many more)
@ -3848,7 +3848,7 @@ void ImGui::DestroyContext(ImGuiContext* ctx)
IM_DELETE(ctx); IM_DELETE(ctx);
} }
// IMPORTANT: ###xxx suffixes must be same in ALL languages to allow for automation. // IMPORTANT: interactive elements requires a fixed ###xxx suffix, it must be same in ALL languages to allow for automation.
static const ImGuiLocEntry GLocalizationEntriesEnUS[] = static const ImGuiLocEntry GLocalizationEntriesEnUS[] =
{ {
{ ImGuiLocKey_VersionStr, "Dear ImGui " IMGUI_VERSION " (" IM_STRINGIFY(IMGUI_VERSION_NUM) ")" }, { ImGuiLocKey_VersionStr, "Dear ImGui " IMGUI_VERSION " (" IM_STRINGIFY(IMGUI_VERSION_NUM) ")" },
@ -3859,6 +3859,7 @@ static const ImGuiLocEntry GLocalizationEntriesEnUS[] =
{ ImGuiLocKey_WindowingMainMenuBar, "(Main menu bar)" }, { ImGuiLocKey_WindowingMainMenuBar, "(Main menu bar)" },
{ ImGuiLocKey_WindowingPopup, "(Popup)" }, { ImGuiLocKey_WindowingPopup, "(Popup)" },
{ ImGuiLocKey_WindowingUntitled, "(Untitled)" }, { ImGuiLocKey_WindowingUntitled, "(Untitled)" },
{ ImGuiLocKey_OpenLink_s, "Open '%s'" },
{ ImGuiLocKey_CopyLink, "Copy Link###CopyLink" }, { ImGuiLocKey_CopyLink, "Copy Link###CopyLink" },
{ ImGuiLocKey_DockingHideTabBar, "Hide tab bar###HideTabBar" }, { ImGuiLocKey_DockingHideTabBar, "Hide tab bar###HideTabBar" },
{ ImGuiLocKey_DockingHoldShiftToDock, "Hold SHIFT to enable Docking window." }, { ImGuiLocKey_DockingHoldShiftToDock, "Hold SHIFT to enable Docking window." },
@ -13863,9 +13864,11 @@ static void ImGui::NavUpdateWindowing()
// Keyboard: Press and Release ALT to toggle menu layer // Keyboard: Press and Release ALT to toggle menu layer
const ImGuiKey windowing_toggle_keys[] = { ImGuiKey_LeftAlt, ImGuiKey_RightAlt }; const ImGuiKey windowing_toggle_keys[] = { ImGuiKey_LeftAlt, ImGuiKey_RightAlt };
bool windowing_toggle_layer_start = false;
for (ImGuiKey windowing_toggle_key : windowing_toggle_keys) for (ImGuiKey windowing_toggle_key : windowing_toggle_keys)
if (nav_keyboard_active && IsKeyPressed(windowing_toggle_key, 0, ImGuiKeyOwner_NoOwner)) if (nav_keyboard_active && IsKeyPressed(windowing_toggle_key, 0, ImGuiKeyOwner_NoOwner))
{ {
windowing_toggle_layer_start = true;
g.NavWindowingToggleLayer = true; g.NavWindowingToggleLayer = true;
g.NavWindowingToggleKey = windowing_toggle_key; g.NavWindowingToggleKey = windowing_toggle_key;
g.NavInputSource = ImGuiInputSource_Keyboard; g.NavInputSource = ImGuiInputSource_Keyboard;
@ -13879,7 +13882,9 @@ static void ImGui::NavUpdateWindowing()
// We cancel toggling nav layer if an owner has claimed the key. // We cancel toggling nav layer if an owner has claimed the key.
if (io.InputQueueCharacters.Size > 0 || io.KeyCtrl || io.KeyShift || io.KeySuper) if (io.InputQueueCharacters.Size > 0 || io.KeyCtrl || io.KeyShift || io.KeySuper)
g.NavWindowingToggleLayer = false; g.NavWindowingToggleLayer = false;
if (TestKeyOwner(g.NavWindowingToggleKey, ImGuiKeyOwner_NoOwner) == false || TestKeyOwner(ImGuiMod_Alt, ImGuiKeyOwner_NoOwner) == false) else if (windowing_toggle_layer_start == false && g.LastKeyboardKeyPressTime == g.Time)
g.NavWindowingToggleLayer = false;
else if (TestKeyOwner(g.NavWindowingToggleKey, ImGuiKeyOwner_NoOwner) == false || TestKeyOwner(ImGuiMod_Alt, ImGuiKeyOwner_NoOwner) == false)
g.NavWindowingToggleLayer = false; g.NavWindowingToggleLayer = false;
// Apply layer toggle on Alt release // Apply layer toggle on Alt release

View File

@ -1,4 +1,4 @@
// dear imgui, v1.91.1 // dear imgui, v1.91.2 WIP
// (headers) // (headers)
// Help: // Help:
@ -11,7 +11,7 @@
// - FAQ ........................ https://dearimgui.com/faq (in repository as docs/FAQ.md) // - FAQ ........................ https://dearimgui.com/faq (in repository as docs/FAQ.md)
// - Homepage ................... https://github.com/ocornut/imgui // - Homepage ................... https://github.com/ocornut/imgui
// - Releases & changelog ....... https://github.com/ocornut/imgui/releases // - Releases & changelog ....... https://github.com/ocornut/imgui/releases
// - Gallery .................... https://github.com/ocornut/imgui/issues/7503 (please post your screenshots/video there!) // - Gallery .................... https://github.com/ocornut/imgui/issues?q=label%3Agallery (please post your screenshots/video there!)
// - Wiki ....................... https://github.com/ocornut/imgui/wiki (lots of good stuff there) // - Wiki ....................... https://github.com/ocornut/imgui/wiki (lots of good stuff there)
// - Getting Started https://github.com/ocornut/imgui/wiki/Getting-Started (how to integrate in an existing app by adding ~25 lines of code) // - Getting Started https://github.com/ocornut/imgui/wiki/Getting-Started (how to integrate in an existing app by adding ~25 lines of code)
// - Third-party Extensions https://github.com/ocornut/imgui/wiki/Useful-Extensions (ImPlot & many more) // - Third-party Extensions https://github.com/ocornut/imgui/wiki/Useful-Extensions (ImPlot & many more)
@ -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.1" #define IMGUI_VERSION "1.91.2 WIP"
#define IMGUI_VERSION_NUM 19110 #define IMGUI_VERSION_NUM 19112
#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

View File

@ -1,4 +1,4 @@
// dear imgui, v1.91.1 // dear imgui, v1.91.2 WIP
// (demo code) // (demo code)
// Help: // Help:

View File

@ -1,4 +1,4 @@
// dear imgui, v1.91.1 // dear imgui, v1.91.2 WIP
// (drawing and font code) // (drawing and font code)
/* /*

View File

@ -1,4 +1,4 @@
// dear imgui, v1.91.1 // dear imgui, v1.91.2 WIP
// (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.
@ -204,24 +204,6 @@ typedef void (*ImGuiErrorLogCallback)(void* user_data, const char* fmt, ...);
extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
#endif #endif
//-------------------------------------------------------------------------
// [SECTION] STB libraries includes
//-------------------------------------------------------------------------
namespace ImStb
{
#undef IMSTB_TEXTEDIT_STRING
#undef IMSTB_TEXTEDIT_CHARTYPE
#define IMSTB_TEXTEDIT_STRING ImGuiInputTextState
#define IMSTB_TEXTEDIT_CHARTYPE ImWchar
#define IMSTB_TEXTEDIT_GETWIDTH_NEWLINE (-1.0f)
#define IMSTB_TEXTEDIT_UNDOSTATECOUNT 99
#define IMSTB_TEXTEDIT_UNDOCHARCOUNT 999
#include "imstb_textedit.h"
} // namespace ImStb
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Macros // [SECTION] Macros
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1121,11 +1103,24 @@ struct IMGUI_API ImGuiInputTextDeactivatedState
ImGuiInputTextDeactivatedState() { memset(this, 0, sizeof(*this)); } ImGuiInputTextDeactivatedState() { memset(this, 0, sizeof(*this)); }
void ClearFreeMemory() { ID = 0; TextA.clear(); } void ClearFreeMemory() { ID = 0; TextA.clear(); }
}; };
// Forward declare imstb_textedit.h structure + make its main configuration define accessible
#undef IMSTB_TEXTEDIT_STRING
#undef IMSTB_TEXTEDIT_CHARTYPE
#define IMSTB_TEXTEDIT_STRING ImGuiInputTextState
#define IMSTB_TEXTEDIT_CHARTYPE ImWchar
#define IMSTB_TEXTEDIT_GETWIDTH_NEWLINE (-1.0f)
#define IMSTB_TEXTEDIT_UNDOSTATECOUNT 99
#define IMSTB_TEXTEDIT_UNDOCHARCOUNT 999
namespace ImStb { struct STB_TexteditState; }
typedef ImStb::STB_TexteditState ImStbTexteditState;
// Internal state of the currently focused/edited text input box // Internal state of the currently focused/edited text input box
// For a given item ID, access with ImGui::GetInputTextState() // For a given item ID, access with ImGui::GetInputTextState()
struct IMGUI_API ImGuiInputTextState 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
ImGuiID ID; // widget id owning the text state ImGuiID ID; // widget id owning the text state
int CurLenW, CurLenA; // we need to maintain our buffer length in both UTF-8 and wchar format. UTF-8 length is valid even if TextA is not. int CurLenW, CurLenA; // we need to maintain our buffer length in both UTF-8 and wchar format. UTF-8 length is valid even if TextA is not.
ImVector<ImWchar> TextW; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer. ImVector<ImWchar> TextW; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer.
@ -1134,7 +1129,6 @@ struct IMGUI_API ImGuiInputTextState
bool TextAIsValid; // temporary UTF8 buffer is not initially valid before we make the widget active (until then we pull the data from user argument) bool TextAIsValid; // temporary UTF8 buffer is not initially valid before we make the widget active (until then we pull the data from user argument)
int BufCapacityA; // end-user buffer capacity int BufCapacityA; // end-user buffer capacity
ImVec2 Scroll; // horizontal offset (managed manually) + vertical scrolling (pulled from child window's own Scroll.y) ImVec2 Scroll; // horizontal offset (managed manually) + vertical scrolling (pulled from child window's own Scroll.y)
ImStb::STB_TexteditState Stb; // state for stb_textedit.h
float CursorAnim; // timer for cursor blink, reset on every user action so the cursor reappears immediately float CursorAnim; // timer for cursor blink, reset on every user action so the cursor reappears immediately
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
@ -1144,32 +1138,30 @@ struct IMGUI_API ImGuiInputTextState
int ReloadSelectionStart; // POSITIONS ARE IN IMWCHAR units *NOT* UTF-8 this is why this is not exposed yet. int ReloadSelectionStart; // POSITIONS ARE IN IMWCHAR units *NOT* UTF-8 this is why this is not exposed yet.
int ReloadSelectionEnd; int ReloadSelectionEnd;
ImGuiInputTextState() { memset(this, 0, sizeof(*this)); } ImGuiInputTextState();
~ImGuiInputTextState();
void ClearText() { CurLenW = CurLenA = 0; TextW[0] = 0; TextA[0] = 0; CursorClamp(); } void ClearText() { CurLenW = CurLenA = 0; TextW[0] = 0; TextA[0] = 0; CursorClamp(); }
void ClearFreeMemory() { TextW.clear(); TextA.clear(); InitialTextA.clear(); } void ClearFreeMemory() { TextW.clear(); TextA.clear(); InitialTextA.clear(); }
int GetUndoAvailCount() const { return Stb.undostate.undo_point; }
int GetRedoAvailCount() const { return IMSTB_TEXTEDIT_UNDOSTATECOUNT - Stb.undostate.redo_point; }
void OnKeyPressed(int key); // Cannot be inline because we call in code in stb_textedit.h implementation void OnKeyPressed(int key); // Cannot be inline because we call in code in stb_textedit.h implementation
// Cursor & Selection // Cursor & Selection
void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking void CursorAnimReset();
void CursorClamp() { Stb.cursor = ImMin(Stb.cursor, CurLenW); Stb.select_start = ImMin(Stb.select_start, CurLenW); Stb.select_end = ImMin(Stb.select_end, CurLenW); } void CursorClamp();
bool HasSelection() const { return Stb.select_start != Stb.select_end; } bool HasSelection() const;
void ClearSelection() { Stb.select_start = Stb.select_end = Stb.cursor; } void ClearSelection();
int GetCursorPos() const { return Stb.cursor; } int GetCursorPos() const;
int GetSelectionStart() const { return Stb.select_start; } int GetSelectionStart() const;
int GetSelectionEnd() const { return Stb.select_end; } int GetSelectionEnd() const;
void SelectAll() { Stb.select_start = 0; Stb.cursor = Stb.select_end = CurLenW; Stb.has_preferred_x = 0; } void SelectAll();
// Reload user buf (WIP #2890) // Reload user buf (WIP #2890)
// If you modify underlying user-passed const char* while active you need to call this (InputText V2 may lift this) // If you modify underlying user-passed const char* while active you need to call this (InputText V2 may lift this)
// strcpy(my_buf, "hello"); // strcpy(my_buf, "hello");
// if (ImGuiInputTextState* state = ImGui::GetInputTextState(id)) // id may be ImGui::GetItemID() is last item // if (ImGuiInputTextState* state = ImGui::GetInputTextState(id)) // id may be ImGui::GetItemID() is last item
// state->ReloadUserBufAndSelectAll(); // state->ReloadUserBufAndSelectAll();
void ReloadUserBufAndSelectAll() { ReloadUserBuf = true; ReloadSelectionStart = 0; ReloadSelectionEnd = INT_MAX; } void ReloadUserBufAndSelectAll();
void ReloadUserBufAndKeepSelection() { ReloadUserBuf = true; ReloadSelectionStart = Stb.select_start; ReloadSelectionEnd = Stb.select_end; } void ReloadUserBufAndKeepSelection();
void ReloadUserBufAndMoveToEnd() { ReloadUserBuf = true; ReloadSelectionStart = ReloadSelectionEnd = INT_MAX; } void ReloadUserBufAndMoveToEnd();
}; };
enum ImGuiWindowRefreshFlags_ enum ImGuiWindowRefreshFlags_
@ -2068,6 +2060,7 @@ enum ImGuiLocKey : int
ImGuiLocKey_WindowingMainMenuBar, ImGuiLocKey_WindowingMainMenuBar,
ImGuiLocKey_WindowingPopup, ImGuiLocKey_WindowingPopup,
ImGuiLocKey_WindowingUntitled, ImGuiLocKey_WindowingUntitled,
ImGuiLocKey_OpenLink_s,
ImGuiLocKey_CopyLink, ImGuiLocKey_CopyLink,
ImGuiLocKey_DockingHideTabBar, ImGuiLocKey_DockingHideTabBar,
ImGuiLocKey_DockingHoldShiftToDock, ImGuiLocKey_DockingHoldShiftToDock,

View File

@ -1,4 +1,4 @@
// dear imgui, v1.91.1 // dear imgui, v1.91.2 WIP
// (tables and columns code) // (tables and columns code)
/* /*

View File

@ -1,4 +1,4 @@
// dear imgui, v1.91.1 // dear imgui, v1.91.2 WIP
// (widgets code) // (widgets code)
/* /*
@ -1466,7 +1466,7 @@ void ImGui::TextLinkOpenURL(const char* label, const char* url)
if (TextLink(label)) if (TextLink(label))
if (g.PlatformIO.Platform_OpenInShellFn != NULL) if (g.PlatformIO.Platform_OpenInShellFn != NULL)
g.PlatformIO.Platform_OpenInShellFn(&g, url); g.PlatformIO.Platform_OpenInShellFn(&g, url);
SetItemTooltip("%s", url); // It is more reassuring for user to _always_ display URL when we same as label SetItemTooltip(LocalizeGetMsg(ImGuiLocKey_OpenLink_s), url); // It is more reassuring for user to _always_ display URL when we same as label
if (BeginPopupContextItem()) if (BeginPopupContextItem())
{ {
if (MenuItem(LocalizeGetMsg(ImGuiLocKey_CopyLink))) if (MenuItem(LocalizeGetMsg(ImGuiLocKey_CopyLink)))
@ -3792,6 +3792,7 @@ bool ImGui::InputDouble(const char* label, double* v, double step, double step_f
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// [SECTION] Widgets: InputText, InputTextMultiline, InputTextWithHint // [SECTION] Widgets: InputText, InputTextMultiline, InputTextWithHint
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// - imstb_textedit.h include
// - InputText() // - InputText()
// - InputTextWithHint() // - InputTextWithHint()
// - InputTextMultiline() // - InputTextMultiline()
@ -3802,6 +3803,11 @@ bool ImGui::InputDouble(const char* label, double* v, double step, double step_f
// - DebugNodeInputTextState() [Internal] // - DebugNodeInputTextState() [Internal]
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
namespace ImStb
{
#include "imstb_textedit.h"
}
bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) 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() IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline()
@ -3900,9 +3906,18 @@ static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* ob
r->num_chars = (int)(text_remaining - (text + line_start_idx)); r->num_chars = (int)(text_remaining - (text + line_start_idx));
} }
static bool is_separator(unsigned int c) static bool ImCharIsSeparatorW(unsigned int c)
{ {
return c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|' || c=='\n' || c=='\r' || c=='.' || c=='!' || c=='\\' || c=='/'; static const unsigned int separator_list[] =
{
',', 0x3001, '.', 0x3002, ';', 0xFF1B, '(', 0xFF08, ')', 0xFF09, '{', 0xFF5B, '}', 0xFF5D,
'[', 0x300C, ']', 0x300D, '|', 0xFF5C, '!', 0xFF01, '\\', 0xFFE5, '/', 0x30FB, 0xFF0F,
'\n', '\r',
};
for (unsigned int separator : separator_list)
if (c == separator)
return true;
return false;
} }
static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx) static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx)
@ -3912,9 +3927,9 @@ static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx)
return 0; return 0;
bool prev_white = ImCharIsBlankW(obj->TextW[idx - 1]); bool prev_white = ImCharIsBlankW(obj->TextW[idx - 1]);
bool prev_separ = is_separator(obj->TextW[idx - 1]); bool prev_separ = ImCharIsSeparatorW(obj->TextW[idx - 1]);
bool curr_white = ImCharIsBlankW(obj->TextW[idx]); bool curr_white = ImCharIsBlankW(obj->TextW[idx]);
bool curr_separ = is_separator(obj->TextW[idx]); bool curr_separ = ImCharIsSeparatorW(obj->TextW[idx]);
return ((prev_white || prev_separ) && !(curr_separ || curr_white)) || (curr_separ && !prev_separ); return ((prev_white || prev_separ) && !(curr_separ || curr_white)) || (curr_separ && !prev_separ);
} }
static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx) static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx)
@ -3923,9 +3938,9 @@ static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx)
return 0; return 0;
bool prev_white = ImCharIsBlankW(obj->TextW[idx]); bool prev_white = ImCharIsBlankW(obj->TextW[idx]);
bool prev_separ = is_separator(obj->TextW[idx]); bool prev_separ = ImCharIsSeparatorW(obj->TextW[idx]);
bool curr_white = ImCharIsBlankW(obj->TextW[idx - 1]); bool curr_white = ImCharIsBlankW(obj->TextW[idx - 1]);
bool curr_separ = is_separator(obj->TextW[idx - 1]); bool curr_separ = ImCharIsSeparatorW(obj->TextW[idx - 1]);
return ((prev_white) && !(curr_separ || curr_white)) || (curr_separ && !prev_separ); return ((prev_white) && !(curr_separ || curr_white)) || (curr_separ && !prev_separ);
} }
static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; } static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
@ -4026,13 +4041,38 @@ static void stb_textedit_replace(ImGuiInputTextState* str, STB_TexteditState* st
} // namespace ImStb } // namespace ImStb
// We added an extra indirection where 'Stb' is heap-allocated, in order facilitate the work of bindings generators.
ImGuiInputTextState::ImGuiInputTextState()
{
memset(this, 0, sizeof(*this));
Stb = IM_NEW(ImStbTexteditState);
}
ImGuiInputTextState::~ImGuiInputTextState()
{
IM_DELETE(Stb);
}
void ImGuiInputTextState::OnKeyPressed(int key) void ImGuiInputTextState::OnKeyPressed(int key)
{ {
stb_textedit_key(this, &Stb, key); stb_textedit_key(this, Stb, key);
CursorFollow = true; CursorFollow = true;
CursorAnimReset(); CursorAnimReset();
} }
// Those functions are not inlined in imgui_internal.h, allowing us to hide ImStbTexteditState from that header.
void ImGuiInputTextState::CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking
void ImGuiInputTextState::CursorClamp() { Stb->cursor = ImMin(Stb->cursor, CurLenW); Stb->select_start = ImMin(Stb->select_start, CurLenW); Stb->select_end = ImMin(Stb->select_end, CurLenW); }
bool ImGuiInputTextState::HasSelection() const { return Stb->select_start != Stb->select_end; }
void ImGuiInputTextState::ClearSelection() { Stb->select_start = Stb->select_end = Stb->cursor; }
int ImGuiInputTextState::GetCursorPos() const { return Stb->cursor; }
int ImGuiInputTextState::GetSelectionStart() const { return Stb->select_start; }
int ImGuiInputTextState::GetSelectionEnd() const { return Stb->select_end; }
void ImGuiInputTextState::SelectAll() { Stb->select_start = 0; Stb->cursor = Stb->select_end = CurLenW; Stb->has_preferred_x = 0; }
void ImGuiInputTextState::ReloadUserBufAndSelectAll() { ReloadUserBuf = true; ReloadSelectionStart = 0; ReloadSelectionEnd = INT_MAX; }
void ImGuiInputTextState::ReloadUserBufAndKeepSelection() { ReloadUserBuf = true; ReloadSelectionStart = Stb->select_start; ReloadSelectionEnd = Stb->select_end; }
void ImGuiInputTextState::ReloadUserBufAndMoveToEnd() { ReloadUserBuf = true; ReloadSelectionStart = ReloadSelectionEnd = INT_MAX; }
ImGuiInputTextCallbackData::ImGuiInputTextCallbackData() ImGuiInputTextCallbackData::ImGuiInputTextCallbackData()
{ {
memset(this, 0, sizeof(*this)); memset(this, 0, sizeof(*this));
@ -4226,7 +4266,7 @@ static void InputTextReconcileUndoStateAfterUserCallback(ImGuiInputTextState* st
const int insert_len = new_last_diff - first_diff + 1; const int insert_len = new_last_diff - first_diff + 1;
const int delete_len = old_last_diff - first_diff + 1; const int delete_len = old_last_diff - first_diff + 1;
if (insert_len > 0 || delete_len > 0) if (insert_len > 0 || delete_len > 0)
if (IMSTB_TEXTEDIT_CHARTYPE* p = stb_text_createundo(&state->Stb.undostate, first_diff, delete_len, insert_len)) if (IMSTB_TEXTEDIT_CHARTYPE* p = stb_text_createundo(&state->Stb->undostate, first_diff, delete_len, insert_len))
for (int i = 0; i < delete_len; i++) for (int i = 0; i < delete_len; i++)
p[i] = ImStb::STB_TEXTEDIT_GETCHAR(state, first_diff + i); p[i] = ImStb::STB_TEXTEDIT_GETCHAR(state, first_diff + i);
} }
@ -4368,7 +4408,7 @@ 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->ReloadUserBuf);
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_state && g.ActiveId != id) || init_changed_specs || init_reload_from_user_buf)
@ -4414,13 +4454,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
else else
{ {
state->Scroll = ImVec2(0.0f, 0.0f); state->Scroll = ImVec2(0.0f, 0.0f);
stb_textedit_initialize_state(&state->Stb, !is_multiline); stb_textedit_initialize_state(state->Stb, !is_multiline);
} }
if (init_reload_from_user_buf) if (init_reload_from_user_buf)
{ {
state->Stb.select_start = state->ReloadSelectionStart; state->Stb->select_start = state->ReloadSelectionStart;
state->Stb.cursor = state->Stb.select_end = state->ReloadSelectionEnd; state->Stb->cursor = state->Stb->select_end = state->ReloadSelectionEnd;
state->CursorClamp(); state->CursorClamp();
} }
else if (!is_multiline) else if (!is_multiline)
@ -4434,7 +4474,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
} }
if (flags & ImGuiInputTextFlags_AlwaysOverwrite) if (flags & ImGuiInputTextFlags_AlwaysOverwrite)
state->Stb.insert_mode = 1; // stb field name is indeed incorrect (see #2863) state->Stb->insert_mode = 1; // stb field name is indeed incorrect (see #2863)
} }
const bool is_osx = io.ConfigMacOSXBehaviors; const bool is_osx = io.ConfigMacOSXBehaviors;
@ -4542,34 +4582,34 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
} }
else if (hovered && io.MouseClickedCount[0] >= 2 && !io.KeyShift) else if (hovered && io.MouseClickedCount[0] >= 2 && !io.KeyShift)
{ {
stb_textedit_click(state, &state->Stb, mouse_x, mouse_y); stb_textedit_click(state, state->Stb, mouse_x, mouse_y);
const int multiclick_count = (io.MouseClickedCount[0] - 2); const int multiclick_count = (io.MouseClickedCount[0] - 2);
if ((multiclick_count % 2) == 0) if ((multiclick_count % 2) == 0)
{ {
// Double-click: Select word // Double-click: Select word
// We always use the "Mac" word advance for double-click select vs CTRL+Right which use the platform dependent variant: // We always use the "Mac" word advance for double-click select vs CTRL+Right which use the platform dependent variant:
// FIXME: There are likely many ways to improve this behavior, but there's no "right" behavior (depends on use-case, software, OS) // FIXME: There are likely many ways to improve this behavior, but there's no "right" behavior (depends on use-case, software, OS)
const bool is_bol = (state->Stb.cursor == 0) || ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb.cursor - 1) == '\n'; const bool is_bol = (state->Stb->cursor == 0) || ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb->cursor - 1) == '\n';
if (STB_TEXT_HAS_SELECTION(&state->Stb) || !is_bol) if (STB_TEXT_HAS_SELECTION(state->Stb) || !is_bol)
state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT); state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT);
//state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT); //state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT);
if (!STB_TEXT_HAS_SELECTION(&state->Stb)) if (!STB_TEXT_HAS_SELECTION(state->Stb))
ImStb::stb_textedit_prep_selection_at_cursor(&state->Stb); ImStb::stb_textedit_prep_selection_at_cursor(state->Stb);
state->Stb.cursor = ImStb::STB_TEXTEDIT_MOVEWORDRIGHT_MAC(state, state->Stb.cursor); state->Stb->cursor = ImStb::STB_TEXTEDIT_MOVEWORDRIGHT_MAC(state, state->Stb->cursor);
state->Stb.select_end = state->Stb.cursor; state->Stb->select_end = state->Stb->cursor;
ImStb::stb_textedit_clamp(state, &state->Stb); ImStb::stb_textedit_clamp(state, state->Stb);
} }
else else
{ {
// Triple-click: Select line // Triple-click: Select line
const bool is_eol = ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb.cursor) == '\n'; const bool is_eol = ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb->cursor) == '\n';
state->OnKeyPressed(STB_TEXTEDIT_K_LINESTART); state->OnKeyPressed(STB_TEXTEDIT_K_LINESTART);
state->OnKeyPressed(STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT); state->OnKeyPressed(STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT);
state->OnKeyPressed(STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT); state->OnKeyPressed(STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT);
if (!is_eol && is_multiline) if (!is_eol && is_multiline)
{ {
ImSwap(state->Stb.select_start, state->Stb.select_end); ImSwap(state->Stb->select_start, state->Stb->select_end);
state->Stb.cursor = state->Stb.select_end; state->Stb->cursor = state->Stb->select_end;
} }
state->CursorFollow = false; state->CursorFollow = false;
} }
@ -4580,15 +4620,15 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (hovered) if (hovered)
{ {
if (io.KeyShift) if (io.KeyShift)
stb_textedit_drag(state, &state->Stb, mouse_x, mouse_y); stb_textedit_drag(state, state->Stb, mouse_x, mouse_y);
else else
stb_textedit_click(state, &state->Stb, mouse_x, mouse_y); stb_textedit_click(state, state->Stb, mouse_x, mouse_y);
state->CursorAnimReset(); state->CursorAnimReset();
} }
} }
else if (io.MouseDown[0] && !state->SelectedAllMouseLock && (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f)) else if (io.MouseDown[0] && !state->SelectedAllMouseLock && (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f))
{ {
stb_textedit_drag(state, &state->Stb, mouse_x, mouse_y); stb_textedit_drag(state, state->Stb, mouse_x, mouse_y);
state->CursorAnimReset(); state->CursorAnimReset();
state->CursorFollow = true; state->CursorFollow = true;
} }
@ -4641,7 +4681,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
IM_ASSERT(state != NULL); IM_ASSERT(state != NULL);
const int row_count_per_page = ImMax((int)((inner_size.y - style.FramePadding.y) / g.FontSize), 1); const int row_count_per_page = ImMax((int)((inner_size.y - style.FramePadding.y) / g.FontSize), 1);
state->Stb.row_count_per_page = row_count_per_page; state->Stb->row_count_per_page = row_count_per_page;
const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0); const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0);
const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl
@ -4748,8 +4788,8 @@ 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)
{ {
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->CurLenW; const int ie = state->HasSelection() ? ImMax(state->Stb->select_start, state->Stb->select_end) : state->CurLenW;
const int clipboard_data_len = ImTextCountUtf8BytesFromStr(state->TextW.Data + ib, state->TextW.Data + ie) + 1; const int clipboard_data_len = ImTextCountUtf8BytesFromStr(state->TextW.Data + ib, state->TextW.Data + ie) + 1;
char* clipboard_data = (char*)IM_ALLOC(clipboard_data_len * sizeof(char)); char* clipboard_data = (char*)IM_ALLOC(clipboard_data_len * sizeof(char));
ImTextStrToUtf8(clipboard_data, clipboard_data_len, state->TextW.Data + ib, state->TextW.Data + ie); ImTextStrToUtf8(clipboard_data, clipboard_data_len, state->TextW.Data + ib, state->TextW.Data + ie);
@ -4761,7 +4801,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (!state->HasSelection()) if (!state->HasSelection())
state->SelectAll(); state->SelectAll();
state->CursorFollow = true; state->CursorFollow = true;
stb_textedit_cut(state, &state->Stb); stb_textedit_cut(state, state->Stb);
} }
} }
else if (is_paste) else if (is_paste)
@ -4783,7 +4823,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
clipboard_filtered[clipboard_filtered_len] = 0; clipboard_filtered[clipboard_filtered_len] = 0;
if (clipboard_filtered_len > 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); stb_textedit_paste(state, state->Stb, clipboard_filtered, clipboard_filtered_len);
state->CursorFollow = true; state->CursorFollow = true;
} }
MemFree(clipboard_filtered); MemFree(clipboard_filtered);
@ -4810,7 +4850,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
apply_new_text_length = 0; apply_new_text_length = 0;
value_changed = true; value_changed = true;
IMSTB_TEXTEDIT_CHARTYPE empty_string; IMSTB_TEXTEDIT_CHARTYPE empty_string;
stb_textedit_replace(state, &state->Stb, &empty_string, 0); stb_textedit_replace(state, state->Stb, &empty_string, 0);
} }
else if (strcmp(buf, state->InitialTextA.Data) != 0) else if (strcmp(buf, state->InitialTextA.Data) != 0)
{ {
@ -4825,7 +4865,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
w_text.resize(ImTextCountCharsFromUtf8(apply_new_text, apply_new_text + apply_new_text_length) + 1); w_text.resize(ImTextCountCharsFromUtf8(apply_new_text, apply_new_text + apply_new_text_length) + 1);
ImTextStrFromUtf8(w_text.Data, w_text.Size, apply_new_text, apply_new_text + apply_new_text_length); ImTextStrFromUtf8(w_text.Data, w_text.Size, apply_new_text, apply_new_text + apply_new_text_length);
} }
stb_textedit_replace(state, &state->Stb, w_text.Data, (apply_new_text_length > 0) ? (w_text.Size - 1) : 0); stb_textedit_replace(state, state->Stb, w_text.Data, (apply_new_text_length > 0) ? (w_text.Size - 1) : 0);
} }
} }
@ -4900,9 +4940,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// We have to convert from wchar-positions to UTF-8-positions, which can be pretty slow (an incentive to ditch the ImWchar buffer, see https://github.com/nothings/stb/issues/188) // We have to convert from wchar-positions to UTF-8-positions, which can be pretty slow (an incentive to ditch the ImWchar buffer, see https://github.com/nothings/stb/issues/188)
ImWchar* text = state->TextW.Data; ImWchar* text = state->TextW.Data;
const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(text, text + state->Stb.cursor); const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(text, text + state->Stb->cursor);
const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(text, text + state->Stb.select_start); const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(text, text + state->Stb->select_start);
const int utf8_selection_end = callback_data.SelectionEnd = ImTextCountUtf8BytesFromStr(text, text + state->Stb.select_end); const int utf8_selection_end = callback_data.SelectionEnd = ImTextCountUtf8BytesFromStr(text, text + state->Stb->select_end);
// Call user code // Call user code
callback(&callback_data); callback(&callback_data);
@ -4913,9 +4953,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
IM_ASSERT(callback_data.BufSize == state->BufCapacityA); IM_ASSERT(callback_data.BufSize == state->BufCapacityA);
IM_ASSERT(callback_data.Flags == flags); IM_ASSERT(callback_data.Flags == flags);
const bool buf_dirty = callback_data.BufDirty; const bool buf_dirty = callback_data.BufDirty;
if (callback_data.CursorPos != utf8_cursor_pos || buf_dirty) { state->Stb.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); state->CursorFollow = true; } if (callback_data.CursorPos != utf8_cursor_pos || buf_dirty) { state->Stb->cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); state->CursorFollow = true; }
if (callback_data.SelectionStart != utf8_selection_start || buf_dirty) { state->Stb.select_start = (callback_data.SelectionStart == callback_data.CursorPos) ? state->Stb.cursor : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart); } if (callback_data.SelectionStart != utf8_selection_start || buf_dirty) { state->Stb->select_start = (callback_data.SelectionStart == callback_data.CursorPos) ? state->Stb->cursor : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart); }
if (callback_data.SelectionEnd != utf8_selection_end || buf_dirty) { state->Stb.select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb.select_start : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); } if (callback_data.SelectionEnd != utf8_selection_end || buf_dirty) { state->Stb->select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb->select_start : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); }
if (buf_dirty) if (buf_dirty)
{ {
// 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.
@ -5037,13 +5077,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
int searches_remaining = 0; int searches_remaining = 0;
if (render_cursor) if (render_cursor)
{ {
searches_input_ptr[0] = text_begin + state->Stb.cursor; searches_input_ptr[0] = text_begin + state->Stb->cursor;
searches_result_line_no[0] = -1; searches_result_line_no[0] = -1;
searches_remaining++; searches_remaining++;
} }
if (render_selection) if (render_selection)
{ {
searches_input_ptr[1] = text_begin + ImMin(state->Stb.select_start, state->Stb.select_end); searches_input_ptr[1] = text_begin + ImMin(state->Stb->select_start, state->Stb->select_end);
searches_result_line_no[1] = -1; searches_result_line_no[1] = -1;
searches_remaining++; searches_remaining++;
} }
@ -5119,8 +5159,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
const ImVec2 draw_scroll = ImVec2(state->Scroll.x, 0.0f); const ImVec2 draw_scroll = ImVec2(state->Scroll.x, 0.0f);
if (render_selection) if (render_selection)
{ {
const ImWchar* text_selected_begin = text_begin + ImMin(state->Stb.select_start, state->Stb.select_end); const ImWchar* text_selected_begin = text_begin + ImMin(state->Stb->select_start, state->Stb->select_end);
const ImWchar* text_selected_end = text_begin + ImMax(state->Stb.select_start, state->Stb.select_end); const ImWchar* text_selected_end = text_begin + ImMax(state->Stb->select_start, state->Stb->select_end);
ImU32 bg_color = GetColorU32(ImGuiCol_TextSelectedBg, render_cursor ? 1.0f : 0.6f); // FIXME: current code flow mandate that render_cursor is always true here, we are leaving the transparent one for tests. ImU32 bg_color = GetColorU32(ImGuiCol_TextSelectedBg, render_cursor ? 1.0f : 0.6f); // FIXME: current code flow mandate that render_cursor is always true here, we are leaving the transparent one for tests.
float bg_offy_up = is_multiline ? 0.0f : -1.0f; // FIXME: those offsets should be part of the style? they don't play so well with multi-line selection. float bg_offy_up = is_multiline ? 0.0f : -1.0f; // FIXME: those offsets should be part of the style? they don't play so well with multi-line selection.
@ -5203,7 +5243,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
{ {
// For focus requests to work on our multiline we need to ensure our child ItemAdd() call specifies the ImGuiItemFlags_Inputable (see #4761, #7870)... // For focus requests to work on our multiline we need to ensure our child ItemAdd() call specifies the ImGuiItemFlags_Inputable (see #4761, #7870)...
Dummy(ImVec2(text_size.x, text_size.y + style.FramePadding.y)); Dummy(ImVec2(text_size.x, text_size.y + style.FramePadding.y));
g.NextItemData.ItemFlags |= ImGuiItemFlags_Inputable | ImGuiItemFlags_NoTabStop; g.NextItemData.ItemFlags |= (ImGuiItemFlags)ImGuiItemFlags_Inputable | ImGuiItemFlags_NoTabStop;
EndChild(); EndChild();
item_data_backup.StatusFlags |= (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredWindow); item_data_backup.StatusFlags |= (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredWindow);
@ -5242,7 +5282,7 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state)
{ {
#ifndef IMGUI_DISABLE_DEBUG_TOOLS #ifndef IMGUI_DISABLE_DEBUG_TOOLS
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImStb::STB_TexteditState* stb_state = &state->Stb; ImStb::STB_TexteditState* stb_state = state->Stb;
ImStb::StbUndoState* undo_state = &stb_state->undostate; ImStb::StbUndoState* undo_state = &stb_state->undostate;
Text("ID: 0x%08X, ActiveID: 0x%08X", state->ID, g.ActiveId); Text("ID: 0x%08X, ActiveID: 0x%08X", state->ID, g.ActiveId);
DebugLocateItemOnHover(state->ID); DebugLocateItemOnHover(state->ID);

View File

@ -3,6 +3,7 @@
// Those changes would need to be pushed into nothings/stb: // Those changes would need to be pushed into nothings/stb:
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321) // - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783) // - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783)
// - Added name to struct or it may be forward declared in our code.
// Grep for [DEAR IMGUI] to find the changes. // Grep for [DEAR IMGUI] to find the changes.
// - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_* // - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_*
@ -318,7 +319,7 @@ typedef struct
int undo_char_point, redo_char_point; int undo_char_point, redo_char_point;
} StbUndoState; } StbUndoState;
typedef struct typedef struct STB_TexteditState
{ {
///////////////////// /////////////////////
// //