Squashed 'external/imgui/imgui/' changes from 6ccc561a2ab..00ad3c65bc2

00ad3c65bc2 Version 1.90.7
f814ef816fb Commented out CaptureKeyboardFromApp(), CaptureMouseFromApp(). Commented out obsolete IsKeyPressedMap() from imgui_internal.h (can call IsKeyPressed). Comments
b9084949bd7 Fixed typo in IsMouseDragging and GetMouseDragDelta's documentation. (#7620)
86931393a36 Shortcuts: Revert "SetShortcutRouting: require explicit routing. (#456)
7832e6a70e6 Shortcuts: Routing: fixed mixed keys<>chars filtering not applying on global routes. (#456, #7618)
85d982011e9 Shortcuts: fixed priority of route calculation (higher first). (#456, #7618)
ce4e210dcb6 Shotcuts: renamed ImGuiInputFlags_RouteGlobalOverFocused -> ImGuiInputFlags_RouteOverFocused, ImGuiInputFlags_RouteGlobalOverActive -> ImGuiInputFlags_RouteOverActive in previsiion of using them with a Hovered route. (#456)
5ce3d299555 Shortcuts: rename ImGuiInputFlags_RouteGlobalHighest to ImGuiInputFlags_RouteGlobalOverActive, made ImGuiInputFlags_RouteGlobalOverFocused and ImGuiInputFlags_RouteGlobalOverActive flags. (#456)
650cb51bf10 Shortcuts: renamed ImGuiInputFlags_RouteActiveItem to ImGuiInputFlags_RouteActive. (#456, #7618)
ef9d525f02c Shortcuts: added ImGuiInputFlags_RouteActiveItem. (#456, #7618) + rearrange Changelog
16b72f2d210 Comments
29439bdd27c Windows: BeginChild(): fixed auto-fit calculation when using either (not both) ResizeX/ResizeY and double-clicking on a border. (#1710)
374b9a7fb43 Demo: Documents: refactor + add Renaming option. (#7233)
c150ad50c46 Shortcuts: claim mods ownership once pressed. (#456, #2637, #2620, #2891, #3370, #3724, #4828, #5108, #5242, #5641)
1002cfa6d2d Demo, Shortcut(): amend Shortcuts demo. (#456)
7c71e66370d Shortcuts, SetShortcutRouting: move ImGuiInputFlags_RouteFromRootWindow evaluation to SetShortcutRouting() for now. (#456)
d5a600e9c64 Shortcuts, SetShortcutRouting: added ImGuiInputFlags_RouteFromRootWindow. Made it possible for SetShortcutRouting() to query for another location.
0eb025f4847 Internals: move ItemHandleShortcut() next to Shortcut(), it's calling it anyhow. (#456)
a689fa262ae SetShortcutRouting: require explicit routing. (#456)
c06e6340cde Shortcuts: added ImGuiInputFlags_Tooltip. (#456)
77e41718940 Shortcuts: added flags to SetNextItemShortcut(). (#456)
197f8904fe8 Shortcuts, Nav: make SetNextItemShortcut() work when another item is active. Made NavCalcPreferredRefPos() take account for remote activation. (#456)
dc5caa483cd Demo: added "Shortcuts" section. (#456, #2637)
fc512a24741 Inputs: Added Shortcut(), SetNextItemShortcut(). Added ImGuiInputFlags, ImGuiInputFlags_RouteXXXX. (#456, #2637)
85513de2476 Internals, Inputs: *Breaking* Swapped parameter order of owner-aware versions of IsKeyPressed(), IsKeyChordPressed(), IsMouseClicked(). (#456)
900b29055c5 Internals, Inputs: *Breaking* Swapped parameter order of Shortcut(). (#456)
55748cdbe12 Internals, Inputs: *Breaking* Renamed ImGuiKeyOwner_None to ImGuiKeyOwner_NoOwner: avoid confusion with non zero value, makes IsKeyPressed() calls using ImGuiKeyOwner_NoOwner more explicit.
ec1d2be96f3 Examples: Win32+DX9,DX10,DX11,DX12: rework main loop to handle minimization and screen locking. (#2496, #3907, #6308, #7615)
6d1a6f1c748 Internals, Inputs: Comments, alignment.
4c3eac2c10e Backends: OpenGL3: Fixed zealous warning by initializing last_pixel_unpack_buffer. (#7614)
a1566c5e1ba Tables: fixed 28a283b breaking PageDown on tables with no interactive items.
aa725ca79dc Inputs: moving ImGuiInputFlags_RouteAlways into ImGuiInputFlags_RouteTypeMask_
cd48059dc53 Tables: comments about skipping access to table data in coarse clipping path.
28a283b4603 Windows: BeginChild(), Tables:fixed visibility of fully clipped child windows and tables to Test Engine.
aa5a6098ee2 Fixed typos in comments (#7599)
d39ca33b63a Fixed false positive with PVS-Studio.
ae8218a3eaf Inputs, Shortcut: fixes some edge cases for GetKeyChordName(), clarify that it is aimed at display. (#456)
25e279ee73f Inputs: Treat ctrl-left-click as right click when ConfigMacOSXBehaviors is set. (#2343)
b4f564c1ed7 Internals: Shortcuts: *Breaking* : rename ImGuiInputFlags_RouteGlobalLow -> ImGuiInputFlags_RouteGlobal, ImGuiInputFlags_RouteGlobal -> ImGuiInputFlags_RouteGlobalOverFocused, ImGuiInputFlags_RouteGlobalHigh -> ImGuiInputFlags_RouteGlobalHighest (#456)
5107e58b0f3 Inputs: amend changelog and clarify how the swap might be a breaking change for a minority of users. (#2343)
8bd5d1d42f0 Inputs: Fixed swapping of keys associated to mods. Fixed warnings. (#2343, #4084, #5923, #456)
77471066471 Inputs: swap Ctrl and Cmd on macOS X, remove ImGuiMod_Shortcut. (#2343, #4084, #5923, #456)
07dbcf1f70d Fixed typos. (#7593)
93daf232233 Examples: SDL3: updates for latest SDL3 API changes.
e45efa9951a Backends: SDL3: Rename SDLK_QUOTE and SDLK_BACKQUOTE to SDLK_APOSTROPHE and SDLK_GRAVE. (#7580)
5d973a87d45 Backends: SDL_Renderer2/SDL_Renderer3: and ImGui_ImplSDLRenderer2_RenderDrawData() and ImGui_ImplSDLRenderer3_RenderDrawData() now takes a SDL_Renderer* parameter.
af2fbf043df Backends/Internals: Don't use IME and clipboard default win32 functions when WINAPI_FAMILY_GAMES (#7585)
e4576914cb9 Internals: amend f806c76 to better match docking + fixed unused static forward declaration warning.
d0524df8879 Internals: slight refactor FindHoveredWindow() -> FindHoveredWindowEx() toward reducing far-away code duplication.
f806c76e97b Tables, Dpi: added dummy g.DpiScale storage (to be altered in docking), using to scale tables border hit thickness.
f0912833ba9 Update FAQ.md (#7581)
ac90e1bd5bd Backends: Win32: replace bd != nullptr assert with early out. (#6275)
0a5d40a0161 Update FAQ.md
d06b8b58d84 Nav: fixed holding Ctrl or gamepad L1 from not slowing down keyboard/gamepad tweak speed.
5e236804541 Backends: all backends + demo now call IMGUI_CHECKVERSION() to verify ABI compatibility between caller code and compiled version of dear imgui. (#7568)
510eb8f4801 Tables: fixed cell background of fully clipped row overlapping with header. (#7575, #7041)
f48aae600a2 Version 1.90.7 WIP

git-subtree-dir: external/imgui/imgui
git-subtree-split: 00ad3c65bc256a16521288505f26fb335440f8f5
This commit is contained in:
2024-05-28 17:12:43 +02:00
parent 0e1b1703f6
commit 293f4fd0a0
44 changed files with 1059 additions and 520 deletions

View File

@@ -1,4 +1,4 @@
// dear imgui, v1.90.6
// dear imgui, v1.90.7
// (demo code)
// Help:
@@ -266,6 +266,9 @@ void ImGui::ShowDemoWindow(bool* p_open)
// Most functions would normally just assert/crash if the context is missing.
IM_ASSERT(ImGui::GetCurrentContext() != NULL && "Missing Dear ImGui context. Refer to examples app!");
// Verify ABI compatibility between caller code and compiled version of Dear ImGui. This helps detects some build issues.
IMGUI_CHECKVERSION();
// Examples Apps (accessible from the "Examples" menu)
static bool show_app_main_menu_bar = false;
static bool show_app_console = false;
@@ -488,6 +491,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
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.ConfigMacOSXBehaviors", &io.ConfigMacOSXBehaviors);
ImGui::SameLine(); HelpMarker("Swap Cmd<>Ctrl keys, enable various MacOS style behaviors.");
ImGui::Text("Also see Style->Rendering for rendering options.");
ImGui::SeparatorText("Debug");
@@ -6180,12 +6184,14 @@ static void ShowDemoWindowInputs()
// Display inputs submitted to ImGuiIO
IMGUI_DEMO_MARKER("Inputs & Focus/Inputs");
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
if (ImGui::TreeNode("Inputs"))
bool inputs_opened = ImGui::TreeNode("Inputs");
ImGui::SameLine();
HelpMarker(
"This is a simplified view. See more detailed input state:\n"
"- in 'Tools->Metrics/Debugger->Inputs'.\n"
"- in 'Tools->Debug Log->IO'.");
if (inputs_opened)
{
HelpMarker(
"This is a simplified view. See more detailed input state:\n"
"- in 'Tools->Metrics/Debugger->Inputs'.\n"
"- in 'Tools->Debug Log->IO'.");
if (ImGui::IsMousePosValid())
ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
else
@@ -6216,15 +6222,17 @@ static void ShowDemoWindowInputs()
// Display ImGuiIO output flags
IMGUI_DEMO_MARKER("Inputs & Focus/Outputs");
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
if (ImGui::TreeNode("Outputs"))
bool outputs_opened = ImGui::TreeNode("Outputs");
ImGui::SameLine();
HelpMarker(
"The value of io.WantCaptureMouse and io.WantCaptureKeyboard are normally set by Dear ImGui "
"to instruct your application of how to route inputs. Typically, when a value is true, it means "
"Dear ImGui wants the corresponding inputs and we expect the underlying application to ignore them.\n\n"
"The most typical case is: when hovering a window, Dear ImGui set io.WantCaptureMouse to true, "
"and underlying application should ignore mouse inputs (in practice there are many and more subtle "
"rules leading to how those flags are set).");
if (outputs_opened)
{
HelpMarker(
"The value of io.WantCaptureMouse and io.WantCaptureKeyboard are normally set by Dear ImGui "
"to instruct your application of how to route inputs. Typically, when a value is true, it means "
"Dear ImGui wants the corresponding inputs and we expect the underlying application to ignore them.\n\n"
"The most typical case is: when hovering a window, Dear ImGui set io.WantCaptureMouse to true, "
"and underlying application should ignore mouse inputs (in practice there are many and more subtle "
"rules leading to how those flags are set).");
ImGui::Text("io.WantCaptureMouse: %d", io.WantCaptureMouse);
ImGui::Text("io.WantCaptureMouseUnlessPopupClose: %d", io.WantCaptureMouseUnlessPopupClose);
ImGui::Text("io.WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
@@ -6258,6 +6266,102 @@ static void ShowDemoWindowInputs()
ImGui::TreePop();
}
// Demonstrate using Shortcut() and Routing Policies.
// The general flow is:
// - Code interested in a chord (e.g. "Ctrl+A") declares their intent.
// - Multiple locations may be interested in same chord! Routing helps find a winner.
// - Every frame, we resolve all claims and assign one owner if the modifiers are matching.
// - The lower-level function is 'bool SetShortcutRouting()', returns true when caller got the route.
// - Most of the times, SetShortcutRouting() is not called directly. User mostly calls Shortcut() with routing flags.
// - If you call Shortcut() WITHOUT any routing option, it uses ImGuiInputFlags_RouteFocused.
// TL;DR: Most uses will simply be:
// - Shortcut(ImGuiMod_Ctrl | ImGuiKey_A); // Use ImGuiInputFlags_RouteFocused policy.
IMGUI_DEMO_MARKER("Inputs & Focus/Shortcuts");
if (ImGui::TreeNode("Shortcuts"))
{
static ImGuiInputFlags route_options = ImGuiInputFlags_Repeat;
static ImGuiInputFlags route_type = ImGuiInputFlags_RouteFocused;
ImGui::CheckboxFlags("ImGuiInputFlags_Repeat", &route_options, ImGuiInputFlags_Repeat);
ImGui::RadioButton("ImGuiInputFlags_RouteActive", &route_type, ImGuiInputFlags_RouteActive);
ImGui::RadioButton("ImGuiInputFlags_RouteFocused (default)", &route_type, ImGuiInputFlags_RouteFocused);
ImGui::RadioButton("ImGuiInputFlags_RouteGlobal", &route_type, ImGuiInputFlags_RouteGlobal);
ImGui::Indent();
ImGui::BeginDisabled(route_type != ImGuiInputFlags_RouteGlobal);
ImGui::CheckboxFlags("ImGuiInputFlags_RouteOverFocused", &route_options, ImGuiInputFlags_RouteOverFocused);
ImGui::CheckboxFlags("ImGuiInputFlags_RouteOverActive", &route_options, ImGuiInputFlags_RouteOverActive);
ImGui::CheckboxFlags("ImGuiInputFlags_RouteUnlessBgFocused", &route_options, ImGuiInputFlags_RouteUnlessBgFocused);
ImGui::EndDisabled();
ImGui::Unindent();
ImGui::RadioButton("ImGuiInputFlags_RouteAlways", &route_type, ImGuiInputFlags_RouteAlways);
ImGuiInputFlags flags = route_type | route_options; // Merged flags
if (route_type != ImGuiInputFlags_RouteGlobal)
route_options &= ~(ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive | ImGuiInputFlags_RouteUnlessBgFocused);
ImGui::SeparatorText("Using SetNextItemShortcut()");
ImGui::Text("Ctrl+S");
ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_S, flags | ImGuiInputFlags_Tooltip);
ImGui::Button("Save");
ImGui::Text("Alt+F");
ImGui::SetNextItemShortcut(ImGuiMod_Alt | ImGuiKey_F, flags | ImGuiInputFlags_Tooltip);
static float f = 0.5f;
ImGui::SliderFloat("Factor", &f, 0.0f, 1.0f);
ImGui::SeparatorText("Using Shortcut()");
const float line_height = ImGui::GetTextLineHeightWithSpacing();
const ImGuiKeyChord key_chord = ImGuiMod_Ctrl | ImGuiKey_A;
ImGui::Text("Ctrl+A");
ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 0.0f, 1.0f, 0.1f));
ImGui::BeginChild("WindowA", ImVec2(-FLT_MIN, line_height * 14), true);
ImGui::Text("Press CTRL+A and see who receives it!");
ImGui::Separator();
// 1: Window polling for CTRL+A
ImGui::Text("(in WindowA)");
ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
// 2: InputText also polling for CTRL+A: it always uses _RouteFocused internally (gets priority when active)
// (Commmented because the owner-aware version of Shortcut() is still in imgui_internal.h)
//char str[16] = "Press CTRL+A";
//ImGui::Spacing();
//ImGui::InputText("InputTextB", str, IM_ARRAYSIZE(str), ImGuiInputTextFlags_ReadOnly);
//ImGuiID item_id = ImGui::GetItemID();
//ImGui::SameLine(); HelpMarker("Internal widgets always use _RouteFocused");
//ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags, item_id) ? "PRESSED" : "...");
// 3: Dummy child is not claiming the route: focusing them shouldn't steal route away from WindowA
ImGui::BeginChild("ChildD", ImVec2(-FLT_MIN, line_height * 4), true);
ImGui::Text("(in ChildD: not using same Shortcut)");
ImGui::Text("IsWindowFocused: %d", ImGui::IsWindowFocused());
ImGui::EndChild();
// 4: Child window polling for CTRL+A. It is deeper than WindowA and gets priority when focused.
ImGui::BeginChild("ChildE", ImVec2(-FLT_MIN, line_height * 4), true);
ImGui::Text("(in ChildE: using same Shortcut)");
ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
ImGui::EndChild();
// 5: In a popup
if (ImGui::Button("Open Popup"))
ImGui::OpenPopup("PopupF");
if (ImGui::BeginPopup("PopupF"))
{
ImGui::Text("(in PopupF)");
ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
// (Commmented because the owner-aware version of Shortcut() is still in imgui_internal.h)
//ImGui::InputText("InputTextG", str, IM_ARRAYSIZE(str), ImGuiInputTextFlags_ReadOnly);
//ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags, ImGui::GetItemID()) ? "PRESSED" : "...");
ImGui::EndPopup();
}
ImGui::EndChild();
ImGui::PopStyleColor();
ImGui::TreePop();
}
// Display mouse cursors
IMGUI_DEMO_MARKER("Inputs & Focus/Mouse Cursors");
if (ImGui::TreeNode("Mouse Cursors"))
@@ -7122,6 +7226,7 @@ struct ExampleAppConsole
}
// Options, Filter
ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_O, ImGuiInputFlags_Tooltip);
if (ImGui::Button("Options"))
ImGui::OpenPopup("Options");
ImGui::SameLine();
@@ -7130,7 +7235,7 @@ struct ExampleAppConsole
// Reserve enough left-over height for 1 separator + 1 input text
const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
if (ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), ImGuiChildFlags_None, ImGuiWindowFlags_HorizontalScrollbar))
if (ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), ImGuiChildFlags_None, ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_NavFlattened))
{
if (ImGui::BeginPopupContextWindow())
{
@@ -8324,92 +8429,119 @@ static void ShowExampleAppCustomRendering(bool* p_open)
// Simplified structure to mimic a Document model
struct MyDocument
{
const char* Name; // Document title
char Name[32]; // Document title
int UID; // Unique ID (necessary as we can change title)
bool Open; // Set when open (we keep an array of all available documents to simplify demo code!)
bool OpenPrev; // Copy of Open from last update.
bool Dirty; // Set when the document has been modified
bool WantClose; // Set when the document
ImVec4 Color; // An arbitrary variable associated to the document
MyDocument(const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f))
MyDocument(int uid, const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f))
{
Name = name;
UID = uid;
snprintf(Name, sizeof(Name), "%s", name);
Open = OpenPrev = open;
Dirty = false;
WantClose = false;
Color = color;
}
void DoOpen() { Open = true; }
void DoQueueClose() { WantClose = true; }
void DoForceClose() { Open = false; Dirty = false; }
void DoSave() { Dirty = false; }
};
struct ExampleAppDocuments
{
ImVector<MyDocument> Documents;
ImVector<MyDocument*> CloseQueue;
MyDocument* RenamingDoc = NULL;
bool RenamingStarted = false;
ExampleAppDocuments()
{
Documents.push_back(MyDocument(0, "Lettuce", true, ImVec4(0.4f, 0.8f, 0.4f, 1.0f)));
Documents.push_back(MyDocument(1, "Eggplant", true, ImVec4(0.8f, 0.5f, 1.0f, 1.0f)));
Documents.push_back(MyDocument(2, "Carrot", true, ImVec4(1.0f, 0.8f, 0.5f, 1.0f)));
Documents.push_back(MyDocument(3, "Tomato", false, ImVec4(1.0f, 0.3f, 0.4f, 1.0f)));
Documents.push_back(MyDocument(4, "A Rather Long Title", false, ImVec4(0.4f, 0.8f, 0.8f, 1.0f)));
Documents.push_back(MyDocument(5, "Some Document", false, ImVec4(0.8f, 0.8f, 1.0f, 1.0f)));
}
// As we allow to change document name, we append a never-changing document ID so tabs are stable
void GetTabName(MyDocument* doc, char* out_buf, size_t out_buf_size)
{
snprintf(out_buf, out_buf_size, "%s###doc%d", doc->Name, doc->UID);
}
// Display placeholder contents for the Document
static void DisplayContents(MyDocument* doc)
void DisplayDocContents(MyDocument* doc)
{
ImGui::PushID(doc);
ImGui::Text("Document \"%s\"", doc->Name);
ImGui::PushStyleColor(ImGuiCol_Text, doc->Color);
ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
ImGui::PopStyleColor();
if (ImGui::Button("Modify", ImVec2(100, 0)))
doc->Dirty = true;
ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_R, ImGuiInputFlags_Tooltip);
if (ImGui::Button("Rename.."))
{
RenamingDoc = doc;
RenamingStarted = true;
}
ImGui::SameLine();
if (ImGui::Button("Save", ImVec2(100, 0)))
ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_M, ImGuiInputFlags_Tooltip);
if (ImGui::Button("Modify"))
doc->Dirty = true;
ImGui::SameLine();
ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_S, ImGuiInputFlags_Tooltip);
if (ImGui::Button("Save"))
doc->DoSave();
ImGui::SameLine();
ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_W, ImGuiInputFlags_Tooltip);
if (ImGui::Button("Close"))
CloseQueue.push_back(doc);
ImGui::ColorEdit3("color", &doc->Color.x); // Useful to test drag and drop and hold-dragged-to-open-tab behavior.
ImGui::PopID();
}
// Display context menu for the Document
static void DisplayContextMenu(MyDocument* doc)
void DisplayDocContextMenu(MyDocument* doc)
{
if (!ImGui::BeginPopupContextItem())
return;
char buf[256];
sprintf(buf, "Save %s", doc->Name);
if (ImGui::MenuItem(buf, "CTRL+S", false, doc->Open))
if (ImGui::MenuItem(buf, "Ctrl+S", false, doc->Open))
doc->DoSave();
if (ImGui::MenuItem("Close", "CTRL+W", false, doc->Open))
doc->DoQueueClose();
if (ImGui::MenuItem("Rename...", "Ctrl+R", false, doc->Open))
RenamingDoc = doc;
if (ImGui::MenuItem("Close", "Ctrl+W", false, doc->Open))
CloseQueue.push_back(doc);
ImGui::EndPopup();
}
};
struct ExampleAppDocuments
{
ImVector<MyDocument> Documents;
ExampleAppDocuments()
// [Optional] Notify the system of Tabs/Windows closure that happened outside the regular tab interface.
// If a tab has been closed programmatically (aka closed from another source such as the Checkbox() in the demo,
// as opposed to clicking on the regular tab closing button) and stops being submitted, it will take a frame for
// the tab bar to notice its absence. During this frame there will be a gap in the tab bar, and if the tab that has
// disappeared was the selected one, the tab bar will report no selected tab during the frame. This will effectively
// give the impression of a flicker for one frame.
// We call SetTabItemClosed() to manually notify the Tab Bar or Docking system of removed tabs to avoid this glitch.
// Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag.
void NotifyOfDocumentsClosedElsewhere()
{
Documents.push_back(MyDocument("Lettuce", true, ImVec4(0.4f, 0.8f, 0.4f, 1.0f)));
Documents.push_back(MyDocument("Eggplant", true, ImVec4(0.8f, 0.5f, 1.0f, 1.0f)));
Documents.push_back(MyDocument("Carrot", true, ImVec4(1.0f, 0.8f, 0.5f, 1.0f)));
Documents.push_back(MyDocument("Tomato", false, ImVec4(1.0f, 0.3f, 0.4f, 1.0f)));
Documents.push_back(MyDocument("A Rather Long Title", false));
Documents.push_back(MyDocument("Some Document", false));
for (MyDocument& doc : Documents)
{
if (!doc.Open && doc.OpenPrev)
ImGui::SetTabItemClosed(doc.Name);
doc.OpenPrev = doc.Open;
}
}
};
// [Optional] Notify the system of Tabs/Windows closure that happened outside the regular tab interface.
// If a tab has been closed programmatically (aka closed from another source such as the Checkbox() in the demo,
// as opposed to clicking on the regular tab closing button) and stops being submitted, it will take a frame for
// the tab bar to notice its absence. During this frame there will be a gap in the tab bar, and if the tab that has
// disappeared was the selected one, the tab bar will report no selected tab during the frame. This will effectively
// give the impression of a flicker for one frame.
// We call SetTabItemClosed() to manually notify the Tab Bar or Docking system of removed tabs to avoid this glitch.
// Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag.
static void NotifyOfDocumentsClosedElsewhere(ExampleAppDocuments& app)
{
for (MyDocument& doc : app.Documents)
{
if (!doc.Open && doc.OpenPrev)
ImGui::SetTabItemClosed(doc.Name);
doc.OpenPrev = doc.Open;
}
}
void ShowExampleAppDocuments(bool* p_open)
{
static ExampleAppDocuments app;
@@ -8443,8 +8575,8 @@ void ShowExampleAppDocuments(bool* p_open)
}
if (ImGui::MenuItem("Close All Documents", NULL, false, open_count > 0))
for (MyDocument& doc : app.Documents)
doc.DoQueueClose();
if (ImGui::MenuItem("Exit", "Ctrl+F4") && p_open)
app.CloseQueue.push_back(&doc);
if (ImGui::MenuItem("Exit") && p_open)
*p_open = false;
ImGui::EndMenu();
}
@@ -8482,7 +8614,7 @@ void ShowExampleAppDocuments(bool* p_open)
if (ImGui::BeginTabBar("##tabs", tab_bar_flags))
{
if (opt_reorderable)
NotifyOfDocumentsClosedElsewhere(app);
app.NotifyOfDocumentsClosedElsewhere();
// [DEBUG] Stress tests
//if ((ImGui::GetFrameCount() % 30) == 0) docs[1].Open ^= 1; // [DEBUG] Automatically show/hide a tab. Test various interactions e.g. dragging with this on.
@@ -8494,20 +8626,23 @@ void ShowExampleAppDocuments(bool* p_open)
if (!doc.Open)
continue;
// As we allow to change document name, we append a never-changing document id so tabs are stable
char doc_name_buf[64];
app.GetTabName(&doc, doc_name_buf, sizeof(doc_name_buf));
ImGuiTabItemFlags tab_flags = (doc.Dirty ? ImGuiTabItemFlags_UnsavedDocument : 0);
bool visible = ImGui::BeginTabItem(doc.Name, &doc.Open, tab_flags);
bool visible = ImGui::BeginTabItem(doc_name_buf, &doc.Open, tab_flags);
// Cancel attempt to close when unsaved add to save queue so we can display a popup.
if (!doc.Open && doc.Dirty)
{
doc.Open = true;
doc.DoQueueClose();
app.CloseQueue.push_back(&doc);
}
MyDocument::DisplayContextMenu(&doc);
app.DisplayDocContextMenu(&doc);
if (visible)
{
MyDocument::DisplayContents(&doc);
app.DisplayDocContents(&doc);
ImGui::EndTabItem();
}
}
@@ -8516,33 +8651,44 @@ void ShowExampleAppDocuments(bool* p_open)
}
}
// Update closing queue
static ImVector<MyDocument*> close_queue;
if (close_queue.empty())
// Display renaming UI
if (app.RenamingDoc != NULL)
{
// Close queue is locked once we started a popup
for (MyDocument& doc : app.Documents)
if (doc.WantClose)
if (app.RenamingStarted)
ImGui::OpenPopup("Rename");
if (ImGui::BeginPopup("Rename"))
{
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 30);
if (ImGui::InputText("###Name", app.RenamingDoc->Name, IM_ARRAYSIZE(app.RenamingDoc->Name), ImGuiInputTextFlags_EnterReturnsTrue))
{
doc.WantClose = false;
close_queue.push_back(&doc);
ImGui::CloseCurrentPopup();
app.RenamingDoc = NULL;
}
if (app.RenamingStarted)
ImGui::SetKeyboardFocusHere(-1);
ImGui::EndPopup();
}
else
{
app.RenamingDoc = NULL;
}
app.RenamingStarted = false;
}
// Display closing confirmation UI
if (!close_queue.empty())
if (!app.CloseQueue.empty())
{
int close_queue_unsaved_documents = 0;
for (int n = 0; n < close_queue.Size; n++)
if (close_queue[n]->Dirty)
for (int n = 0; n < app.CloseQueue.Size; n++)
if (app.CloseQueue[n]->Dirty)
close_queue_unsaved_documents++;
if (close_queue_unsaved_documents == 0)
{
// Close documents when all are unsaved
for (int n = 0; n < close_queue.Size; n++)
close_queue[n]->DoForceClose();
close_queue.clear();
for (int n = 0; n < app.CloseQueue.Size; n++)
app.CloseQueue[n]->DoForceClose();
app.CloseQueue.clear();
}
else
{
@@ -8553,37 +8699,35 @@ void ShowExampleAppDocuments(bool* p_open)
ImGui::Text("Save change to the following items?");
float item_height = ImGui::GetTextLineHeightWithSpacing();
if (ImGui::BeginChild(ImGui::GetID("frame"), ImVec2(-FLT_MIN, 6.25f * item_height), ImGuiChildFlags_FrameStyle))
{
for (int n = 0; n < close_queue.Size; n++)
if (close_queue[n]->Dirty)
ImGui::Text("%s", close_queue[n]->Name);
}
for (MyDocument* doc : app.CloseQueue)
if (doc->Dirty)
ImGui::Text("%s", doc->Name);
ImGui::EndChild();
ImVec2 button_size(ImGui::GetFontSize() * 7.0f, 0.0f);
if (ImGui::Button("Yes", button_size))
{
for (int n = 0; n < close_queue.Size; n++)
for (MyDocument* doc : app.CloseQueue)
{
if (close_queue[n]->Dirty)
close_queue[n]->DoSave();
close_queue[n]->DoForceClose();
if (doc->Dirty)
doc->DoSave();
doc->DoForceClose();
}
close_queue.clear();
app.CloseQueue.clear();
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
if (ImGui::Button("No", button_size))
{
for (int n = 0; n < close_queue.Size; n++)
close_queue[n]->DoForceClose();
close_queue.clear();
for (MyDocument* doc : app.CloseQueue)
doc->DoForceClose();
app.CloseQueue.clear();
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
if (ImGui::Button("Cancel", button_size))
{
close_queue.clear();
app.CloseQueue.clear();
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();