Refactor: UI: Replace uiItemMenuF and uiItemMenuFN with uiLayout methods

This converts the public `uiItemMenuF` and `uiItemMenuFN`
functions to an object oriented API (an `uiLayout::menu_fn`
and `uiLayout::menu_fn_argN_free` respectively), following
recent uiLayout changes.

Part of: #117604

Pull Request: https://projects.blender.org/blender/blender/pulls/138902
This commit is contained in:
Guillermo Venegas
2025-05-15 21:26:49 +02:00
committed by Hans Goudey
parent 5a449439ef
commit 89a3478e35
10 changed files with 45 additions and 39 deletions

View File

@@ -1016,9 +1016,9 @@ static bool move_to_collection_poll(bContext *C)
* Encode the parameters into an integer, and return as void*.
*
* NOTE(@sybren): This makes it possible to use these values and pass them directly as
* 'custom data' pointer to `uiItemMenuF()`. This makes it possible to give every menu a unique
* bone collection index for which it should show the child collections, without having to allocate
* memory or use static variables. See `move_to_collection_invoke()` in `object_edit.cc`
* 'custom data' pointer to `uiLayout::menu_fn()`. This makes it possible to give every menu a
* unique bone collection index for which it should show the child collections, without having to
* allocate memory or use static variables. See `move_to_collection_invoke()` in `object_edit.cc`
* for the alternative that I wanted to avoid.
*/
static void *menu_custom_data_encode(const int bcoll_index, const bool is_move_operation)
@@ -1078,9 +1078,10 @@ static void menu_add_item_for_move_assign_unassign(uiLayout *layout,
* Add menu items to the layout, for a set of bone collections.
*
* \param menu_custom_data: Contains two values, encoded as void* to match the signature required
* by `uiItemMenuF`. It contains the parent bone collection index (either -1 to show all roots, or
* another value to show the children of that collection), as well as a boolean that indicates
* whether the menu is created for the "move to collection" or "assign to collection" operator.
* by `uiLayout::menu_fn`. It contains the parent bone collection index (either -1 to show all
* roots, or another value to show the children of that collection), as well as a boolean that
* indicates whether the menu is created for the "move to collection" or "assign to collection"
* operator.
*
* \see menu_custom_data_encode
*/
@@ -1143,11 +1144,10 @@ static void move_to_collection_menu_create(bContext *C, uiLayout *layout, void *
}
if (blender::animrig::bonecoll_has_children(bcoll)) {
uiItemMenuF(layout,
bcoll->name,
ICON_NONE,
move_to_collection_menu_create,
menu_custom_data_encode(index, is_move_operation));
layout->menu_fn(bcoll->name,
ICON_NONE,
move_to_collection_menu_create,
menu_custom_data_encode(index, is_move_operation));
}
else {
menu_add_item_for_move_assign_unassign(layout, arm, bcoll, index, is_move_operation);

View File

@@ -259,6 +259,22 @@ struct uiLayout : uiItem {
*/
void menu(blender::StringRef menuname, std::optional<blender::StringRef> name, int icon);
/**
* Adds a menu item, which is a button that when active will display a menu.
* \param name: Label to show in the menu button.
* \param func: Function that generates the menu layout.
* \param arg: Pointer to data used as last argument in \a func.
*/
void menu_fn(blender::StringRefNull name, int icon, uiMenuCreateFunc func, void *arg);
/**
* Adds a menu item, which is a button that when active will display a menu.
* \param name: Label to show in the menu button.
* \param func: Function that generates the menu layout.
* \param argN: Pointer to data used as last argument in \a func, it will be
* freed with the menu button.
*/
void menu_fn_argN_free(blender::StringRefNull name, int icon, uiMenuCreateFunc func, void *argN);
/**
* Adds a operator item, places a button in the layout to call the operator.
* \param opname: Operator id name.
@@ -716,13 +732,6 @@ void uiItemPopoverPanelFromGroup(uiLayout *layout,
/**
* Level items.
*/
void uiItemMenuF(
uiLayout *layout, blender::StringRefNull, int icon, uiMenuCreateFunc func, void *arg);
/**
* Version of #uiItemMenuF that free's `argN`.
*/
void uiItemMenuFN(
uiLayout *layout, blender::StringRefNull, int icon, uiMenuCreateFunc func, void *argN);
void uiItemMenuEnumFullO_ptr(uiLayout *layout,
const bContext *C,
wmOperatorType *ot,

View File

@@ -1353,20 +1353,17 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but, const wmEvent *ev
/* skip */
}
else if (ELEM(region->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
uiItemMenuF(
layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, nullptr);
layout->menu_fn(IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, nullptr);
}
else if (region->regiontype == RGN_TYPE_NAV_BAR) {
uiItemMenuF(layout, IFACE_("Navigation Bar"), ICON_NONE, ED_buttons_navbar_menu, nullptr);
layout->menu_fn(IFACE_("Navigation Bar"), ICON_NONE, ED_buttons_navbar_menu, nullptr);
const ScrArea *area = CTX_wm_area(C);
if (area && area->spacetype == SPACE_PROPERTIES) {
uiItemMenuF(
layout, IFACE_("Visible Tabs"), ICON_NONE, ED_buttons_visible_tabs_menu, nullptr);
layout->menu_fn(IFACE_("Visible Tabs"), ICON_NONE, ED_buttons_visible_tabs_menu, nullptr);
}
}
else if (region->regiontype == RGN_TYPE_FOOTER) {
uiItemMenuF(
layout, IFACE_("Footer"), ICON_NONE, ED_screens_footer_tools_menu_create, nullptr);
layout->menu_fn(IFACE_("Footer"), ICON_NONE, ED_screens_footer_tools_menu_create, nullptr);
}
}

View File

@@ -3495,25 +3495,26 @@ void uiItemSpacer(uiLayout *layout)
"");
}
void uiItemMenuF(
uiLayout *layout, const StringRefNull name, int icon, uiMenuCreateFunc func, void *arg)
void uiLayout::menu_fn(const StringRefNull name, int icon, uiMenuCreateFunc func, void *arg)
{
if (!func) {
return;
}
ui_item_menu(layout, name, icon, func, arg, nullptr, "", false);
ui_item_menu(this, name, icon, func, arg, nullptr, "", false);
}
void uiItemMenuFN(
uiLayout *layout, const StringRefNull name, int icon, uiMenuCreateFunc func, void *argN)
void uiLayout::menu_fn_argN_free(const StringRefNull name,
int icon,
uiMenuCreateFunc func,
void *argN)
{
if (!func) {
return;
}
/* Second 'argN' only ensures it gets freed. */
ui_item_menu(layout, name, icon, func, argN, argN, "", false);
ui_item_menu(this, name, icon, func, argN, argN, "", false);
}
struct MenuItemLevel {

View File

@@ -135,7 +135,7 @@ static void draw_constraint_header(uiLayout *layout, Object *ob, bConstraint *co
row->prop(&ptr, "enabled", UI_ITEM_NONE, "", ICON_NONE);
/* Extra operators menu. */
uiItemMenuF(row, "", ICON_DOWNARROW_HLT, constraint_ops_extra_draw, con);
row->menu_fn("", ICON_DOWNARROW_HLT, constraint_ops_extra_draw, con);
/* Close 'button' - emboss calls here disable drawing of 'button' behind X */
sub = &row->row(false);

View File

@@ -2373,7 +2373,7 @@ static void move_to_collection_menus_items(uiLayout *layout, MoveToCollectionDat
menu->index);
}
else {
uiItemMenuF(layout, menu->collection->id.name + 2, icon, move_to_collection_menu_create, menu);
layout->menu_fn(menu->collection->id.name + 2, icon, move_to_collection_menu_create, menu);
}
}

View File

@@ -5321,8 +5321,7 @@ static wmOperatorStatus screen_context_menu_invoke(bContext *C,
ED_screens_region_flip_menu_create(C, layout, nullptr);
const ScrArea *area = CTX_wm_area(C);
if (area && area->spacetype == SPACE_PROPERTIES) {
uiItemMenuF(
layout, IFACE_("Visible Tabs"), ICON_NONE, ED_buttons_visible_tabs_menu, nullptr);
layout->menu_fn(IFACE_("Visible Tabs"), ICON_NONE, ED_buttons_visible_tabs_menu, nullptr);
}
UI_popup_menu_end(C, pup);
}

View File

@@ -526,7 +526,7 @@ static wmOperatorStatus workspace_add_invoke(bContext *C,
C, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, op->type->name), ICON_ADD);
uiLayout *layout = UI_popup_menu_layout(pup);
uiItemMenuF(layout, IFACE_("General"), ICON_NONE, workspace_add_menu, nullptr);
layout->menu_fn(IFACE_("General"), ICON_NONE, workspace_add_menu, nullptr);
ListBase templates;
BKE_appdir_app_templates(&templates);
@@ -538,7 +538,7 @@ static wmOperatorStatus workspace_add_invoke(bContext *C,
BLI_path_to_display_name(display_name, sizeof(display_name), IFACE_(app_template));
/* Steals ownership of link data string. */
uiItemMenuFN(layout, display_name, ICON_NONE, workspace_add_menu, app_template);
layout->menu_fn_argN_free(display_name, ICON_NONE, workspace_add_menu, app_template);
}
BLI_freelistN(&templates);

View File

@@ -436,7 +436,7 @@ static void modifier_panel_header(const bContext *C, Panel *panel)
}
/* Extra operators menu. */
uiItemMenuF(row, "", ICON_DOWNARROW_HLT, modifier_ops_extra_draw, md);
row->menu_fn("", ICON_DOWNARROW_HLT, modifier_ops_extra_draw, md);
/* Delete button. */
if (modifier_can_delete(md) && !modifier_is_simulation(md)) {

View File

@@ -194,7 +194,7 @@ static void shaderfx_panel_header(const bContext * /*C*/, Panel *panel)
row->prop(ptr, "show_render", UI_ITEM_NONE, "", ICON_NONE);
/* Extra operators. */
uiItemMenuF(row, "", ICON_DOWNARROW_HLT, gpencil_shaderfx_ops_extra_draw, fx);
row->menu_fn("", ICON_DOWNARROW_HLT, gpencil_shaderfx_ops_extra_draw, fx);
row = &row->row(false);
uiLayoutSetEmboss(row, blender::ui::EmbossType::None);