imgui icon indicating copy to clipboard operation
imgui copied to clipboard

Read-only / Disabled widgets

Open heroboy opened this issue 9 years ago • 61 comments

heroboy avatar May 08 '15 12:05 heroboy

+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

andoma avatar Sep 02 '15 08:09 andoma

Which widget in particular are you using it for?

ocornut avatar Sep 02 '15 08:09 ocornut

Typically sliders and buttons

image

vs

image

(this is with adjusting global alpha)

andoma avatar Sep 02 '15 09:09 andoma

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".

ocornut avatar Sep 04 '15 13:09 ocornut

Just the interaction-parts is perfectly sufficient for me.

Btw, thanks for all your awesome work on this.

andoma avatar Sep 07 '15 06:09 andoma

In our software I've been handling the disabled state myself, "wrapping" existing imgui calls.

Pagghiu avatar Sep 07 '15 09:09 Pagghiu

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?

ocornut avatar Sep 07 '15 22:09 ocornut

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.

heroboy avatar Sep 08 '15 01:09 heroboy

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 avatar Sep 08 '15 07:09 ocornut

@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 :)

benvanik avatar Sep 08 '15 23:09 benvanik

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.

ocornut avatar Sep 09 '15 08:09 ocornut

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.

disabled-override

Probably won't affect this task here, but I wanted to share that it may be also a viable idea in some cases.

ocornut avatar Sep 10 '15 16:09 ocornut

@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.

ocornut avatar Sep 13 '15 09:09 ocornut

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.

r-lyeh-archived avatar Aug 13 '16 23:08 r-lyeh-archived

+1 on the general idea of a disabled state :)

teamimx avatar Aug 16 '16 07:08 teamimx

https://github.com/ocornut/imgui/compare/master...leftspace89:master

thx for information :)

leftspace89 avatar Feb 05 '17 20:02 leftspace89

@leftspace89 By chance, could you make a patch instead of a series of images?

ratzlaff avatar Feb 06 '17 14:02 ratzlaff

+1 on the general idea of a disabled state :)

sonoro1234 avatar Feb 08 '17 16:02 sonoro1234

+1 on the general idea of a disabled state

qimmer avatar Feb 19 '17 20:02 qimmer

Any update on this?

codecat avatar Mar 16 '17 00:03 codecat

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.

ldecarufel avatar Apr 05 '17 18:04 ldecarufel

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);
}

image

r-lyeh-archived avatar Sep 01 '17 11:09 r-lyeh-archived

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();
    }

disabled

ocornut avatar Oct 25 '17 07:10 ocornut

ah, i overlooked the api :)

r-lyeh-archived avatar Oct 26 '17 19:10 r-lyeh-archived

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 avatar Feb 20 '18 12:02 Cwiiis

@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.

ocornut avatar Feb 20 '18 12:02 ocornut

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)

Cwiiis avatar Feb 20 '18 13:02 Cwiiis

any update on when this feature will be exposed ? it would be very useful. Anyway thanks for all the work you do!

aerydna avatar Mar 31 '18 13:03 aerydna

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

IanButterworth avatar May 16 '19 14:05 IanButterworth

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.

x1nixmzeng avatar Jul 25 '19 20:07 x1nixmzeng