Comments (17)
Have you tried the range_select
branch to see if it meets your needs?
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.
from imgui.
I need couple days to try it :)
from imgui.
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
ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_ClearOnClickVoid | ImGuiMultiSelectFlags_BoxSelect2d);
static ImGuiSelectionBasicStorage selection;
selection.ApplyRequests(ms_io, 16*16);
ImGui::Text("Selection: %d/%d", selection.Size, 16*16);
if ( ImGui::BeginTable("MAP NEW", 16, flags) ) {
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImGui::GetStyleColorVec4(ImGuiCol_ChildBg));
for(int y=0; y<16; y++) {
ImGui::TableNextRow();
for(int x=0; x<16; x++) {
ImGui::TableNextColumn();
ImGui::PushID(y+x*16);
ImGui::SetNextItemWidth(50.0);
bool IsSelected = selection.Contains((ImGuiID)(y+x*16));
ImGui::SetNextItemSelectionUserData(y+x*16);
if(IsSelected) {
ImGui::PushStyleColor(ImGuiCol_FrameBg, IM_COL32(0, 130, 216, 50));
}
char label[64];
sprintf(label, "%d", y+x*16);
ImGui::Selectable(label, IsSelected);
//ImGui::Text(label);
//ImGui::Checkbox(label, (bool*)&data[y][x]);
/*if (ImGui::InputScalar("##Data", ImGuiDataType_Float, &data[y][x], NULL, NULL, "%.2f", ImGuiInputTextFlags_EnterReturnsTrue) ) {
dataToSet = data[y][x];
}*/
if(IsSelected) {
ImGui::PopStyleColor();
}
ImGui::PopID();
}
}
ImGui::PopStyleColor();
ImGui::EndTable();
}
ms_io = ImGui::EndMultiSelect();
selection.ApplyRequests(ms_io, 16*16);
from imgui.
I am going to try working on a simple demo to demonstrate a grid with text editable items that allows multi-write like this.
from imgui.
Thank you for your thoughtful and careful repro, I will investigate it.
An InputScalar()
is not selectable but I'm not sure what it would mean to select it.
Would the underlying intent to e.g. select many fields and type in all of them together ?
from imgui.
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 ImGuiSelectionBasicStorage
assume that value passed to ImGui::SetNextItemSelectionUserData()
are interpolable indices.
[A] If you instead use:
//int idx = y + x * 16; // Broken
int idx = x + y * 16; // OK
(and change all values to use idx
)
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.
(
I also found an issue when using box-select in a window that is not a child window.
The current logic prevents focusing, steals hovers and nav id. I pushed a mitigation (a304677) to allow clicking on title bar at least, and will need to revisit some of the logic for box-select.
)
This is really useful feedback as I found two things to improve already. Thanks!
from imgui.
(I also found an issue when using box-select in a window that is not a child window.
The current logic prevents focusing, steals hovers and nav id. I pushed a mitigation to allow clicking on title bar at least, and will need to revisit some of the logic for box-select.)
Pushed a better fix d60299d for both ScopeWindow and ScopeRect cases.
from imgui.
Thank you for your thoughtful and careful repro, I will investigate it.
An
InputScalar()
is not selectable but I'm not sure what it would mean to select it. Would the underlying intent to e.g. select many fields and type in all of them together ?
Yes exactly. I need to select cells and be able to change them to same value, increase all or even extrapolate (smooth)
from imgui.
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 InputText()
widget, and when edited apply the value to all of selection.
Aka you don't need (and you cannot have) multiple active InputText()
, but one can represent the selection.
from imgui.
Is this possible to draw this InputText Over Selectable?
from imgui.
Yes, you need to pass ImGuiSelectableFlags_AllowOverlap
to the `Selectable().
See Demo->Layout->Overlap Mode
or Demo->Widgets->Selectables->Rendering more items on the same line
from imgui.
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.
from imgui.
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
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;
static bool set_flag = false;
static bool change_flag = false;
float change = 0.0f;
// FIXME: don't clear selection when clicking selected item
ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(
ImGuiMultiSelectFlags_ClearOnEscape
| ImGuiMultiSelectFlags_BoxSelect2d
| ImGuiMultiSelectFlags_ClearOnClickVoid
);
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))
{
if(ImGui::IsKeyPressed(ImGuiKey_KeypadAdd)) {
change_flag = true;
change = 1.0f;
}
else if(ImGui::IsKeyPressed(ImGuiKey_KeypadSubtract)) {
change_flag = true;
change = -1.0f;
}
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);
char label[64];
sprintf(label, "%g###sel", data[n]);
ImGui::SetNextItemAllowOverlap();
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::SetKeyboardFocusHere(0);
ImGui::InputFloat("###edit", &data[n], 0.0f, 0.0f, "%g");
if (ImGui::IsItemDeactivated())
{
set_flag = true;
change = data[n];
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);
if(set_flag) {
set_flag = false;
for(int n = 0; n < COUNT; n++) {
if(selection.Contains((ImGuiID)n) ) {
data[n] = change;
}
}
}
if(change_flag) {
change_flag = false;
for(int n = 0; n < COUNT; n++) {
if(selection.Contains((ImGuiID)n) ) {
data[n] += change;
}
}
}
}
ImGui::End();
}
In Source code i just commented out clear request when focus is lost. ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags)
in imgui_widgets.cpp
else if (g.NavJustMovedFromFocusScopeId == ms->FocusScopeId)
{
// Also clear on leaving scope (may be optional?)
if ((ms->KeyMods & (ImGuiMod_Ctrl | ImGuiMod_Shift)) == 0 && (flags & (ImGuiMultiSelectFlags_NoAutoClear | ImGuiMultiSelectFlags_NoAutoSelect)) == 0) {
//request_clear = true;
}
}
from imgui.
In Source code i just commented out clear request when focus is lost. ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags) in imgui_widgets.cpp
This is not specifically when focus is lost but when LEAVING the current scope.
Can you clarify why you want/need to disable it? (then I can see if it's worth adding an option for it)
from imgui.
In Source code i just commented out clear request when focus is lost. ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags) in imgui_widgets.cpp
This is not specifically when focus is lost but when LEAVING the current scope. Can you clarify why you want/need to disable it? (then I can see if it's worth adding an option for it)
It was the easiest way to keep selection after enter pressed and switch focus to InputFloat
from imgui.
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!
from imgui.
else if (g.NavJustMovedFromFocusScopeId == ms->FocusScopeId)
{
// Also clear on leaving scope (may be optional?)
if ((ms->KeyMods & (ImGuiMod_Ctrl | ImGuiMod_Shift)) == 0 && (flags & (ImGuiMultiSelectFlags_NoAutoClear | ImGuiMultiSelectFlags_NoAutoSelect)) == 0) {
//request_clear = true;
}
}
It's interesting because the logic in my code triggers the NavJustMovedToFocusScopeId
block, while the logic in yours triggers the NavJustMovedFromFocusScopeId
block. Will need further research before I can design a proper flag.
from imgui.
Related Issues (20)
- Delay in Combo Popup Opening with glfwWaitEventsTimeout HOT 4
- Where's the binaries? HOT 4
- Mouse scrolling not working HOT 6
- Imgui community HOT 1
- Rendering vertices with the D3DPT_LINESTRIP type. HOT 1
- Can't access some stuff from imgui.h HOT 1
- Suggestion: Consider Adding Title Bar Text to Popups HOT 2
- SDL3 Multi-Viewports not creating windows when main window is hidden
- Recommended way to expand / collapse tree nodes with keyboard shortcuts? HOT 3
- VuIkan: invalid Dynamic Rendering functions from the Instance-level loader HOT 3
- Text Bottom Padding Bug HOT 1
- Power savings & hardware usage HOT 3
- Add RGFW backend implementation HOT 2
- Text wrapping: how does it work? HOT 1
- ImDrawList rects aren't perfect HOT 7
- Running ImGui app on Arm Processor (Allwinner H3 with mali 400 -> orangepi one) HOT 1
- Can no longer use ctrl shortcuts in InputText's as of v1.90.6 HOT 4
- ImGui::BeginTooltip() should allow specifying override HOT 4
- No Hover Flags in ImGui::IsAnyItemHovered() HOT 4
- Keeping combo open after clicking selectable
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from imgui.