imgui
imgui copied to clipboard
Read-only / Disabled widgets
+1 on this, currently i just decrease alpha to make it look disabled but widgets still respond to events (obviously). Would be nice to have this built-in
Which widget in particular are you using it for?
Typically sliders and buttons
vs
(this is with adjusting global alpha)
Probably rather low-priority. There's two aspects to it - the interaction and the rendering. The interaction is probably easy to sort out. Outside api to be based on PushButtonRepeat()/PopButtonRepeat() (storing a bool + a stack) and check it in the right spot.
The rendering side is more work because we ought to decide on the design here, how are disabled state represented in general, how it can be part of the theme in a sensible lightweight manner without adding dozens of new entries into the theme system that the user would have to manipulate. Perhaps the theme system can compute certain colors based on HSV space operations and store that so widgets code don't have to do those calculation. e.g. we'd have a Colors[] array and a ColorsDisabled[] array that's auto computed. This tie somehow with some of the ground toward a potential new design (#184).
For now I suppose we could add the feature as affecting interaction only, probably wouldn't hurt but it would have to be documented as "visuals will change in a future version".
Just the interaction-parts is perfectly sufficient for me.
Btw, thanks for all your awesome work on this.
In our software I've been handling the disabled state myself, "wrapping" existing imgui calls.
Some notes. Are you looking for a "InteractionDisabled" or "EditDisabled/Readonly" flag ?
- Text box must still be selectable / copiable into clipboard.
- Scrollbar must be active? e.g. scrollbar of a listbox, of a child?
- How about tree nodes and collapsing header?
- Do we allow sliders and drags to be ctrl+clickable to be turned into a read-only text input?
- How about the mouse hovering feedback on drags (currently the background is highlighted).
- How about columns separators?
- How about buttons? If the flag is called ReadOnly vs Disabled how we expect that button works?
- Do we need separate Disabled and ReadOnly flags?
- What do IsItemHovered() returns?
I think "Disable" means disable all child widgets including the scrollbar, and preventing all mouse interactive. And only a few widget has "Readonly" flag. Readonly widget can interact as normal, but the content will not be changed. And now the readonly can easily implement in application level, for example:
float tmp = x;
ImGui::InputFloat("xxx",&x);
x = tmp;
I think this is good, because windows controls act like this.
I think read-only should be global and inherited as well, so you can easily turn an entire block into read-only and still, scroll and copy data. That solution above a bit a hacky and would show an edit flicker before the revert, it's not really satisfying enough.
@ocornut agreed - having something similar to button repeat would be nice. It'd also prevent the need for a bool disabled/bool read_only/etc on everything.
I was just running into this myself needing both read-only content and separately fully-disabled UI (no input/greyed out/etc). My hacky solution in lieu of a real one is to filter some of the mouse events in broad regions before handing them to imgui and to draw a giant semi-translucent rect over everything at the end. It's nasty :)
Alright,
I have added a ImGuiInputTextFlags_ReadOnly flag to InputText() / InputTextMultiline() as an exception because I think it is a more common use case (to make blobs of text more naturally copiable, even though you can use the logging api for that too).
We need different flag for Disabled and global- ReadOnly. Earlier is easier to implement, later probably a bit more work, as we need to dig a little more inside widgets to make sure things like IsItemHovered() works but the widget doesn't react. So probably will add Disabled early on. It will have to be documented as "unfinished" because it won't affect the visuals just you but it WILL in the future.
There's another usage pattern which I found useful in one app I made, which is to have widgets that looks disabled but are active. Here I have a set of variables that can be overriden. You can click the override checkbox but you can also directly click on disabled-lookin widget on the right-side and it automatically set the override flag as you click them. That's easily done with just changing text color.
Probably won't affect this task here, but I wanted to share that it may be also a viable idea in some cases.
@haddock07 in #330
Is there a way to disable a widget (shown but with a disabled state)? For example, I would like to have a check box, in a disabled state, where it couldn't be activated or hovered, and displayed with a darker color. Of course, the function ImGui::Checkbox would always return false. I did a workaround by setting the same color for the 3 states (normal, hovered, active), but when the user clicks on the check box, the check mark is actually shown one frame before returning to the unchecked state.
Hey,
I was looking for possible CheckboxDisabled()/RadioDisabled()/MenuItemDisabled() widgets and found this thread instead. I guess I may share some feedback.
Rather than multiplexing the workload into infinite disabled widget variants that may be (very) time consuming, my suggestion would be rather to create a single BeginDisabled()/EndDisabled(); group that pushes disable state into the stack. From this point:
a) I would expect to be able to browse still the disabled group (scrollbars and tooltips would be active), but not able to interact with any variable modifier at all (checkboxes, selectables, combos, input boxes and so on). Ie, all sub-widgets that may change the user variables shall not react to keyboard/mouse events (ever); any other will. So all my widget values are safe (constant) inside a disabled stack.
b) I would expect the rendered widgets would look similar to a blended widget+background. Achieved either by blending every sub-widget with alpha *0.5, or by doing fancy HSV to blend every rendered color with the background color.
Keep up the good work!
Edit: PS: you could store all the disabled colors variants (the (HSV+color background)/2 thing) when applying styles, so everything would be "cached" in anticipation.
+1 on the general idea of a disabled state :)
https://github.com/ocornut/imgui/compare/master...leftspace89:master
thx for information :)
@leftspace89 By chance, could you make a patch instead of a series of images?
+1 on the general idea of a disabled state :)
+1 on the general idea of a disabled state
Any update on this?
I'd just like to chime in and say that I also would like a way to disable groups of controls.
Maybe PushDisabledState()/PopDisabledState() functions would be the best, since it follows ImGui's stack-based approach.
Maybe disabled controls could simply be drawn in the monochrome version of their regular color, multiplied by a predefined color in the styles.
I just hacked it from ideas in this thread. Hovering, tooltips and input texts work as expected when disabled.
namespace ImGui {
std::vector<float> alphas;
void PushDisabled( bool disabled = true ) {
alphas.push_back( GetStyle().Alpha );
GetStyle().Alpha = disabled ? 0.25f : 1.0f;
}
void PopDisabled( int num = 1 ) {
while( num-- ) {
GetStyle().Alpha = alphas.back();
alphas.pop_back();
}
}
// Install: edit ImGui::IsMouseHoveringRect() and change return to:
// return rect_for_touch.Contains(g.IO.MousePos) && (GetStyle().Alpha >= 1);
}
I have pushed the simplest form of disabled flag, but haven't exposed it (it's in imgui_internal.h
for now)
It doesn't affect the style but you can apply an alpha multiplier fairly easily.
(Btw @r-lyeh why are you using your own stack and not PushStyleVar
which does exactly that?)
static bool disabled = false;
ImGui::Checkbox("Disable", &disabled);
if (disabled)
{
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
}
[...]
if (disabled)
{
ImGui::PopItemFlag();
ImGui::PopStyleVar();
}
ah, i overlooked the api :)
I like the solution using PushItemFlag, but it would be nice to be able to use it like you can style flags, so you could push a flag that causes items to be disabled before creating a window. If you push the item flags before creating a window now, you end up creating the debug window instead of affecting subsequent items.
@Cwiiis the existing other settings (ItemWidth, TextWrapPos) are also using a per-window stack. What's is your use case? Is it just the lack of symmetry that is a problem here? If it was a cross-window setting you may expect the window itself to be disabled?
It is tempting to consider the possibility to move more of those to a shared stack. ItemWidth however makes less sense in a shared stack since it needs a suitable default per-window and values are more likely to be based on window width.
In my use-case, I have a UI where in its 'mobile' mode, there is one main view, then a series of smaller preview windows. When you press the preview windows, they become the main view (and the main view shrinks and joins the preview windows). One of these views is a control-panel and I disable controls in it so that you can't accidentally activate anything until it's a main view.
The small issue is that without being able to disable items across windows, I need to pass a flag around a few different functions when the code that creates these windows isn't really concerned with whether or not it's disabled.
It's a good point about what the behaviour of a disabled window should be though - maybe you shouldn't be able to move it? (this particular application disables all window movement anyway, but I could imagine that being useful)
any update on when this feature will be exposed ? it would be very useful. Anyway thanks for all the work you do!
Has this functionality made it into 1.70? I noticed a mention in the release notes of the gamepad functionality that was added in https://github.com/ocornut/imgui/commit/a26085ed53d07603a9fde0e164ad69773d119642 and referenced above
Bumping for interest.
My usage is a row of several buttons I want to show on the debug window at all times:
if (ImGui::Button("Button 1")) { ... }
ImGui::SameLine();
if (ImGui::Button("Button 2")) { ... }
Exposing ButtonEx
and ImGuiButtonFlags_Disabled
does the trick, but remains part of imgui_internal and doesn't change the style.