diff --git a/bindings/imgui_bundle/demos_cpp/demos_immapp/demo_docking.cpp b/bindings/imgui_bundle/demos_cpp/demos_immapp/demo_docking.cpp index 49dbb199..450177d8 100644 --- a/bindings/imgui_bundle/demos_cpp/demos_immapp/demo_docking.cpp +++ b/bindings/imgui_bundle/demos_cpp/demos_immapp/demo_docking.cpp @@ -183,28 +183,38 @@ void DemoHideWindow(AppState& appState) } } -// Display a button that will show an additional window +// Display a button that will add another dockable window during execution void DemoShowAdditionalWindow(AppState& appState) { - // Notes: - // - it is *not* possible to modify the content of the vector runnerParams.dockingParams.dockableWindows - // from the code inside a window's `GuiFunction` (since this GuiFunction will be called while iterating on this vector!) - // - there are two ways to dynamically add windows: - // * either make them initially invisible, and exclude them from the view menu (such as shown here) - // * or modify runnerParams.dockingParams.dockableWindows inside the callback RunnerCallbacks.PreNewFrame - const char* windowName = "Additional Window"; + // In order to add a dockable window during execution, you should use + // HelloImGui::AddDockableWindow() + // Note: you should not modify manually the content of runnerParams.dockingParams.dockableWindows + // (since HelloImGui is constantly looping on it) + ImGui::PushFont(appState.TitleFont); ImGui::Text("Dynamically add window"); ImGui::PopFont(); + + auto currentWindow = ImGui::GetCurrentWindow(); + + const char* windowName = "Additional Window"; if (ImGui::Button("Show additional window")) { - auto additionalWindowPtr = HelloImGui::GetRunnerParams()->dockingParams.dockableWindowOfName(windowName); - if (additionalWindowPtr) - { - // additionalWindowPtr->includeInViewMenu = true; - additionalWindowPtr->isVisible = true; - } + HelloImGui::DockableWindow additionalWindow; + additionalWindow.label = windowName; + additionalWindow.includeInViewMenu = false; // this window is not shown in the view menu, + additionalWindow.rememberIsVisible = true; // its visibility is not saved in the settings file, + additionalWindow.dockSpaceName = "MiscSpace"; // when shown, it will appear in MiscSpace. + additionalWindow.GuiFunction = [] { ImGui::Text("This is the additional window"); }; + HelloImGui::AddDockableWindow( + additionalWindow, + false // forceDockspace=false: means that the window will be docked to the last space it was docked to + // i.e. dockSpaceName is ignored if the user previously moved the window to another space + ); } - if (ImGui::IsItemHovered()) - ImGui::SetTooltip("By clicking this button, you can show an additional window"); + ImGui::SetItemTooltip("By clicking this button, you can show an additional window"); + + if (ImGui::Button("Remove additional window")) + HelloImGui::RemoveDockableWindow(windowName); + ImGui::SetItemTooltip("By clicking this button, you can remove the additional window"); } void DemoLogs(AppState& appState) @@ -723,16 +733,6 @@ std::vector CreateDockableWindows(AppState& appState dearImGuiDemoWindow.imGuiWindowFlags = ImGuiWindowFlags_MenuBar; dearImGuiDemoWindow.GuiFunction = [] { ImGui::ShowDemoWindow(); }; - // additionalWindow is initially not visible (and not mentioned in the view menu). - // it will be opened only if the user chooses to display it - HelloImGui::DockableWindow additionalWindow; - additionalWindow.label = "Additional Window"; - additionalWindow.isVisible = false; // this window is initially hidden, - additionalWindow.includeInViewMenu = false; // it is not shown in the view menu, - additionalWindow.rememberIsVisible = false; // its visibility is not saved in the settings file, - additionalWindow.dockSpaceName = "MiscSpace"; // when shown, it will appear in MiscSpace. - additionalWindow.GuiFunction = [] { ImGui::Text("This is the additional window"); }; - // alternativeThemeWindow HelloImGui::DockableWindow alternativeThemeWindow; // Since this window applies a theme, We need to call "ImGui::Begin" ourselves so @@ -747,7 +747,6 @@ std::vector CreateDockableWindows(AppState& appState layoutCustomizationWindow, logsWindow, dearImGuiDemoWindow, - additionalWindow, alternativeThemeWindow }; return dockableWindows; diff --git a/bindings/imgui_bundle/demos_python/demos_immapp/demo_docking.py b/bindings/imgui_bundle/demos_python/demos_immapp/demo_docking.py index a9e08938..bb1904dd 100644 --- a/bindings/imgui_bundle/demos_python/demos_immapp/demo_docking.py +++ b/bindings/imgui_bundle/demos_python/demos_immapp/demo_docking.py @@ -161,31 +161,35 @@ def demo_hide_window(app_state: AppState): hello_imgui.get_runner_params().app_window_params.hidden = False -# Display a button that will show an additional window +# Display a button that will add another dockable window during execution def demo_show_additional_window(app_state: AppState): - # Notes: - # - it is *not* possible to modify the content of the vector runnerParams.dockingParams.dockableWindows - # from the code inside a window's `GuiFunction` (since this GuiFunction will be called while iterating - # on this vector!) - # - there are two ways to dynamically add windows: - # * either make them initially invisible, and exclude them from the view menu (such as shown here) - # * or modify runnerParams.dockingParams.dockableWindows inside the callback RunnerCallbacks.PreNewFrame - window_name = "Additional Window" + # In order to add a dockable window during execution, you should use + # hello_imgui.add_dockable_window() + # Note: you should not modify manually the content of runnerParams.docking_params.dockable_windows + # (since HelloImGui is constantly looping on it) imgui.push_font(app_state.title_font) imgui.text("Dynamically add window") imgui.pop_font() + window_name = "Additional Window" if imgui.button("Show additional window"): - runner_params = hello_imgui.get_runner_params() - additional_window_ptr = runner_params.docking_params.dockable_window_of_name( - window_name + additional_window = hello_imgui.DockableWindow() + additional_window.label = window_name + additional_window.include_in_view_menu = False # this window is not shown in the view menu, + additional_window.remember_is_visible = False # its visibility is not saved in the settings file, + additional_window.dock_space_name = "MiscSpace" # when shown, it will appear in MiscSpace. + additional_window.gui_function = lambda: imgui.text("This is the additional window") + hello_imgui.add_dockable_window( + additional_window, + force_dockspace=False # means that the window will be docked to the last space it was docked to + # i.e. dock_space_name is ignored if the user previously moved the window to another space ) - if additional_window_ptr: - # additional_window_ptr.include_in_view_menu = True - additional_window_ptr.is_visible = True - if imgui.is_item_hovered(): - imgui.set_tooltip("By clicking this button, you can show an additional window") + imgui.set_item_tooltip("By clicking this button, you can show an additional window") + + if imgui.button("Remove additional window"): + hello_imgui.remove_dockable_window(window_name) + imgui.set_item_tooltip("By clicking this button, you can remove the additional window") def demo_basic_widgets(app_state: AppState): @@ -725,20 +729,6 @@ def create_dockable_windows(app_state: AppState) -> List[hello_imgui.DockableWin dear_imgui_demo_window.imgui_window_flags = imgui.WindowFlags_.menu_bar dear_imgui_demo_window.gui_function = imgui.show_demo_window # type: ignore - # additional_window is initially not visible (and not mentioned in the view menu). - # it will be opened only if the user chooses to display it - additional_window = hello_imgui.DockableWindow() - additional_window.label = "Additional Window" - additional_window.is_visible = False # this window is initially hidden, - additional_window.include_in_view_menu = False # it is not shown in the view menu, - additional_window.remember_is_visible = ( - False # its visibility is not saved in the settings file, - ) - additional_window.dock_space_name = ( - "MiscSpace" # when shown, it will appear in MiscSpace. - ) - additional_window.gui_function = lambda: imgui.text("This is the additional window") - # alternativeThemeWindow alternative_theme_window = hello_imgui.DockableWindow() # Since this window applies a theme, We need to call "imgui.begin" ourselves so @@ -753,7 +743,6 @@ def create_dockable_windows(app_state: AppState) -> List[hello_imgui.DockableWin layout_customization_window, logs_window, dear_imgui_demo_window, - additional_window, alternative_theme_window, ] return dockable_windows diff --git a/bindings/imgui_bundle/hello_imgui.pyi b/bindings/imgui_bundle/hello_imgui.pyi index 8cc2c257..3f92b710 100644 --- a/bindings/imgui_bundle/hello_imgui.pyi +++ b/bindings/imgui_bundle/hello_imgui.pyi @@ -2122,7 +2122,7 @@ class DockableWindow: # --------------- Main params ------------------- # std::string label; /* original C++ signature */ - # `label`: _string_. Title of the window. + # `label`: _string_. Title of the window. It should be unique! Use "##" to add a unique suffix if needed. label: str # DockSpaceName dockSpaceName; /* original C++ signature */ @@ -2306,11 +2306,7 @@ class DockingParams: # std::optional dockSpaceIdFromName(const std::string& dockSpaceName); /* original C++ signature */ def dock_space_id_from_name(self, dock_space_name: str) -> Optional[ImGuiID]: """`optional dockSpaceIdFromName(const std::string& dockSpaceName)`: - may return the ImGuiID corresponding to the dockspace with this name. - **Warning**: this will work reliably only if - layoutCondition = DockingLayoutCondition::ApplicationStart. - In other cases, the ID may be cached by ImGui himself at the first run, - and HelloImGui will *not* know it on subsequent runs! + returns the ImGuiID corresponding to the dockspace with this name """ pass # DockingParams(std::vector dockingSplits = std::vector(), std::vector dockableWindows = std::vector(), std::string layoutName = "Default", ImGuiDockNodeFlags mainDockSpaceNodeFlags = ImGuiDockNodeFlags_PassthruCentralNode, DockingLayoutCondition layoutCondition = DockingLayoutCondition::FirstUseEver, bool layoutReset = false); /* original C++ signature */ @@ -3292,6 +3288,23 @@ def current_layout_name() -> str: """`CurrentLayoutName()`: returns the name of the current layout""" pass +# void AddDockableWindow(const DockableWindow& dockableWindow, bool forceDockspace = false); /* original C++ signature */ +def add_dockable_window( + dockable_window: DockableWindow, force_dockspace: bool = False +) -> None: + """`AddDockableWindow()`: will add a dockable window to the current layout. + Will dock the window to the dockspace it belongs to if forceDockspace is True, + otherwise will dock it to the last space it was docked to (using saved settings) + """ + pass + +# void RemoveDockableWindow(const std::string& dockableWindowName); /* original C++ signature */ +def remove_dockable_window(dockable_window_name: str) -> None: + """`RemoveDockableWindow()`: will remove a dockable window from the current layout. + (dockableWindowName is the label of the window, as provided in the DockableWindow struct) + """ + pass + # @@md # ============================== User prefs Utils ============================= diff --git a/external/hello_imgui/bindings/hello_imgui_amalgamation.h b/external/hello_imgui/bindings/hello_imgui_amalgamation.h index 92f8343b..649274a0 100644 --- a/external/hello_imgui/bindings/hello_imgui_amalgamation.h +++ b/external/hello_imgui/bindings/hello_imgui_amalgamation.h @@ -1692,7 +1692,7 @@ struct DockableWindow { // --------------- Main params ------------------- - // `label`: _string_. Title of the window. + // `label`: _string_. Title of the window. It should be unique! Use "##" to add a unique suffix if needed. std::string label; // `dockSpaceName`: _DockSpaceName (aka string)_. @@ -1846,11 +1846,7 @@ struct DockingParams bool focusDockableWindow(const std::string& windowName); // `optional dockSpaceIdFromName(const std::string& dockSpaceName)`: - // may return the ImGuiID corresponding to the dockspace with this name. - // **Warning**: this will work reliably only if - // layoutCondition = DockingLayoutCondition::ApplicationStart. - // In other cases, the ID may be cached by ImGui himself at the first run, - // and HelloImGui will *not* know it on subsequent runs! + // returns the ImGuiID corresponding to the dockspace with this name std::optional dockSpaceIdFromName(const std::string& dockSpaceName); }; // @@md @@ -2626,6 +2622,16 @@ void SwitchLayout(const std::string& layoutName); // `CurrentLayoutName()`: returns the name of the current layout std::string CurrentLayoutName(); + +// `AddDockableWindow()`: will add a dockable window to the current layout. +// Will dock the window to the dockspace it belongs to if forceDockspace is true, +// otherwise will dock it to the last space it was docked to (using saved settings) +void AddDockableWindow(const DockableWindow& dockableWindow, bool forceDockspace = false); + +// `RemoveDockableWindow()`: will remove a dockable window from the current layout. +// (dockableWindowName is the label of the window, as provided in the DockableWindow struct) +void RemoveDockableWindow(const std::string& dockableWindowName); + // @@md diff --git a/external/hello_imgui/bindings/pybind_hello_imgui.cpp b/external/hello_imgui/bindings/pybind_hello_imgui.cpp index 4088891e..45a27a47 100644 --- a/external/hello_imgui/bindings/pybind_hello_imgui.cpp +++ b/external/hello_imgui/bindings/pybind_hello_imgui.cpp @@ -849,7 +849,7 @@ void py_init_module_hello_imgui(py::module& m) auto pyClassDockableWindow = py::class_ (m, "DockableWindow", "DockableWindow is a struct that represents a window that can be docked.") - .def_readwrite("label", &HelloImGui::DockableWindow::label, "`label`: _string_. Title of the window.") + .def_readwrite("label", &HelloImGui::DockableWindow::label, "`label`: _string_. Title of the window. It should be unique! Use \"##\" to add a unique suffix if needed.") .def_readwrite("dock_space_name", &HelloImGui::DockableWindow::dockSpaceName, " `dockSpaceName`: _DockSpaceName (aka string)_.\n Id of the dock space where this window should initially be placed") .def_readwrite("gui_function", &HelloImGui::DockableWindow::GuiFunction, " `GuiFunction`: _VoidFunction_.\n Any function that will render this window's Gui") .def_readwrite("is_visible", &HelloImGui::DockableWindow::isVisible, " `isVisible`: _bool, default=true_.\n Flag that indicates whether this window is visible or not.") @@ -910,7 +910,7 @@ void py_init_module_hello_imgui(py::module& m) .def("dock_space_id_from_name", &HelloImGui::DockingParams::dockSpaceIdFromName, py::arg("dock_space_name"), - " `optional dockSpaceIdFromName(const std::string& dockSpaceName)`:\n may return the ImGuiID corresponding to the dockspace with this name.\n **Warning**: this will work reliably only if\n layoutCondition = DockingLayoutCondition::ApplicationStart.\n In other cases, the ID may be cached by ImGui himself at the first run,\n and HelloImGui will *not* know it on subsequent runs!") + " `optional dockSpaceIdFromName(const std::string& dockSpaceName)`:\n returns the ImGuiID corresponding to the dockspace with this name") ; @@ -1273,6 +1273,16 @@ void py_init_module_hello_imgui(py::module& m) m.def("current_layout_name", HelloImGui::CurrentLayoutName, "`CurrentLayoutName()`: returns the name of the current layout"); + m.def("add_dockable_window", + HelloImGui::AddDockableWindow, + py::arg("dockable_window"), py::arg("force_dockspace") = false, + " `AddDockableWindow()`: will add a dockable window to the current layout.\n Will dock the window to the dockspace it belongs to if forceDockspace is True,\n otherwise will dock it to the last space it was docked to (using saved settings)"); + + m.def("remove_dockable_window", + HelloImGui::RemoveDockableWindow, + py::arg("dockable_window_name"), + " `RemoveDockableWindow()`: will remove a dockable window from the current layout.\n (dockableWindowName is the label of the window, as provided in the DockableWindow struct)"); + m.def("save_user_pref", HelloImGui::SaveUserPref, py::arg("user_pref_name"), py::arg("user_pref_content"), diff --git a/external/hello_imgui/hello_imgui b/external/hello_imgui/hello_imgui index 95531caa..cb89a2e4 160000 --- a/external/hello_imgui/hello_imgui +++ b/external/hello_imgui/hello_imgui @@ -1 +1 @@ -Subproject commit 95531caa22be48dca5076869ac038b6485d41430 +Subproject commit cb89a2e4a8f11abc4e9905734d3f4209ef25cb1c