UI: Customizable quick label tooltip for buttons #110016
@ -8,6 +8,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
# include <functional>
|
||||
# include <string>
|
||||
#endif
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_string_utf8_symbols.h"
|
||||
#include "BLI_sys_types.h" /* size_t */
|
||||
@ -289,8 +294,11 @@ enum {
|
||||
UI_BUT_TEXT_RIGHT = 1 << 3,
|
||||
/** Prevent the button to show any tooltip. */
|
||||
UI_BUT_NO_TOOLTIP = 1 << 4,
|
||||
/** Always show a tooltip label (the short tooltip that appears faster than the full one and only
|
||||
* shows the label) even the label may already be visible. */
|
||||
UI_BUT_FORCE_TOOLTIP_LABEL = 1 << 5,
|
||||
/** Do not add the usual horizontal padding for text drawing. */
|
||||
UI_BUT_NO_TEXT_PADDING = 1 << 5,
|
||||
UI_BUT_NO_TEXT_PADDING = 1 << 6,
|
||||
|
||||
/* Button align flag, for drawing groups together.
|
||||
* Used in 'uiBlock.flag', take care! */
|
||||
@ -1386,6 +1394,8 @@ typedef enum uiStringInfoType {
|
||||
BUT_GET_RNASTRUCT_IDENTIFIER,
|
||||
BUT_GET_RNAENUM_IDENTIFIER,
|
||||
BUT_GET_LABEL,
|
||||
/** Sometimes the button doesn't have a label itself, but provides one for the tooltip. */
|
||||
BUT_GET_TIP_LABEL,
|
||||
BUT_GET_RNA_LABEL,
|
||||
BUT_GET_RNAENUM_LABEL,
|
||||
BUT_GET_RNA_LABEL_CONTEXT, /* Context specified in CTX_XXX_ macros are just unreachable! */
|
||||
@ -1746,6 +1756,10 @@ void UI_but_func_drawextra_set(
|
||||
|
||||
void UI_but_func_menu_step_set(uiBut *but, uiMenuStepFunc func);
|
||||
|
||||
#ifdef __cplusplus
|
||||
void UI_but_func_tooltip_label_set(uiBut *but, std::function<std::string(const uiBut *but)> func);
|
||||
#endif
|
||||
|
||||
void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *arg, uiFreeArgFunc free_arg);
|
||||
/**
|
||||
* Recreate tool-tip (use to update dynamic tips)
|
||||
|
@ -856,7 +856,7 @@ static void ui_but_update_old_active_from_new(uiBut *oldbut, uiBut *but)
|
||||
|
||||
/* flags from the buttons we want to refresh, may want to add more here... */
|
||||
const int flag_copy = UI_BUT_REDALERT | UI_HAS_ICON | UI_SELECT_DRAW;
|
||||
const int drawflag_copy = 0; /* None currently. */
|
||||
const int drawflag_copy = UI_BUT_FORCE_TOOLTIP_LABEL;
|
||||
|
||||
/* still stuff needs to be copied */
|
||||
oldbut->rect = but->rect;
|
||||
@ -878,6 +878,7 @@ static void ui_but_update_old_active_from_new(uiBut *oldbut, uiBut *but)
|
||||
std::swap(oldbut->tip_func, but->tip_func);
|
||||
std::swap(oldbut->tip_arg, but->tip_arg);
|
||||
std::swap(oldbut->tip_arg_free, but->tip_arg_free);
|
||||
std::swap(oldbut->tip_label_func, but->tip_label_func);
|
||||
|
||||
oldbut->flag = (oldbut->flag & ~flag_copy) | (but->flag & flag_copy);
|
||||
oldbut->drawflag = (oldbut->drawflag & ~drawflag_copy) | (but->drawflag & drawflag_copy);
|
||||
@ -6076,6 +6077,11 @@ void UI_but_func_menu_step_set(uiBut *but, uiMenuStepFunc func)
|
||||
but->menu_step_func = func;
|
||||
}
|
||||
|
||||
void UI_but_func_tooltip_label_set(uiBut *but, std::function<std::string(const uiBut *but)> func)
|
||||
{
|
||||
but->tip_label_func = func;
|
||||
}
|
||||
|
||||
void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *arg, uiFreeArgFunc free_arg)
|
||||
{
|
||||
but->tip_func = func;
|
||||
@ -6577,6 +6583,17 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
|
||||
uiStringInfoType type = si->type;
|
||||
char *tmp = nullptr;
|
||||
|
||||
if (type == BUT_GET_TIP_LABEL) {
|
||||
if (but->tip_label_func) {
|
||||
const std::string tooltip_label = but->tip_label_func(but);
|
||||
tmp = BLI_strdupn(tooltip_label.c_str(), tooltip_label.size());
|
||||
}
|
||||
/* Fallback to the regular label. */
|
||||
else {
|
||||
type = BUT_GET_LABEL;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == BUT_GET_LABEL) {
|
||||
if (but->str && but->str[0]) {
|
||||
const char *str_sep;
|
||||
|
@ -219,6 +219,7 @@ struct uiBut {
|
||||
uiButToolTipFunc tip_func = nullptr;
|
||||
void *tip_arg = nullptr;
|
||||
uiFreeArgFunc tip_arg_free = nullptr;
|
||||
std::function<std::string(const uiBut *)> tip_label_func;
|
||||
|
||||
/** info on why button is disabled, displayed in tooltip */
|
||||
const char *disabled_info = nullptr;
|
||||
|
@ -144,11 +144,19 @@ bool UI_but_is_tool(const uiBut *but)
|
||||
|
||||
bool UI_but_has_tooltip_label(const uiBut *but)
|
||||
{
|
||||
if (but->drawflag & UI_BUT_FORCE_TOOLTIP_LABEL) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* No tooltip label if the button itself shows a label already. */
|
||||
if (but->drawstr[0] != '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (but->tip_label_func) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (UI_but_is_tool(but)) {
|
||||
return !ui_block_is_popover(but->block);
|
||||
}
|
||||
|
@ -751,6 +751,7 @@ static uiTooltipData *ui_tooltip_data_from_button_or_extra_icon(bContext *C,
|
||||
const bool is_label)
|
||||
{
|
||||
uiStringInfo but_label = {BUT_GET_LABEL, nullptr};
|
||||
uiStringInfo but_tip_label = {BUT_GET_TIP_LABEL, nullptr};
|
||||
uiStringInfo but_tip = {BUT_GET_TIP, nullptr};
|
||||
uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, nullptr};
|
||||
uiStringInfo enum_tip = {BUT_GET_RNAENUM_TIP, nullptr};
|
||||
@ -770,20 +771,22 @@ static uiTooltipData *ui_tooltip_data_from_button_or_extra_icon(bContext *C,
|
||||
|
||||
if (extra_icon) {
|
||||
if (is_label) {
|
||||
UI_but_extra_icon_string_info_get(C, extra_icon, &but_label, &enum_label, nullptr);
|
||||
UI_but_extra_icon_string_info_get(C, extra_icon, &but_tip_label, &enum_label, nullptr);
|
||||
}
|
||||
else {
|
||||
UI_but_extra_icon_string_info_get(C, extra_icon, &but_label, &but_tip, &op_keymap, nullptr);
|
||||
UI_but_extra_icon_string_info_get(
|
||||
C, extra_icon, &but_label, &but_tip_label, &but_tip, &op_keymap, nullptr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (is_label) {
|
||||
UI_but_string_info_get(C, but, &but_label, &enum_label, nullptr);
|
||||
UI_but_string_info_get(C, but, &but_tip_label, &enum_label, nullptr);
|
||||
}
|
||||
else {
|
||||
UI_but_string_info_get(C,
|
||||
but,
|
||||
&but_label,
|
||||
&but_tip_label,
|
||||
&but_tip,
|
||||
&enum_label,
|
||||
&enum_tip,
|
||||
@ -799,11 +802,14 @@ static uiTooltipData *ui_tooltip_data_from_button_or_extra_icon(bContext *C,
|
||||
* Check prefix instead of comparing because the button may include the shortcut.
|
||||
* Buttons with dynamic tool-tips also don't get their default label here since they
|
||||
* can already provide more accurate and specific tool-tip content. */
|
||||
if (but_label.strinfo && !STRPREFIX(but->drawstr, but_label.strinfo) && !but->tip_func) {
|
||||
const bool force_tip_label = but->drawflag & UI_BUT_FORCE_TOOLTIP_LABEL;
|
||||
if (but_tip_label.strinfo &&
|
||||
(force_tip_label || (!STRPREFIX(but->drawstr, but_tip_label.strinfo) && !but->tip_func)))
|
||||
{
|
||||
uiTooltipField *field = text_field_add(
|
||||
data, uiTooltipFormat::Style::Header, uiTooltipFormat::ColorID::Normal);
|
||||
|
||||
field->text = BLI_strdup(but_label.strinfo);
|
||||
field->text = BLI_strdup(but_tip_label.strinfo);
|
||||
}
|
||||
|
||||
/* Tip */
|
||||
@ -986,6 +992,9 @@ static uiTooltipData *ui_tooltip_data_from_button_or_extra_icon(bContext *C,
|
||||
if (but_label.strinfo) {
|
||||
MEM_freeN(but_label.strinfo);
|
||||
}
|
||||
if (but_tip_label.strinfo) {
|
||||
MEM_freeN(but_tip_label.strinfo);
|
||||
}
|
||||
if (but_tip.strinfo) {
|
||||
MEM_freeN(but_tip.strinfo);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user
It may be better to use the new method completely, so that
UI_BUT_FORCE_TOOLTIP_LABEL
becomesUI_BUT_HAS_TOOLTIP_LABEL
. That decentralizes the logic in a way that's more consistent and more extensible.It also avoids adding complexity as this PR currently does by adding a new way to do the same thing.
Submitted a separate PR for this: #110200. Both solutions are fine with me, but the new one is a bit more risky since it changes existing code.
The other PR still includes
UI_BUT_FORCE_TOOLTIP_LABEL
,. Wasn't it supposed to be completely replaced byUI_BUT_HAS_TOOLTIP_LABEL
?That was to skip the
!STRPREFIX(but->drawstr, but_tip_label.strinfo)
condition in the tooltip code, but I think we can remove this entirely. It was a weak check and didn't account for label clipping.