UI: uiBut Indeterminate State #108210

Merged
Julian Eisel merged 15 commits from Harley/blender:Indeterminate into main 2023-07-17 19:37:24 +02:00
Member

Setting a new uiBut drawflag shows items in an indeterminate state,
not indicating a specific value or state.


This is needed for the Asset Shelf, but also for multi-object property editing if we ever want to make that default behavior. Properties shared between multiple objects but with differing values would show this indeterminate state. This just adds a new but->drawflag of UI_BUT_INDETERMINATE that gives different behavior:

image

image

Setting a new uiBut drawflag shows items in an indeterminate state, not indicating a specific value or state. --- This is needed for the Asset Shelf, but also for multi-object property editing if we ever want to make that default behavior. Properties shared between multiple objects but with differing values would show this indeterminate state. This just adds a new but->drawflag of UI_BUT_INDETERMINATE that gives different behavior: ![image](/attachments/322a953b-74a0-4046-a1ad-ac0c1f31a9df) ![image](/attachments/74ccb539-2050-4cd6-8b38-2c8f90c91eab)
Harley Acheson added 1 commit 2023-05-24 00:59:04 +02:00
b01d64cb91 UI: uiBut Indeterminate State
Setting a new uiBut drawflag shows items in an indeterminate state,
not indicating a specific value or state.
Harley Acheson added this to the User Interface project 2023-05-24 00:59:12 +02:00
Harley Acheson requested review from Julian Eisel 2023-05-24 00:59:22 +02:00
Harley Acheson added 1 commit 2023-05-24 01:51:52 +02:00

Better to show a dash instead of blank (cc @pablovazquez )

Better to show a dash instead of blank (cc @pablovazquez )
Harley Acheson added 1 commit 2023-06-02 21:19:22 +02:00
Author
Member

Wider "emdash" looks okay where narrow hypen looked too inconsequential.

Wider "emdash" looks okay where narrow hypen looked too inconsequential.

Fantastic, it looks much better Harley, thanks.

Could you please try to centralise the dashes everywhere? (object font, text on curve, rotation, and the drop-down)

