UI: Highlight Selected Item in View3D Mode Menu #112058

Merged
Harley Acheson merged 1 commits from Harley/blender:SetModeSelected into blender-v4.0-release 2023-10-11 19:27:09 +02:00
2 changed files with 53 additions and 8 deletions

View File

@ -2833,16 +2833,20 @@ void uiItemPointerR(uiLayout *layout,
const char *searchpropname,
const char *name,
int icon);
/* Create a list of enum items. Active is an optional item to highlight. */
void uiItemsFullEnumO(uiLayout *layout,
const char *opname,
const char *propname,
IDProperty *properties,
wmOperatorCallContext context,
eUI_Item_Flag flag);
eUI_Item_Flag flag,
const int active = -1);
/**
* Create UI items for enum items in \a item_array.
*
* A version of #uiItemsFullEnumO that takes pre-calculated item array.
* active, if not -1, will highlight that item.
*/
void uiItemsFullEnumO_items(uiLayout *layout,
wmOperatorType *ot,
@ -2852,7 +2856,8 @@ void uiItemsFullEnumO_items(uiLayout *layout,
wmOperatorCallContext context,
eUI_Item_Flag flag,
const EnumPropertyItem *item_array,
int totitem);
int totitem,
int active = -1);
struct uiPropertySplitWrapper {
uiLayout *label_column;

View File

@ -1459,7 +1459,8 @@ void uiItemsFullEnumO_items(uiLayout *layout,
wmOperatorCallContext context,
eUI_Item_Flag flag,
const EnumPropertyItem *item_array,
int totitem)
int totitem,
int active)
{
const char *propname = RNA_property_identifier(prop);
if (RNA_property_type(prop) != PROP_ENUM) {
@ -1548,7 +1549,13 @@ void uiItemsFullEnumO_items(uiLayout *layout,
flag,
nullptr);
ui_but_tip_from_enum_item(static_cast<uiBut *>(block->buttons.last), item);
uiBut *but = static_cast<uiBut *>(block->buttons.last);
if (active == (i - 1)) {
Harley marked this conversation as resolved Outdated

I don't think i can ever be 0 in this loop, so the selected_item != -1 check seems redundant.

I don't think `i` can ever be 0 in this loop, so the `selected_item != -1` check seems redundant.
but->flag |= UI_SELECT_DRAW;
}
ui_but_tip_from_enum_item(but, item);
}
else {
if (item->name) {
@ -1603,7 +1610,8 @@ void uiItemsFullEnumO(uiLayout *layout,
const char *propname,
IDProperty *properties,
wmOperatorCallContext context,
eUI_Item_Flag flag)
eUI_Item_Flag flag,
const int active)
{
wmOperatorType *ot = WM_operatortype_find(opname, false); /* print error next */
@ -1651,7 +1659,8 @@ void uiItemsFullEnumO(uiLayout *layout,
}
/* add items */
uiItemsFullEnumO_items(layout, ot, ptr, prop, properties, context, flag, item_array, totitem);
uiItemsFullEnumO_items(
layout, ot, ptr, prop, properties, context, flag, item_array, totitem, active);
if (free) {
MEM_freeN((void *)item_array);
@ -3550,15 +3559,46 @@ struct MenuItemLevel {
PointerRNA rnapoin;
};
static void menu_item_enum_opname_menu(bContext * /*C*/, uiLayout *layout, void *arg)
/* Obtain the active menu item based on the calling button's text. */
static int menu_item_enum_opname_menu_active(bContext *C, uiBut *but, MenuItemLevel *lvl)
{
wmOperatorType *ot = WM_operatortype_find(lvl->opname, true);
if (!ot) {
Harley marked this conversation as resolved Outdated

Switch this null check and return early to avoid indenting the rest of the function.

Switch this null check and return early to avoid indenting the rest of the function.
return -1;
}
PointerRNA ptr;
const EnumPropertyItem *item_array = nullptr;
bool free;
int totitem;
WM_operator_properties_create_ptr(&ptr, ot);
Harley marked this conversation as resolved Outdated

The most confusing part here is that it's hard to be sure what but->str points to, and it seems a bit non-obvious to rely on the fact that it has the same string as the active item in the enum. At least it deserves a comment maybe with some reference to the place that but->str gets set to the active item's string.

The most confusing part here is that it's hard to be sure what `but->str` points to, and it seems a bit non-obvious to rely on the fact that it has the same string as the active item in the enum. At least it deserves a comment maybe with some reference to the place that `but->str` gets set to the active item's string.
/* so the context is passed to itemf functions (some need it) */
WM_operator_properties_sanitize(&ptr, false);
Harley marked this conversation as resolved Outdated

Maybe pass the context from the caller to avoid using evil_C?

Maybe pass the context from the caller to avoid using `evil_C`?
PropertyRNA *prop = RNA_struct_find_property(&ptr, lvl->propname);
Harley marked this conversation as resolved Outdated

I still think it's important to add comment here that describes at least briefly how but->str ends up becoming the name of the active item.

I still think it's important to add comment here that describes at least briefly how `but->str` ends up becoming the name of the active item.
RNA_property_enum_items_gettexted(C, &ptr, prop, &item_array, &totitem, &free);
int active = RNA_enum_from_name(item_array, but->str);
if (free) {
MEM_freeN((void *)item_array);
}
return active;
}
static void menu_item_enum_opname_menu(bContext *C, uiLayout *layout, void *arg)
{
uiBut *but = static_cast<uiBut *>(arg);
MenuItemLevel *lvl = static_cast<MenuItemLevel *>(but->func_argN);
/* Use the operator properties from the button owning the menu. */
IDProperty *op_props = but->opptr ? static_cast<IDProperty *>(but->opptr->data) : nullptr;
/* The calling but's str _probably_ contains the active
* menu item name, set in uiItemMenuEnumFullO_ptr. */
const int active = menu_item_enum_opname_menu_active(C, but, lvl);
uiLayoutSetOperatorContext(layout, lvl->opcontext);
uiItemsFullEnumO(layout, lvl->opname, lvl->propname, op_props, lvl->opcontext, UI_ITEM_NONE);
uiItemsFullEnumO(
layout, lvl->opname, lvl->propname, op_props, lvl->opcontext, UI_ITEM_NONE, active);
/* override default, needed since this was assumed pre 2.70 */
UI_block_direction_set(layout->root->block, UI_DIR_DOWN);