#84

Clicking on popup elements

OpenWhatWhatzopened 1y ago

Hi pretty new to this project. Got a small question: I want to click on the Close Button that is part of a Popup described as follow

ImGui::Begin("Test", nullptr, ImGuiWindowFlags_NoSavedSettings);
ImGui::Text("Hello, automation world");
if (ImGui::Button("Open")) ImGui::OpenPopup("Popup");

if (ImGui::BeginPopup("Popup"))
{
    ImGui::Text("This is text in popup");

    if (ImGui::Button("Close")) ImGui::CloseCurrentPopup();

    ImGui::EndPopup();
}
ImGui::End();

To emulate a click I intuitively wrote the following:

ctx->SetRef("Test");
ctx->ItemClick("Open");
ctx->Sleep(1);
ctx->ItemClick("Popup/Close");

However, this throws that '//Test/Popup/Close' is not a valid path I don t want to use the //$FOCUSED as I want to make my test case as clear as possible

I checked how Popups are tested in the suite and found the following solution:

ctx->SetRef("Test");
ctx->ItemClick("Open");
ctx->Sleep(1);
ImGuiWindow* popup = NULL;
popup = ctx->GetWindowByRef(ctx->PopupGetWindowID("//Test/Popup"));
ctx->SetRef(popup->Name);
ctx->ItemClick("Close")

I understand that popup->Name is //Test/Popup_[numbers] but why this behavior? Why does ctx->SetRef(//Test/Popup); not refence the popup but ctx->PopupGetWindowID("//Test/Popup") points to it? Am I using the first example incorrectly?

Activity

2
ocornut1y ago

However, this throws that '//Test/Popup/Close' is not a valid path

The popup is not a child of the "Test" window. The confusion stem from the fact that the popup identifier will hash the current top of ID stack which in this case is ImHashStr("Test").

I don't want to use the //$FOCUSED as I want to make my test case as clear as possible

It's currently the simplest and easiest way tho.

I understand that popup->Name is //Test/Popup_[numbers] but why this behavior? Why does ctx->SetRef(//Test/Popup); not refence the popup but ctx->PopupGetWindowID("//Test/Popup") points to it? Am I using the first example incorrectly?

The popup->Name is not "//Test/Popup_[numbers]" it is "##Popup_[Numbers]" where numbers is a hash of the current top of the ID stack followed by popup name, effectively ImHash("Test" "Popup") here.

This is how PopupGetWindowID() is implemented:

ImGuiID ImGuiTestContext::PopupGetWindowID(ImGuiTestRef ref)
{
    Str30f popup_name("//##Popup_%08x", GetID(ref));
    return GetID(popup_name.c_str());
}

Note that your code is a bit more complicated than necessary:

  • ctx->PopupGetWindowID("//Test/Popup") can be ctx->PopupGetWindowID("Popup") since you already did a SetRef() above.
  • the next SetRef() can take a ImGuiWindow* pointer or even the ID directly

So

ImGuiWindow* popup = NULL;
popup = ctx->GetWindowByRef(ctx->PopupGetWindowID("//Test/Popup"));
ctx->SetRef(popup->Name);

Can be:

ctx->SetRef(ctx->PopupGetWindowID("Popup"));

I don't have a general great answer now: there are complications and mangling issues related to Popups, Tables, and Child Windows that are currently surfaced to the user and ideally would not. Open issues under the label [named references] list those.

I will need to come up with a design to clarify and simplify this so you don't need to be thinking so hard about what's under the hood, but I don't have a satisfying solution yet.

ocornut1y ago

While looking at @mgerhardy tests, I found: https://github.com/vengi-voxel/vengi/blob/2a34c5a770959b4b1da721bb2b2afaecd58db835/src/tools/voxedit/modules/voxedit-ui/tests/MainWindowTest.cpp#L37

ctx->SetRef(POPUP_TITLE_UNSAVED);
ctx->ItemClick("###Yes");

Which initially surprised me, but it turns out that: https://github.com/vengi-voxel/vengi/blob/2a34c5a770959b4b1da721bb2b2afaecd58db835/src/tools/voxedit/modules/voxedit-ui/WindowTitles.h#L32

#define POPUP_TITLE_UNSAVED "###unsavedpopup"
const core::String title = makeTitle(_("Unsaved Changes"), POPUP_TITLE_UNSAVED_SCENE);
ImGui::OpenPopup(POPUP_TITLE_UNSAVED);

It is a little trick that append a "###" style end to the name which effectively clear the previous internal name. It's a neat workaround for now.