I think it will look better (for the drop down you probably want to centralise considering the entire area, “ignoring” the arrow. Otherwise it won’t align well in the UI with the other elements.

Fantastic, it looks much better Harley, thanks. Could you please try to centralise the dashes everywhere? (object font, text on curve, rotation, and the drop-down) I think it will look better (for the drop down you probably want to centralise considering the entire area, “ignoring” the arrow. Otherwise it won’t align well in the UI with the other elements.
Harley Acheson added 1 commit 2023-06-03 19:45:12 +02:00
Harley Acheson added 1 commit 2023-06-03 20:17:14 +02:00

It looks good enough for me 👍

It looks good enough for me 👍
Julian Eisel requested changes 2023-06-08 13:08:01 +02:00
Julian Eisel left a comment
Member

The one thing I'm wondering is, should we modify the draw-string like done here, or should we handle this in widget drawing? I think using the draw string makes sense, and in testing it behaves nicely (e.g. clicking to edit text or copy/pasting still uses the actual value). @ideasman42 any concerns about that?

We also need to figure out how to set this flag properly, like, you wouldn't want to always have to set the flag manually (which involves additional checks). Probably ui_but_is_pushed_ex() should allow some 3-way state as well. But this can be done separately.

The one thing I'm wondering is, should we modify the draw-string like done here, or should we handle this in widget drawing? I think using the draw string makes sense, and in testing it behaves nicely (e.g. clicking to edit text or copy/pasting still uses the actual value). @ideasman42 any concerns about that? We also need to figure out how to set this flag properly, like, you wouldn't want to always have to set the flag manually (which involves additional checks). Probably `ui_but_is_pushed_ex()` should allow some 3-way state as well. But this can be done separately.
@ -319,1 +319,4 @@
UI_BUT_CHECKBOX_INVERT = 1 << 25,
/* Drawn in a way that indicates that the state/value is unknown. */
UI_BUT_INDETERMINATE = 1 << 26,
Member

Not sure if indeterminate is the right word. For example for the checkbox in the asset catalog selector the state is known (it's unchecked, we just want to indicate that it has checked children). Maybe UI_BUT_INDICATE_MUTLIVALUE?

Not sure if _indeterminate_ is the right word. For example for the checkbox in the asset catalog selector the state is known (it's unchecked, we just want to indicate that it has checked children). Maybe `UI_BUT_INDICATE_MUTLIVALUE`?
Harley marked this conversation as resolved
@ -3797,6 +3797,11 @@ static void ui_but_update_ex(uiBut *but, const bool validate)
}
}
if (but->drawflag & UI_BUT_INDETERMINATE) {
Member

I'd rather avoid flags that silently change other flags. Why exactly is this needed?

I'd rather avoid flags that silently change other flags. Why exactly is this needed?
Harley marked this conversation as resolved
@ -3863,2 +3868,3 @@
}
STRNCPY(but->drawstr, but->str);
if (but->drawflag & UI_BUT_INDETERMINATE) {
STRNCPY(but->drawstr, "\u2014");
Member

It's not clear what \u2014 is, better make this a named constant.

It's not clear what `\u2014` is, better make this a named constant.
Harley marked this conversation as resolved
@ -4164,0 +4177,4 @@
/* Flush the widget cache so we can draw on top. */
GPU_blend(GPU_BLEND_ALPHA);
UI_widgetbase_draw_cache_flush();
Member

We should avoid flushing the widget cache, this can introduce slowdowns (there were significant slowdowns in widget drawing in early 2.8, before adding the cache). It should be trivial to draw a line in the widget shader, without immediate mode drawing. E.g. see shape_preset_init_number_arrows().

We should avoid flushing the widget cache, this can introduce slowdowns (there were significant slowdowns in widget drawing in early 2.8, before adding the cache). It should be trivial to draw a line in the widget shader, without immediate mode drawing. E.g. see `shape_preset_init_number_arrows()`.
Harley marked this conversation as resolved
Harley Acheson added 1 commit 2023-06-09 02:17:19 +02:00
Author
Member

@JulianEisel - Not sure if indeterminate is the right word

All other uses 3-state checkboxes I have found use that word, and these include usecases that fit yours exactly. The best example is the HTML DOM where you can do things like:

var checkbox = document.getElementById("some-checkbox");
checkbox.indeterminate = true;

image

https://css-tricks.com/indeterminate-checkboxes/

Why exactly is this needed?

I added some comments, but it is to center the text and to unselect toggles.

It should be trivial to draw a line in the widget shader, without immediate mode drawing. E.g. see shape_preset_init_number_arrows()

It certainly looks trivial but so far not finding it as such. Although that function sets a vert array and face array those seem to be ignored and everything is instead done in the shader. For example you can change that tria->type from ROUNDBOX_TRIA_ARROWS to ROUNDBOX_TRIA_CHECK and a checkmark will display without changing anything else. weird.

> @JulianEisel - Not sure if indeterminate is the right word All other uses 3-state checkboxes I have found use that word, and these include usecases that fit yours exactly. The best example is the HTML DOM where you can do things like: ``` var checkbox = document.getElementById("some-checkbox"); checkbox.indeterminate = true; ``` ![image](/attachments/4fe64cb7-00c3-4a2f-af09-8ebb9d72704e) https://css-tricks.com/indeterminate-checkboxes/ > Why exactly is this needed? I added some comments, but it is to center the text and to unselect toggles. > It should be trivial to draw a line in the widget shader, without immediate mode drawing. E.g. see shape_preset_init_number_arrows() It certainly _looks_ trivial but so far not finding it as such. Although that function sets a vert array and face array those seem to be ignored and everything is instead done in the shader. For example you can change that tria->type from ROUNDBOX_TRIA_ARROWS to ROUNDBOX_TRIA_CHECK and a checkmark will display without changing anything else. weird.
3.6 KiB
Julian Eisel requested changes 2023-06-09 17:16:49 +02:00
Julian Eisel left a comment
Member

In the current patch the selected color is used with transparency. I think we should blend between the un-selected & selected color instead. Otherwise it would look weird if the region background is drastically different from the widget inner color.

All other uses 3-state checkboxes I have found use that word, and these include usecases that fit yours exactly.

I personally still don't really like that term, or at least would prefer what I suggested earlier. But fair enough, the commonality may be worthwhile.

It certainly looks trivial but so far not finding it as such. Although that function sets a vert array and face array those seem to be ignored and everything is instead done in the shader. For example you can change that tria->type from ROUNDBOX_TRIA_ARROWS to ROUNDBOX_TRIA_CHECK and a checkmark will display without changing anything else. weird.

AFAICS the new shape needs to be added both in the C code and in the shader. Maybe best if you ask @fclem for help.

In the current patch the selected color is used with transparency. I think we should blend between the un-selected & selected color instead. Otherwise it would look weird if the region background is drastically different from the widget inner color. > All other uses 3-state checkboxes I have found use that word, and these include usecases that fit yours exactly. I personally still don't really like that term, or at least would prefer what I suggested earlier. But fair enough, the commonality may be worthwhile. > It certainly _looks_ trivial but so far not finding it as such. Although that function sets a vert array and face array those seem to be ignored and everything is instead done in the shader. For example you can change that tria->type from ROUNDBOX_TRIA_ARROWS to ROUNDBOX_TRIA_CHECK and a checkmark will display without changing anything else. weird. AFAICS the new shape needs to be added both in the C code and in the shader. Maybe best if you ask @fclem for help.
@ -3789,2 +3789,4 @@
double value = UI_BUT_VALUE_UNSET;
/* Use emdash in place of text when in indeterminate state. */
const char *emdash = "\u2014";
Member

emdash isn't really useful either, this should be more descriptive. Would suggest something like UI_VALUE_INDETERMINATE_CHAR.

`emdash` isn't really useful either, this should be more descriptive. Would suggest something like `UI_VALUE_INDETERMINATE_CHAR`.
Harley marked this conversation as resolved
@ -3798,2 +3801,4 @@
}
if (but->drawflag & UI_BUT_INDETERMINATE) {
/* Center text. */
Member

These comments only explain what it does which is obvious from the code. But why does it do this? And for which button types?

These comments only explain what it does which is obvious from the code. But why does it do this? And for which button types?
Harley marked this conversation as resolved
Harley Acheson added 2 commits 2023-06-26 23:32:50 +02:00
Julian Eisel requested changes 2023-07-04 17:38:23 +02:00
@ -3789,2 +3790,4 @@
double value = UI_BUT_VALUE_UNSET;
/* Use emdash in place of text when in indeterminate state. */
const char *UI_VALUE_INDETERMINATE_CHAR = "\u2014";
Member

Would put this in UI_interface.h, together with other defines like UI_SEP_CHAR_S.

Would put this in `UI_interface.h`, together with other defines like `UI_SEP_CHAR_S`.
Harley marked this conversation as resolved
@ -3791,2 +3795,4 @@
ui_but_update_select_flag(but, &value);
if ((but->drawflag & UI_BUT_INDETERMINATE) && (but->flag & UI_SELECT)) {
but->flag &= ~UI_SELECT;
Member

I still can't see an explanation on why this is done, only what it does. Testing the patch, when I simply enable UI_BUT_INDETERMINATE for all buttons, I get a whole bunch of interaction issues/glitches. That is because UI_SELECT is supposed to impact the behavior, not just the drawing.

I guess this should only affect drawing (it's controlled by a draw flag after all), so this should probably be done in ui_draw_but(). At the end of that we already do similar things to safely manipulate flags for drawing.

I still can't see an explanation on _why_ this is done, only what it does. Testing the patch, when I simply enable `UI_BUT_INDETERMINATE` for all buttons, I get a whole bunch of interaction issues/glitches. That is because `UI_SELECT` is supposed to impact the behavior, not just the drawing. I guess this should only affect drawing (it's controlled by a draw flag after all), so this should probably be done in `ui_draw_but()`. At the end of that we already do similar things to safely manipulate flags for drawing.
Harley marked this conversation as resolved
@ -3864,1 +3872,3 @@
STRNCPY(but->drawstr, but->str);
if (but->drawflag & UI_BUT_INDETERMINATE) {
STRNCPY(but->drawstr, UI_VALUE_INDETERMINATE_CHAR);
but->drawflag &= ~(UI_BUT_TEXT_LEFT | UI_BUT_TEXT_RIGHT);
Member

Same here, not sure if we should permanently modify the drawing flags here. Can be done just before drawing.

Actually, let's not even override the draw-string here, and just do that in widget_draw_text() by setting drawstr to UI_VALUE_INDETERMINATE_CHAR for specific button types.

Same here, not sure if we should permanently modify the drawing flags here. Can be done just before drawing. Actually, let's not even override the draw-string here, and just do that in `widget_draw_text()` by setting `drawstr` to `UI_VALUE_INDETERMINATE_CHAR` for specific button types.
Harley marked this conversation as resolved
Harley Acheson added 2 commits 2023-07-13 21:19:40 +02:00
Harley Acheson added 1 commit 2023-07-13 21:23:11 +02:00
Harley Acheson added 1 commit 2023-07-13 21:58:05 +02:00
Harley Acheson added 1 commit 2023-07-14 00:59:03 +02:00
Julian Eisel reviewed 2023-07-14 14:49:51 +02:00
@ -5032,6 +5070,10 @@ void ui_draw_but(const bContext *C, ARegion *region, uiStyle *style, uiBut *but,
state.but_flag &= ~UI_BUT_OVERRIDDEN;
}
if ((state.but_drawflag & UI_BUT_INDETERMINATE) && (state.but_flag & UI_SELECT)) {
Member

I'd remove the && (state.but_flag & UI_SELECT) part, just makes the logic look unnecessarily complex.

I'd remove the ` && (state.but_flag & UI_SELECT)` part, just makes the logic look unnecessarily complex.
Harley marked this conversation as resolved
Julian Eisel reviewed 2023-07-14 15:21:32 +02:00
@ -1930,0 +1946,4 @@
UI_BTYPE_TEXT,
UI_BTYPE_SEARCH_MENU))
{
STRNCPY(but->drawstr, UI_VALUE_INDETERMINATE_CHAR);
Member

Do not modify but->drawstr here, the function shouldn't have such side effects. Modify the local drawstr instead.

Do not modify `but->drawstr` here, the function shouldn't have such side effects. Modify the local `drawstr` instead.
Harley marked this conversation as resolved
Julian Eisel reviewed 2023-07-14 15:27:59 +02:00
@ -1930,0 +1948,4 @@
{
STRNCPY(but->drawstr, UI_VALUE_INDETERMINATE_CHAR);
align = UI_STYLE_TEXT_CENTER;
use_right_only = false;
Member

This doesn't have any impact, use_right_only is already false at this point, and may only be set to true later. Same for drawstr_right.

I think a bool drawstr_overridden makes sense. When true we don't draw right aligned text. This could also be set when but->editstr is true.

This doesn't have any impact, `use_right_only` is already false at this point, and may only be set to true later. Same for `drawstr_right`. I think a `bool drawstr_overridden` makes sense. When true we don't draw right aligned text. This could also be set when `but->editstr` is true.
Harley marked this conversation as resolved
Harley Acheson added 2 commits 2023-07-15 02:38:56 +02:00
Julian Eisel approved these changes 2023-07-16 23:43:24 +02:00
Julian Eisel merged commit 1b1349cee4 into main 2023-07-17 19:37:24 +02:00
Sign in to join this conversation.
No reviewers
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
3 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender#108210
No description provided.