mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-02-17 20:52:36 +01:00
Updated ImGui.
This commit is contained in:
392
3rdparty/dear-imgui/imgui_demo.cpp
vendored
392
3rdparty/dear-imgui/imgui_demo.cpp
vendored
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.90.5
|
||||
// dear imgui, v1.90.7
|
||||
// (demo code)
|
||||
|
||||
// Help:
|
||||
@@ -10,6 +10,11 @@
|
||||
// Read top of imgui.cpp and imgui.h for many details, documentation, comments, links.
|
||||
// Get the latest version at https://github.com/ocornut/imgui
|
||||
|
||||
// How to easily locate code?
|
||||
// - Use the Item Picker to debug break in code by clicking any widgets: https://github.com/ocornut/imgui/wiki/Debug-Tools
|
||||
// - Browse an online version the demo with code linked to hovered widgets: https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html
|
||||
// - Find a visible string and search for it in the code!
|
||||
|
||||
//---------------------------------------------------
|
||||
// PLEASE DO NOT REMOVE THIS FILE FROM YOUR PROJECT!
|
||||
//---------------------------------------------------
|
||||
@@ -261,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;
|
||||
@@ -483,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");
|
||||
@@ -901,13 +910,18 @@ static void ShowDemoWindowWidgets()
|
||||
if (i == 0)
|
||||
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
|
||||
|
||||
if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
|
||||
// Here we use PushID() to generate a unique base ID, and then the "" used as TreeNode id won't conflict.
|
||||
// An alternative to using 'PushID() + TreeNode("", ...)' to generate a unique ID is to use 'TreeNode((void*)(intptr_t)i, ...)',
|
||||
// aka generate a dummy pointer-sized value to be hashed. The demo below uses that technique. Both are fine.
|
||||
ImGui::PushID(i);
|
||||
if (ImGui::TreeNode("", "Child %d", i))
|
||||
{
|
||||
ImGui::Text("blah blah");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::SmallButton("button")) {}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
@@ -925,7 +939,10 @@ static void ShowDemoWindowWidgets()
|
||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", &base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick);
|
||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", &base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); ImGui::SameLine(); HelpMarker("Extend hit area to all available width instead of allowing more items to be laid out after the node.");
|
||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &base_flags, ImGuiTreeNodeFlags_SpanFullWidth);
|
||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanTextWidth", &base_flags, ImGuiTreeNodeFlags_SpanTextWidth); ImGui::SameLine(); HelpMarker("Reduce hit area to the text label and a bit of margin.");
|
||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &base_flags, ImGuiTreeNodeFlags_SpanAllColumns); ImGui::SameLine(); HelpMarker("For use in Tables only.");
|
||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_AllowOverlap", &base_flags, ImGuiTreeNodeFlags_AllowOverlap);
|
||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_Framed", &base_flags, ImGuiTreeNodeFlags_Framed); ImGui::SameLine(); HelpMarker("Draw frame with background (e.g. for CollapsingHeader)");
|
||||
ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position);
|
||||
ImGui::Checkbox("Test tree node as drag source", &test_drag_and_drop);
|
||||
ImGui::Text("Hello!");
|
||||
@@ -958,6 +975,12 @@ static void ShowDemoWindowWidgets()
|
||||
ImGui::Text("This is a drag and drop source");
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
if (i == 2)
|
||||
{
|
||||
// Item 2 has an additional inline button to help demonstrate SpanTextWidth.
|
||||
ImGui::SameLine();
|
||||
if (ImGui::SmallButton("button")) {}
|
||||
}
|
||||
if (node_open)
|
||||
{
|
||||
ImGui::BulletText("Blah blah\nBlah Blah");
|
||||
@@ -1821,7 +1844,6 @@ static void ShowDemoWindowWidgets()
|
||||
ImGui::Checkbox("Animate", &animate);
|
||||
|
||||
// Plot as lines and plot as histogram
|
||||
IMGUI_DEMO_MARKER("Widgets/Plotting/PlotLines, PlotHistogram");
|
||||
static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
|
||||
ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr));
|
||||
ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0, 80.0f));
|
||||
@@ -1875,15 +1897,17 @@ static void ShowDemoWindowWidgets()
|
||||
ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
IMGUI_DEMO_MARKER("Widgets/Progress Bars");
|
||||
if (ImGui::TreeNode("Progress Bars"))
|
||||
{
|
||||
// Animate a simple progress bar
|
||||
IMGUI_DEMO_MARKER("Widgets/Plotting/ProgressBar");
|
||||
static float progress = 0.0f, progress_dir = 1.0f;
|
||||
if (animate)
|
||||
{
|
||||
progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime;
|
||||
if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; }
|
||||
if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; }
|
||||
}
|
||||
progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime;
|
||||
if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; }
|
||||
if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; }
|
||||
|
||||
// Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width,
|
||||
// or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth.
|
||||
@@ -1895,6 +1919,13 @@ static void ShowDemoWindowWidgets()
|
||||
char buf[32];
|
||||
sprintf(buf, "%d/%d", (int)(progress_saturated * 1753), 1753);
|
||||
ImGui::ProgressBar(progress, ImVec2(0.f, 0.f), buf);
|
||||
|
||||
// Pass an animated negative value, e.g. -1.0f * (float)ImGui::GetTime() is the recommended value.
|
||||
// Adjust the factor if you want to adjust the animation speed.
|
||||
ImGui::ProgressBar(-1.0f * (float)ImGui::GetTime(), ImVec2(0.0f, 0.0f), "Searching..");
|
||||
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||
ImGui::Text("Indeterminate");
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
@@ -5141,7 +5172,8 @@ static void ShowDemoWindowTables()
|
||||
static ImGuiTableFlags flags = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
|
||||
|
||||
static ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAllColumns;
|
||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &tree_node_flags, ImGuiTreeNodeFlags_SpanFullWidth);
|
||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &tree_node_flags, ImGuiTreeNodeFlags_SpanFullWidth);
|
||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanTextWidth", &tree_node_flags, ImGuiTreeNodeFlags_SpanTextWidth);
|
||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &tree_node_flags, ImGuiTreeNodeFlags_SpanAllColumns);
|
||||
|
||||
HelpMarker("See \"Columns flags\" section to configure how indentation is applied to individual columns.");
|
||||
@@ -5330,6 +5362,17 @@ static void ShowDemoWindowTables()
|
||||
ImGui::SliderInt("Frozen rows", &frozen_rows, 0, 2);
|
||||
ImGui::CheckboxFlags("Disable header contributing to column width", &column_flags, ImGuiTableColumnFlags_NoHeaderWidth);
|
||||
|
||||
if (ImGui::TreeNode("Style settings"))
|
||||
{
|
||||
ImGui::SameLine();
|
||||
HelpMarker("Giving access to some ImGuiStyle value in this demo for convenience.");
|
||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
|
||||
ImGui::SliderAngle("style.TableAngledHeadersAngle", &ImGui::GetStyle().TableAngledHeadersAngle, -50.0f, +50.0f);
|
||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
|
||||
ImGui::SliderFloat2("style.TableAngledHeadersTextAlign", (float*)&ImGui::GetStyle().TableAngledHeadersTextAlign, 0.0f, 1.0f, "%.2f");
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTable("table_angled_headers", columns_count, table_flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 12)))
|
||||
{
|
||||
ImGui::TableSetupColumn(column_names[0], ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_NoReorder);
|
||||
@@ -6141,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
|
||||
@@ -6177,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);
|
||||
@@ -6219,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"))
|
||||
@@ -6619,6 +6762,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
|
||||
ImGui::SeparatorText("Tables");
|
||||
ImGui::SliderFloat2("CellPadding", (float*)&style.CellPadding, 0.0f, 20.0f, "%.0f");
|
||||
ImGui::SliderAngle("TableAngledHeadersAngle", &style.TableAngledHeadersAngle, -50.0f, +50.0f);
|
||||
ImGui::SliderFloat2("TableAngledHeadersTextAlign", (float*)&style.TableAngledHeadersTextAlign, 0.0f, 1.0f, "%.2f");
|
||||
|
||||
ImGui::SeparatorText("Widgets");
|
||||
ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
|
||||
@@ -7082,6 +7226,7 @@ struct ExampleAppConsole
|
||||
}
|
||||
|
||||
// Options, Filter
|
||||
ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_O, ImGuiInputFlags_Tooltip);
|
||||
if (ImGui::Button("Options"))
|
||||
ImGui::OpenPopup("Options");
|
||||
ImGui::SameLine();
|
||||
@@ -7090,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())
|
||||
{
|
||||
@@ -8284,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;
|
||||
@@ -8403,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();
|
||||
}
|
||||
@@ -8442,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.
|
||||
@@ -8454,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();
|
||||
}
|
||||
}
|
||||
@@ -8476,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
|
||||
{
|
||||
@@ -8513,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();
|
||||
|
||||
Reference in New Issue
Block a user