New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Table range select #7424
Comments
Have you tried the I know Omar is looking for feedback on it, and in the near future it should be the canonical way to handle what you're doing. It can be merged into docking with some minor conflict resolution. |
I need couple days to try it :) |
This feature looks very promising. But actually i don't know if there is posibility to select input widgets i.e. InputScalar?. Also i have some strange behavior during rectangle selection (video) Nagrywanie.2024-04-18.134417.mp4
|
Thank you for your thoughtful and careful repro, I will investigate it. An |
Note how you are using "y + x * 16" everywhere, meaning your selectables are not submitted in the same sequential order as their value, and by default [A] If you instead use: //int idx = y + x * 16; // Broken
int idx = x + y * 16; // OK (and change all values to use Note the value order now goes left-to-right, top-to-bottom: Then it works, but note that shift+down/up assume a type of selection that's not necessarily what you want here (I think we may need a flag to make shift+select use 2d coordinates rather than sequential?). That's the case for all three alternatives. [B] Alternatively, you change change the idx->stored selection id mapping: selection.AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage*, int idx)
{
int x = idx % 16;
int y = idx / 16;
return (ImGuiID)(y + x * 16);
}; int idx = x + y * 16; // Submission index
int id = y + x * 16; // ID (== selection.AdapterIndexToStorageId(idx))
//IM_ASSERT(selection.AdapterIndexToStorageId(&selection, idx) == id);
[...]
ImGui::PushID(idx); // <-- here it doesn't matter which you use as long as it is unique
[...]
ImGui::SetNextItemSelectionUserData(idx); // <-- here you pass index
[...]
bool IsSelected = selection.Contains((ImGuiID)(id)); // <-- Stored selection ID, == selection.AdapterIndexToStorageId(idx) [C] A third alternative would to submit items in the same order as the id you want to use. aka fill entire column first, but it may be harder to perform clipping there. ( This is really useful feedback as I found two things to improve already. Thanks! |
Pushed a better fix d60299d for both ScopeWindow and ScopeRect cases. |
Yes exactly. I need to select cells and be able to change them to same value, increase all or even extrapolate (smooth) |
I think in this case it makes sense to display and focus a single |
Is this possible to draw this InputText Over Selectable? |
Yes, you need to pass See |
I am going to try working on a simple demo to demonstrate a grid with text editable items that allows multi-write like this. |
I wrote a draft of it but it doesn't allow to multi-edit as currently multi-select system has a bias toward unselecting others when e.g. pressing enter on an item, so may need an improvement of multi-select. void DemoSelectableEditableGrid()
{
ImGui::Begin("Selection #7424");
{
const int COUNT_X = 10;
const int COUNT_Y = 16;
const int COUNT = COUNT_X * COUNT_Y;
static ImGuiSelectionBasicStorage selection;
static float data[COUNT];
static int editing_n = -1;
static int focus_n_next = -1;
// FIXME: don't clear selection when clicking selected item
ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect2d);
selection.ApplyRequests(ms_io, COUNT);
ImGui::Text("Selection: %d/%d", selection.Size, COUNT);
const int focus_n_curr = focus_n_next;
focus_n_next = -1;
if (ImGui::BeginTable("Array", COUNT_X, ImGuiTableFlags_Borders))
{
for (int n = 0; n < COUNT; n++)
{
ImGui::TableNextColumn(); // Next cell w/ auto-wrap
ImGui::PushID(n);
const bool is_selected = selection.Contains((ImGuiID)n);
ImGui::SetNextItemSelectionUserData(n);
ImVec2 p = ImGui::GetCursorScreenPos();
if (focus_n_curr == n)
ImGui::SetKeyboardFocusHere(0);
if (editing_n != n)
{
char label[64];
sprintf(label, "%g###sel", data[n]);
ImGui::Selectable(label, is_selected);
if (ImGui::IsItemClicked() && ImGui::IsMouseDoubleClicked(0))
editing_n = focus_n_next = n;
if (ImGui::IsItemFocused() && ImGui::IsKeyPressed(ImGuiKey_Enter))
editing_n = focus_n_next = n;
}
if (editing_n == n)
{
// May be easier if we had a public-facing version of TempInputXXX functions
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ImGui::GetColorU32(ImGuiCol_Header));
ImGui::SetCursorScreenPos(p);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::SetNextItemWidth(-FLT_MIN);
// FIXME: May want to use InputText() and convert empty string to 0.0f (vs InputFloat preserve value)
ImGui::InputFloat("###edit", &data[n], 0.0f, 0.0f, "%g");
if (ImGui::IsItemDeactivated())
{
editing_n = -1;
if (ImGui::IsItemFocused() && !ImGui::IsMouseClicked(0))
focus_n_next = n;
}
ImGui::PopStyleVar();
}
ImGui::PopID();
}
ImGui::EndTable();
}
ms_io = ImGui::EndMultiSelect();
selection.ApplyRequests(ms_io, COUNT);
}
ImGui::End();
} Honestly this is the kind of thing where there are lots of subtleties which are not trivial to get right/perfect with dear imgui, so it'll require more work. It'll be an interesting demo. |
Hello Thank @ocornut for Your reply. I think it is almost done.... One bad thing is that i have changed a little ImGui source code. This should be done in more sophisticated way. table.mp4
In Source code i just commented out clear request when focus is lost.
|
This is not specifically when focus is lost but when LEAVING the current scope. |
It was the easiest way to keep selection after enter pressed and switch focus to InputFloat |
OK so that's a workaround but I will find a way to design a solution for it. Thanks for clarifying! |
Version/Branch of Dear ImGui:
Version 1.90.1, Branch: docking
Back-ends:
imgui_impl_win32.cpp + imgui_impl_opengl3.cpp
Compiler, OS:
Windows 11 + GCC 12.2.0
Full config/build information:
No response
Details:
I have question what is best method to implement range select in table.
I have to implement table with scalar input. In this table I need to be able to select an area and change the values in all selected cells.
Also I have to know which cells have been changed.
At this moment i pass to my function vectors that hold cell state.
Problems:
Maybe someone have some ideas how to improve my implementation?
Screenshots/Video:
table.mp4
Minimal, Complete and Verifiable Example code:
The text was updated successfully, but these errors were encountered: