Skip to content
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

How to make hover highlighting on (many) overlapping InputTexts? #7510

Open
wolfgang371 opened this issue Apr 19, 2024 · 14 comments
Open

How to make hover highlighting on (many) overlapping InputTexts? #7510

wolfgang371 opened this issue Apr 19, 2024 · 14 comments

Comments

@wolfgang371
Copy link

Version/Branch of Dear ImGui:

1.89.9 master

Back-ends:

crsfml, 2.5.3

Compiler, OS:

gcc/crystal, Ubuntu

Full config/build information:

Dear ImGui 1.89.9 (18990)
--------------------------------
sizeof(size_t): 8, sizeof(ImDrawIdx): 2, sizeof(ImDrawVert): 20
--------------------------------
io.BackendPlatformName: imgui_impl_sfml
io.BackendRendererName: NULL
io.ConfigFlags: 0x00000000
io.ConfigInputTextCursorBlink
io.ConfigWindowsResizeFromEdges
io.ConfigMemoryCompactTimer = 60.0
io.BackendFlags: 0x00000007
 HasGamepad
 HasMouseCursors
 HasSetMousePos
--------------------------------
io.Fonts: 1 fonts, Flags: 0x00000000, TexSize: 512,64
io.DisplaySize: 1280.00,720.00
io.DisplayFramebufferScale: 1.00,1.00
--------------------------------
style.WindowPadding: 8.00,8.00
style.WindowBorderSize: 1.00
style.FramePadding: 4.00,3.00
style.FrameRounding: 0.00
style.FrameBorderSize: 0.00
style.ItemSpacing: 8.00,4.00
style.ItemInnerSpacing: 4.00,4.00

Details:

My main window consists of a spreadsheet-like bunch of cells, mostly InputTexts. I cannot use the table implementation because I have a lot of custom requirements, e.g. having rather arbitrary cell overlap.
One other requirement is that I want to have InputTexts change the color when hovered. This is rather straightforward as long as cells don't overlap, but I can't get rid of the glitches when working with overlap (e.g. neighbour cells start to get highlighted in addition).

So far I checked with SetNextItemAllowOverlap along with Dummy, InvisibleButton; I checked with Groups, I tested DrawLists.
The latter almost solving the issue, if it would let me draw a rectangle after the InputText, in between the depth of the window and the InputText - but this I also find impossible to achieve (either below the window, on the very top or at least right above the InputText).

Any help appreciated!

Screenshots/Video:

No response

Minimal, Complete and Verifiable Example code:

// Here's some code anyone can copy and paste to reproduce your issue
ImGui::Begin("Example Bug");
MoreCodeToExplainMyIssue();
ImGui::End();
@ocornut
Copy link
Owner

ocornut commented Apr 22, 2024

I don't understand your question please showcase a more concrete problem or code.

@wolfgang371
Copy link
Author

Ok, sorry, I should have been more precise. I would like to have an input_text to have a separate hover color, like many other widgets. In the following code you can find some of my attempts to get this working (all of them failing)...

# prelude
buf = ImGui::TextBuffer.new("something", 10)
color_unhovered = ImVec4.new(0.0,0.5,0.0,1.0)
color_hovered = ImVec4.new(0.5,0.0,0.0,1.0)
ImGui.push_style_color(ImGuiCol::FrameBg, color_unhovered) # used for `input_text`...
ImGui.push_style_color(ImGuiCol::FrameBgHovered, color_hovered) # ... ignored for `input_text`

# input_text hover coloring, attempt #1 (-> no hover highlighting)
pos = ImGui.get_cursor_pos
ImGui.set_next_item_allow_overlap
ImGui.input_text("##inputtext1a", buf)
pos.x += 50
pos.y += 5
ImGui.set_cursor_pos(pos)
ImGui.input_text("##inputtext1b", buf)
item_size = 

# input_text hover coloring, attempt #2 (-> highlighting either none or all items under mouse)
pos = ImGui.get_cursor_pos
# ImGui.set_next_item_allow_overlap # if used, invisible_button will never be highlighted, since it will be fully covered by the input_text
ImGui.invisible_button("##invisiblebutton2a", ImGui.get_item_rect_size)
# ImGui.dummy(ImGui.get_item_rect_size) # disrespects ImGui.set_next_item_allow_overlap; all four set intersections for the two input_texts are highlighted (0/first/second/both)
color = (ImGui.is_item_hovered ? color_hovered : color_unhovered)
ImGui.set_cursor_pos(pos)
ImGui.set_next_item_allow_overlap
ImGui.push_style_color(ImGuiCol::FrameBg, color)
ImGui.input_text("##inputtext2a", buf)
ImGui.pop_style_color
pos.x += 50
pos.y += 5
ImGui.set_cursor_pos(pos)
# ImGui.set_next_item_allow_overlap # if used, invisible_button will never be highlighted, since it will be fully covered by the input_text
ImGui.invisible_button("##invisiblebutton2b", ImGui.get_item_rect_size)
# ImGui.dummy(ImGui.get_item_rect_size) # disrespects ImGui.set_next_item_allow_overlap; all four set intersections for the two input_texts are highlighted (0/first/second/both)
color = (ImGui.is_item_hovered ? color_hovered : color_unhovered)
ImGui.set_cursor_pos(pos)
ImGui.set_next_item_allow_overlap
ImGui.push_style_color(ImGuiCol::FrameBg, color)
ImGui.input_text("##inputtext2b", buf)
ImGui.pop_style_color

# input_text hover coloring, attempt #3 (-> highlighting either none or all items under mouse))
# any usage of the is_item_hovered optional arguments yields either of the two results of above
# (code omitted)

# input_text hover coloring, attempt #4 (-> no hover highlighting)
pos = ImGui.get_cursor_pos
ImGui.set_next_item_allow_overlap # assuming the following group _should_ be overlappable with whatever follows after the group
ImGui.group do
    ImGui.set_next_item_allow_overlap # assuming it _should_ work inside the group only
    ImGui.invisible_button("##invisiblebutton4a", ImGui.get_item_rect_size)
    color = (ImGui.is_item_hovered ? color_hovered : color_unhovered)
    ImGui.set_cursor_pos(pos)
    ImGui.push_style_color(ImGuiCol::FrameBg, color)
    ImGui.input_text("##inputtext4a", buf)
    ImGui.pop_style_color
end
pos.x += 50
pos.y += 5
ImGui.set_cursor_pos(pos)
ImGui.group do
    ImGui.set_next_item_allow_overlap # if used, invisible_button will never be highlighted, since it will be fully covered by the input_text
    ImGui.invisible_button("##invisiblebutton4b", ImGui.get_item_rect_size)
    color = (ImGui.is_item_hovered ? color_hovered : color_unhovered)
    ImGui.set_cursor_pos(pos)
    ImGui.push_style_color(ImGuiCol::FrameBg, color)
    ImGui.input_text("##inputtext4b", buf)
    ImGui.pop_style_color
end

# input_text hover coloring, attempt #5
# using ImGui.get_foreground_draw_list.add_rect_filled (-> text unreadable)
# using ImGui.get_background_draw_list.add_rect_filled (-> coloring under window / window alpha)
# using ImGui.get_window_draw_list.add_rect_filled (-> same issue as with the invisible_buttons above)
# (code omitted)

# prologue
ImGui.pop_style_color(2)

The thing about the "many" overlapping items: the only thing left I could think of, is storing the hover states for the next frame, which I disliked if I have "many" items to keep track of. But, of course, this "workaround" would be bad design to start with, since it would always be off one frame - and the corresponding mouse movement...

@ocornut
Copy link
Owner

ocornut commented Apr 23, 2024

Ok, sorry, I should have been more precise. I would like to have an input_text to have a separate hover color, like many other widgets.

Linking to #3411 for tracking. Indeed InputText() doesn't use FrameBgHovered currently.

This is very much a XY Problem here and you seem to have gone quite deep and far into the workaround.

Let's move this to #3411.

@ocornut
Copy link
Owner

ocornut commented Apr 23, 2024

I'll close this. Will keep #7515 open as it raises a very specific issue, which is rather complex to solve, but I eventually would like to. I will however lower its priority considering its report is not motivated by a use case that you really need IMHO. Better working on #3411.

@ocornut ocornut closed this as completed Apr 23, 2024
@wolfgang371
Copy link
Author

Thanks for picking it up; but no, not an XY problem (you caught me once on this already ) - this here was the first issue I raised; the others I posted later, because I thought you might be interested in them independently 😄

@ocornut ocornut reopened this Apr 23, 2024
@ocornut
Copy link
Owner

ocornut commented Apr 23, 2024

Can you clarify? It seems like your issue is to colorize the frame of an InputText() when hovered, in which case that should be the first issue to raise?

A slightly saner workaround, for being simple, might be:

if (g.HoveredIdPreviousFrame == ImGui::GetID("YourInputText"))
    PushStyleColor(...);

@wolfgang371
Copy link
Author

Hm. I called it "How to make hover highlighting on (many) overlapping InputTexts" and in the first post I also wrote "One other requirement is that I want to have InputTexts change the color when hovered. This is rather straightforward as long as cells don't overlap".

So veeery strictly speaking you say, I should have raised a ticket for general InputText hover highlighting. This would probably have resulted in one of my attempts; which all fail for overlapping cases. That's why I included it in the first place...

