UI: New internal API function to add a simple button

For blender/blender!141292, we need a simple icon and text button that
executes a callback on click. The size should be determined based on the
text and icon, as it's typically done with the `UI_interface_layout.hh`
API. Trying to do this with `uiDefIconTextBut()` is annoyingly
complicated, mostly because we'd have to duplicate size calculations.

Instead expand the `UI_interface_layout.hh` API to cover this.

* Allow passing a button type to `uiItemL_()` and rename it to
  `uiItem_simple()`. The code in this function is commonly useful, not
  just for label buttons. It's a convenient way to add a single button
  with normal size calculations. The function stays internal to
  `interface_layout.cc`.
* Add `uiItemBut()` as public API function to call this and assign an
  on-click callback.

No user visible changes expected.

Pull Request: https://projects.blender.org/blender/blender/pulls/141900
This commit is contained in:
Julian Eisel
2025-07-16 13:10:22 +02:00
committed by Julian Eisel
parent fc05a70dcd
commit 2658754324
2 changed files with 35 additions and 12 deletions

View File

@@ -657,6 +657,13 @@ struct uiLayout : uiItem, blender::NonCopyable, blender::NonMovable {
int icon,
const char *menu_type);
/** Simple button executing \a func on click. */
uiBut *button(uiLayout *layout,
blender::StringRef name,
int icon,
std::function<void(bContext &)> func,
std::optional<blender::StringRef> tooltip = std::nullopt);
/** Adds a separator item, that adds empty space between items. */
void separator(float factor = 1.0f, LayoutSeparatorType type = LayoutSeparatorType::Auto);

View File

@@ -2969,8 +2969,15 @@ void uiLayout::popover_group(
}
}
/* label item */
static uiBut *uiItemL_(uiLayout *layout, const StringRef name, int icon)
/**
* Single button with an icon and/or text, using the given button type and no further data/behavior
* attached.
*/
static uiBut *uiItem_simple(uiLayout *layout,
const StringRef name,
int icon,
std::optional<blender::StringRef> tooltip = std::nullopt,
const eButType but_type = UI_BTYPE_LABEL)
{
uiBlock *block = layout->block();
@@ -2985,15 +2992,13 @@ static uiBut *uiItemL_(uiLayout *layout, const StringRef name, int icon)
uiBut *but;
if (icon && !name.is_empty()) {
but = uiDefIconTextBut(
block, UI_BTYPE_LABEL, 0, icon, name, 0, 0, w, UI_UNIT_Y, nullptr, 0.0, 0.0, std::nullopt);
block, but_type, 0, icon, name, 0, 0, w, UI_UNIT_Y, nullptr, 0.0, 0.0, tooltip);
}
else if (icon) {
but = uiDefIconBut(
block, UI_BTYPE_LABEL, 0, icon, 0, 0, w, UI_UNIT_Y, nullptr, 0.0, 0.0, std::nullopt);
but = uiDefIconBut(block, but_type, 0, icon, 0, 0, w, UI_UNIT_Y, nullptr, 0.0, 0.0, tooltip);
}
else {
but = uiDefBut(
block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, nullptr, 0.0, 0.0, std::nullopt);
but = uiDefBut(block, but_type, 0, name, 0, 0, w, UI_UNIT_Y, nullptr, 0.0, 0.0, tooltip);
}
/* to compensate for string size padding in ui_text_icon_width,
@@ -3019,7 +3024,7 @@ static uiBut *uiItemL_(uiLayout *layout, const StringRef name, int icon)
uiBut *uiItemL_ex(
uiLayout *layout, const StringRef name, int icon, const bool highlight, const bool redalert)
{
uiBut *but = uiItemL_(layout, name, icon);
uiBut *but = uiItem_simple(layout, name, icon);
if (highlight) {
/* TODO: add another flag for this. */
@@ -3035,7 +3040,7 @@ uiBut *uiItemL_ex(
void uiLayout::label(const StringRef name, int icon)
{
uiItemL_(this, name, icon);
uiItem_simple(this, name, icon);
}
uiPropertySplitWrapper uiItemPropertySplitWrapperCreate(uiLayout *parent_layout)
@@ -3062,7 +3067,7 @@ uiLayout *uiItemL_respect_property_split(uiLayout *layout, StringRef text, int i
const uiPropertySplitWrapper split_wrapper = uiItemPropertySplitWrapperCreate(layout);
/* Further items added to 'layout' will automatically be added to split_wrapper.property_row */
uiItemL_(split_wrapper.label_column, text, icon);
uiItem_simple(split_wrapper.label_column, text, icon);
UI_block_layout_set_current(block, split_wrapper.property_row);
return split_wrapper.decorate_column;
@@ -3070,14 +3075,14 @@ uiLayout *uiItemL_respect_property_split(uiLayout *layout, StringRef text, int i
char namestr[UI_MAX_NAME_STR];
text = ui_item_name_add_colon(text, namestr);
uiItemL_(layout, text, icon);
uiItem_simple(layout, text, icon);
return nullptr;
}
void uiItemLDrag(uiLayout *layout, PointerRNA *ptr, StringRef name, int icon)
{
uiBut *but = uiItemL_(layout, name, icon);
uiBut *but = uiItem_simple(layout, name, icon);
if (ptr && ptr->type) {
if (RNA_struct_is_ID(ptr->type)) {
@@ -3086,6 +3091,17 @@ void uiItemLDrag(uiLayout *layout, PointerRNA *ptr, StringRef name, int icon)
}
}
uiBut *uiLayout::button(uiLayout *layout,
const StringRef name,
const int icon,
std::function<void(bContext &)> func,
std::optional<blender::StringRef> tooltip)
{
uiBut *but = uiItem_simple(layout, name, icon, tooltip, UI_BTYPE_BUT);
UI_but_func_set(but, std::move(func));
return but;
}
void uiLayout::separator(float factor, const LayoutSeparatorType type)
{
uiBlock *block = this->block();