UI: support an 'active default' button for pop-ups
Use this for the save confirmation dialog so it has a default action when pressing enter which draws with a highlight so it's clear what the default action is (the dialog was just closing before). Resolves T57686
This commit is contained in:
parent
e3b83e2921
commit
2d34420648
Notes:
blender-bot
2023-02-14 07:31:32 +01:00
Referenced by issue #57686, Indicate which button gets activated when you hit Return
|
@ -193,6 +193,9 @@ enum {
|
|||
UI_BUT_IMMEDIATE = 1 << 20,
|
||||
UI_BUT_NO_UTF8 = 1 << 21,
|
||||
|
||||
/** For popups, pressing return activates this button, overriding the highlighed button. */
|
||||
UI_BUT_ACTIVE_DEFAULT = 1 << 23,
|
||||
|
||||
/** This but is "inside" a list item (currently used to change theme colors). */
|
||||
UI_BUT_LIST_ITEM = 1 << 24,
|
||||
/** edit this button as well as the active button (not just dragging) */
|
||||
|
@ -1053,6 +1056,7 @@ void uiLayoutSetContextFromBut(uiLayout *layout, uiBut *but);
|
|||
|
||||
void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext);
|
||||
void uiLayoutSetActive(uiLayout *layout, bool active);
|
||||
void uiLayoutSetActiveDefault(uiLayout *layout, bool active_default);
|
||||
void uiLayoutSetActivateInit(uiLayout *layout, bool active);
|
||||
void uiLayoutSetEnabled(uiLayout *layout, bool enabled);
|
||||
void uiLayoutSetRedAlert(uiLayout *layout, bool redalert);
|
||||
|
@ -1069,6 +1073,7 @@ int uiLayoutGetLocalDir(const uiLayout *layout);
|
|||
|
||||
int uiLayoutGetOperatorContext(uiLayout *layout);
|
||||
bool uiLayoutGetActive(uiLayout *layout);
|
||||
bool uiLayoutGetActiveDefault(uiLayout *layout);
|
||||
bool uiLayoutGetActivateInit(uiLayout *layout);
|
||||
bool uiLayoutGetEnabled(uiLayout *layout);
|
||||
bool uiLayoutGetRedAlert(uiLayout *layout);
|
||||
|
|
|
@ -9241,9 +9241,16 @@ static int ui_handle_menu_event(
|
|||
menu->menuretval = UI_RETURN_CANCEL;
|
||||
}
|
||||
else if (ELEM(event->type, RETKEY, PADENTER) && event->val == KM_PRESS) {
|
||||
uiBut *but_active = ui_region_find_first_but_test_flag(ar, UI_BUT_ACTIVE_DEFAULT, UI_HIDDEN);
|
||||
if (but_active != NULL) {
|
||||
ui_handle_button_activate(C, ar, but_active, BUTTON_ACTIVATE);
|
||||
/* Get again below just incase it's disabled for eg. */
|
||||
}
|
||||
but_active = ui_region_find_active_but(ar);
|
||||
|
||||
/* enter will always close this block, we let the event
|
||||
* get handled by the button if it is activated, otherwise we cancel */
|
||||
if (!ui_region_find_active_but(ar)) {
|
||||
if (but_active == NULL) {
|
||||
menu->menuretval = UI_RETURN_CANCEL | UI_RETURN_POPUP_OK;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -846,6 +846,7 @@ bool ui_block_is_popover(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
|
|||
bool ui_block_is_pie_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
|
||||
bool ui_block_is_popup_any(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
uiBut *ui_region_find_first_but_test_flag(struct ARegion *ar, int flag_include, int flag_exclude);
|
||||
uiBut *ui_region_find_active_but(struct ARegion *ar) ATTR_WARN_UNUSED_RESULT;
|
||||
bool ui_region_contains_point_px(
|
||||
const struct ARegion *ar, int x, int y) ATTR_WARN_UNUSED_RESULT;
|
||||
|
|
|
@ -160,6 +160,7 @@ struct uiLayout {
|
|||
short space;
|
||||
bool align;
|
||||
bool active;
|
||||
bool active_default;
|
||||
bool activate_init;
|
||||
bool enabled;
|
||||
bool redalert;
|
||||
|
@ -1060,6 +1061,10 @@ static uiBut *uiItemFullO_ptr_ex(
|
|||
UI_but_flag_enable(but, UI_BUT_REDALERT);
|
||||
}
|
||||
|
||||
if (layout->active_default) {
|
||||
UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT);
|
||||
}
|
||||
|
||||
/* assign properties */
|
||||
if (properties || r_opptr) {
|
||||
PointerRNA *opptr = UI_but_operator_ptr_get(but);
|
||||
|
@ -4150,6 +4155,11 @@ void uiLayoutSetActive(uiLayout *layout, bool active)
|
|||
layout->active = active;
|
||||
}
|
||||
|
||||
void uiLayoutSetActiveDefault(uiLayout *layout, bool active_default)
|
||||
{
|
||||
layout->active_default = active_default;
|
||||
}
|
||||
|
||||
void uiLayoutSetActivateInit(uiLayout *layout, bool activate_init)
|
||||
{
|
||||
layout->activate_init = activate_init;
|
||||
|
@ -4225,6 +4235,11 @@ bool uiLayoutGetActive(uiLayout *layout)
|
|||
return layout->active;
|
||||
}
|
||||
|
||||
bool uiLayoutGetActiveDefault(uiLayout *layout)
|
||||
{
|
||||
return layout->active_default;
|
||||
}
|
||||
|
||||
bool uiLayoutGetActivateInit(uiLayout *layout)
|
||||
{
|
||||
return layout->activate_init;
|
||||
|
|
|
@ -469,6 +469,21 @@ uiBut *ui_region_find_active_but(ARegion *ar)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
uiBut *ui_region_find_first_but_test_flag(ARegion *ar, int flag_include, int flag_exclude)
|
||||
{
|
||||
for (uiBlock *block = ar->uiblocks.first; block; block = block->next) {
|
||||
for (uiBut *but = block->buttons.first; but; but = but->next) {
|
||||
if (((but->flag & flag_include) == flag_include) &&
|
||||
((but->flag & flag_exclude) == 0))
|
||||
{
|
||||
return but;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -4563,23 +4563,32 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
|
|||
GPU_blend(true);
|
||||
}
|
||||
|
||||
bool show_semi_highlight = false;
|
||||
|
||||
#ifdef USE_UI_POPOVER_ONCE
|
||||
if (but->block->flag & UI_BLOCK_POPOVER_ONCE) {
|
||||
if ((state & UI_ACTIVE) && ui_but_is_popover_once_compat(but)) {
|
||||
uiWidgetType wt_back = *wt;
|
||||
uiWidgetType *wt_temp = widget_type(UI_WTYPE_MENU_ITEM);
|
||||
wt_temp->state(wt_temp, state, drawflag);
|
||||
copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
|
||||
wt->wcol.inner[3] = 128;
|
||||
wt->wcol.roundness = 0.5f;
|
||||
ui_draw_roundbox(
|
||||
&rect_orig,
|
||||
0.25f * min_ff(BLI_rcti_size_x(&rect_orig), BLI_rcti_size_y(&rect_orig)),
|
||||
&wt_temp->wcol);
|
||||
*wt = wt_back;
|
||||
show_semi_highlight = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (but->flag & UI_BUT_ACTIVE_DEFAULT) {
|
||||
show_semi_highlight = true;
|
||||
}
|
||||
|
||||
if (show_semi_highlight) {
|
||||
uiWidgetType wt_back = *wt;
|
||||
uiWidgetType *wt_temp = widget_type(UI_WTYPE_MENU_ITEM);
|
||||
wt_temp->state(wt_temp, state, drawflag);
|
||||
copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
|
||||
wt->wcol.inner[3] = 128;
|
||||
wt->wcol.roundness = 0.5f;
|
||||
ui_draw_roundbox(
|
||||
&rect_orig,
|
||||
0.25f * min_ff(BLI_rcti_size_x(&rect_orig), BLI_rcti_size_y(&rect_orig)),
|
||||
&wt_temp->wcol);
|
||||
*wt = wt_back;
|
||||
}
|
||||
|
||||
wt->text(fstyle, &wt->wcol, but, rect);
|
||||
if (disabled) {
|
||||
|
|
|
@ -881,6 +881,16 @@ static void rna_UILayout_active_set(PointerRNA *ptr, bool value)
|
|||
uiLayoutSetActive(ptr->data, value);
|
||||
}
|
||||
|
||||
static bool rna_UILayout_active_default_get(PointerRNA *ptr)
|
||||
{
|
||||
return uiLayoutGetActiveDefault(ptr->data);
|
||||
}
|
||||
|
||||
static void rna_UILayout_active_default_set(PointerRNA *ptr, bool value)
|
||||
{
|
||||
uiLayoutSetActiveDefault(ptr->data, value);
|
||||
}
|
||||
|
||||
static bool rna_UILayout_activate_init_get(PointerRNA *ptr)
|
||||
{
|
||||
return uiLayoutGetActivateInit(ptr->data);
|
||||
|
@ -1066,6 +1076,13 @@ static void rna_def_ui_layout(BlenderRNA *brna)
|
|||
prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_funcs(prop, "rna_UILayout_active_get", "rna_UILayout_active_set");
|
||||
|
||||
prop = RNA_def_property(srna, "active_default", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_funcs(prop, "rna_UILayout_active_default_get", "rna_UILayout_active_default_set");
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Active Default",
|
||||
"When true, an operator button defined after this will be activated when pressing return"
|
||||
"(use with popup dialogs)");
|
||||
|
||||
prop = RNA_def_property(srna, "activate_init", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_funcs(prop, "rna_UILayout_activate_init_get", "rna_UILayout_activate_init_set");
|
||||
RNA_def_property_ui_text(
|
||||
|
|
|
@ -433,6 +433,7 @@ static uiBlock *block_create_confirm_quit(struct bContext *C, struct ARegion *ar
|
|||
block, UI_BTYPE_BUT, 0, ICON_FILE_TICK, IFACE_("Save & Quit"), 0, 0, 50, UI_UNIT_Y,
|
||||
NULL, 0, 0, 0, 0, TIP_("Save and quit"));
|
||||
UI_but_func_set(but, wm_block_confirm_quit_save, block, NULL);
|
||||
UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT);
|
||||
|
||||
UI_block_bounds_set_centered(block, 10);
|
||||
|
||||
|
|
Loading…
Reference in New Issue