@wolfgang371
Copy link
Author

Thanks for your proposal, I will have a look!

Can you clarify? It seems like your issue is to colorize the frame of an InputText() when hovered, in which case that should be the first issue to raise?

A slightly saner workaround, for being simple, might be:

if (g.HoveredIdPreviousFrame == ImGui::GetID("YourInputText"))
    PushStyleColor(...);

@wolfgang371
Copy link
Author

The context structure is part of ImGui's internals; I think I don't have access to it via the Crystal wrapper

@ocornut
Copy link
Owner

ocornut commented Apr 24, 2024

Hm. I called it "How to make hover highlighting on (many) overlapping InputTexts" and in the first post I also wrote "One other requirement is that I want to have InputTexts change the color when hovered. This is rather straightforward as long as cells don't overlap".
So veeery strictly speaking you say, I should have raised a ticket for general InputText hover highlighting. This would probably have resulted in one of my attempts; which all fail for overlapping cases. That's why I included it in the first place...

Can you provide more context and images about your use case, in term or when and how you need to overlap?

I am not sure how to would trivially achieve an excel like setup with e.g. merged cell. I assume it should be possible but honestly I'd recommend implementing the whole thing as one custom canvas/widget and then submitting e.g. InputText() only when something is edited. Closer to what I did here: #7424 (comment)

The context structure is part of ImGui's internals; I think I don't have access to it via the Crystal wrap

🤷

@wolfgang371
Copy link
Author

Hm. I called it "How to make hover highlighting on (many) overlapping InputTexts" and in the first post I also wrote "One other requirement is that I want to have InputTexts change the color when hovered. This is rather straightforward as long as cells don't overlap".
So veeery strictly speaking you say, I should have raised a ticket for general InputText hover highlighting. This would probably have resulted in one of my attempts; which all fail for overlapping cases. That's why I included it in the first place...

Can you provide more context and images about your use case, in term or when and how you need to overlap?

Ok, not sure if you will gain something from it, but here you go: this is a 3x3 matrix, all cells equal size, but scrolled to an overlapping state. You will see several glitches here (frame glitch with missing highlighting, overlapping highlighting of two or four cells):
imgui-hover-issue

I am not sure how to would trivially achieve an excel like setup with e.g. merged cell. I assume it should be possible but honestly I'd recommend implementing the whole thing as one custom canvas/widget and then submitting e.g. InputText() only when something is edited. Closer to what I did here: #7424 (comment)

Merged cells currently I don't support (yet). Thanks for the link, you're dynamically switching between Selectable and InputFloat, I see.

The context structure is part of ImGui's internals; I think I don't have access to it via the Crystal wrap

🤷

Sure...

@ocornut
Copy link
Owner

ocornut commented Apr 24, 2024

Ok, not sure if you will gain something from it, but here you go: this is a 3x3 matrix, all cells equal size, but scrolled to an overlapping state. You will see several glitches here (frame glitch with missing highlighting, overlapping highlighting of two or four cells):

I think what you are trying to achieve is too advanced to want to use AllowOverlap for it.
You may want to handle hit-testing yourself and things will be simpler.
If we eventually add support for column spanning (#3565) it might become possible for you to use tables, but right now it's not possible.

Merged cells currently I don't support (yet).

If you don't support them you could use tables for this.
If you are trying to reimplement tables I am afraid you are on your own. My own implementation has been the result of many months of work and iterations, but I simultaneously have no doubt it is possible to come up with a much simpler version if you take some shortcuts and aren't too regarding or certain performances constraints (per-frame allocs, drawcalls).

🤷
Sure...

I mean, I would encourage you to see if you can allow exposing more in your language, or at least allow a path for custom exposure of the data you need via a custom helper C function?

@wolfgang371
Copy link
Author

I'm pretty much done with my implementation, the only thing left for the time being is the overlap thing. I'll leave it for the time being.
I was thinking about using tables but then gave up the concept since I need (1) clipping in both dimensions, (2) a very flexible column/row fixing and (3) for it to work on a sparse data structure, just to name a few topics. Also, standard drag-and-drop didn't work out for me, in the picture you actually see my own version of it.

@wolfgang371
Copy link
Author

🤷
Sure...

I mean, I would encourage you to see if you can allow exposing more in your language, or at least allow a path for custom exposure of the data you need via a custom helper C function?

Actually I'm still waiting on @oprypin supporting your newest version on Crystal (hi!); maybe there's even some support for the ImGui internals I'm not aware of...
And I'm stubbornly refusing getting back to C++; I had two projects in the past, all started in C++ and I switched the first one to Digital Mars D, the second one to Crystal - and since the latter I was never happier! 😄 But, of course, that's just me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants