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
4 changed files with 61 additions and 3 deletions

View File

@ -86,6 +86,11 @@ typedef struct uiViewItemHandle uiViewItemHandle;
#define UI_SEP_CHAR '|'
#define UI_SEP_CHAR_S "|"
/**
* Character used when value is indeterminate (multiple, unknown, unset).
*/
#define UI_VALUE_INDETERMINATE_CHAR BLI_STR_UTF8_EM_DASH
/* Separator for text in search menus (right pointing arrow).
* keep in sync with `string_search.cc`. */
#define UI_MENU_ARROW_SEP BLI_STR_UTF8_BLACK_RIGHT_POINTING_SMALL_TRIANGLE
@ -326,6 +331,9 @@ enum {
/* Draw the checkbox buttons inverted. */
UI_BUT_CHECKBOX_INVERT = 1 << 25,
/* Drawn in a way that indicates that the state/value is unknown. */
UI_BUT_INDETERMINATE = 1 << 26,
};
/**

View File

@ -1127,6 +1127,7 @@ enum {
ROUNDBOX_TRIA_MENU,
ROUNDBOX_TRIA_CHECK,
ROUNDBOX_TRIA_HOLD_ACTION_ARROW,
ROUNDBOX_TRIA_DASH,
ROUNDBOX_TRIA_MAX, /* don't use */
};

View File

@ -1032,6 +1032,16 @@ static void shape_preset_trias_from_rect_checkmark(uiWidgetTrias *tria, const rc
tria->index = g_shape_preset_checkmark_face;
}
static void shape_preset_trias_from_rect_dash(uiWidgetTrias *tria, const rcti *rect)
{
tria->type = ROUNDBOX_TRIA_DASH;
/* Center position and size. */
tria->center[0] = rect->xmin + 0.5f * BLI_rcti_size_y(rect);
tria->center[1] = rect->ymin + 0.5f * BLI_rcti_size_y(rect);
tria->size = 0.5f * BLI_rcti_size_y(rect);
}
/** \} */
/* -------------------------------------------------------------------- */
@ -1872,6 +1882,7 @@ static void widget_draw_text(const uiFontStyle *fstyle,
const char *drawstr = but->drawstr;
const char *drawstr_right = nullptr;
bool use_right_only = false;
const char *indeterminate_str = UI_VALUE_INDETERMINATE_CHAR;
#ifdef WITH_INPUT_IME
const wmIMEData *ime_data;
@ -1927,6 +1938,20 @@ static void widget_draw_text(const uiFontStyle *fstyle,
}
}
/* If not editing and indeterminate, show dash.*/
if (but->drawflag & UI_BUT_INDETERMINATE && !but->editstr &&
ELEM(but->type,
UI_BTYPE_MENU,
UI_BTYPE_NUM,
UI_BTYPE_NUM_SLIDER,
UI_BTYPE_TEXT,
UI_BTYPE_SEARCH_MENU))
{
Harley marked this conversation as resolved
Review

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.
drawstr = indeterminate_str;
drawstr_left_len = strlen(drawstr);
Harley marked this conversation as resolved Outdated

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.
align = UI_STYLE_TEXT_CENTER;
}
/* text button selection, cursor, composite underline */
if (but->editstr && but->pos != -1) {
int but_pos_ofs;
@ -3775,7 +3800,7 @@ static void widget_numslider(uiBut *but,
widgetbase_draw(&wtb, wcol);
/* Draw slider part only when not in text editing. */
if (!state->is_text_input) {
if (!state->is_text_input && !(but->drawflag & UI_BUT_INDETERMINATE)) {
int roundboxalign_slider = roundboxalign;
uchar outline[3];
@ -3902,6 +3927,10 @@ static void widget_swatch(uiBut *but,
ui_but_v3_get(but, col);
if (but->drawflag & UI_BUT_INDETERMINATE) {
col[0] = col[1] = col[2] = col[3] = 0.5f;
}
if ((state->but_flag & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN |
UI_BUT_OVERRIDDEN | UI_BUT_REDALERT)) ||
(state->but_drawflag & UI_BUT_ANIMATED_CHANGED))
@ -4210,11 +4239,19 @@ static void widget_optionbut(uiWidgetColors *wcol,
/* Keep one edge in place. */
BLI_rcti_translate(&recttemp, text_before_widget ? delta : -delta, 0);
if (state->but_drawflag & UI_BUT_INDETERMINATE) {
/* The same muted background color regardless of state. */
color_blend_v4_v4v4(wcol->inner, wcol->inner, wcol->inner_sel, 0.75f);
}
const float rad = widget_radius_from_rcti(&recttemp, wcol);
round_box_edges(&wtb, UI_CNR_ALL, &recttemp, rad);
/* decoration */
if (state->but_flag & UI_SELECT) {
if (state->but_drawflag & UI_BUT_INDETERMINATE) {
shape_preset_trias_from_rect_dash(&wtb.tria1, &recttemp);
}
else if (state->but_flag & UI_SELECT) {
shape_preset_trias_from_rect_checkmark(&wtb.tria1, &recttemp);
}
@ -5032,6 +5069,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;
Harley marked this conversation as resolved
Review

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.
}
const float zoom = 1.0f / but->block->aspect;
wt->state(wt, &state, but->emboss);
if (wt->custom) {

View File

@ -137,7 +137,7 @@ vec2 do_tria()
outRectSize = vec2(0.74, 0.14);
outRoundCorners = vec4(0.01);
}
else {
else if (triaType == 5.0) {
/* ROUNDBOX_TRIA_HOLD_ACTION_ARROW */
/* We use a single triangle to cut the round rect in half. The edge will not be Antialiased. */
pos = tria2 ? vec2(0.0) : arrow_pos[min(vidx, 2)]; /* Only keep 1 triangle. */
@ -149,6 +149,14 @@ vec2 do_tria()
outRectSize = vec2(0.75);
outRoundCorners = vec4(0.01);
}
else if (triaType == 6.0) {
/* ROUNDBOX_TRIA_DASH */
pos = point_pos[vidx];
uvInterp = point_uvs[vidx];
uvInterp -= vec2(0.2, 0.45); /* Translate */
outRectSize = vec2(0.6, 0.1);
outRoundCorners = vec4(0.01);
}
uvInterp *= abs(size);
outRectSize *= abs(size);