UI: Refactor quick label tooltip implementation for buttons

No user visible changes expected. Used in the asset shelf branch,
see #104831.

These tooltips only show a label string and appear after a shorter timeout
than the regular tooltips. After the regular tooltip timeout they expand to
the full tooltip. The toolbar and properties editor navigation tabs make use
of this already.

The changes here enable more control over quick label tooltips, making them
usable in more cases, and less ad-hoc. Main changes:
- Refactors internal logic so a single `UI_BUT_HAS_TOOLTIP_LABEL` button flag
  can be used to enable quick label tooltips. This decentralizes logic in a
  way that's more consistent and extensible.
- Custom callback to return a quick label. This is useful when a label tooltip
  should be displayed even when there is no button string set. E.g. in the
  asset shelf with "Show Names" disabled.

Pull Request: https://projects.blender.org/blender/blender/pulls/110200
This commit is contained in:
Julian Eisel
2023-07-25 16:22:31 +02:00
parent 89811cb96f
commit 9d0907560a
6 changed files with 63 additions and 21 deletions

View File

@@ -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 */
@@ -294,8 +299,11 @@ enum {
UI_BUT_TEXT_RIGHT = 1 << 3,
/** Prevent the button to show any tooltip. */
UI_BUT_NO_TOOLTIP = 1 << 4,
/** Show a quick tooltip label, that is, a short tooltip that appears faster than the full one
* and only shows the label. After a short delay the full toolitp is shown if any. */
UI_BUT_HAS_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! */
@@ -1394,6 +1402,10 @@ 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. This can
* be displayed in a quick tooltip, appearing after a smaller timeout and expanding to the full
* tooltip after the regular timeout. */
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! */
@@ -1754,6 +1766,9 @@ void UI_but_func_drawextra_set(
void UI_but_func_menu_step_set(uiBut *but, uiMenuStepFunc func);
void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *arg, uiFreeArgFunc free_arg);
#ifdef __cplusplus
void UI_but_func_tooltip_label_set(uiBut *but, std::function<std::string(const uiBut *but)> func);
#endif
/**
* Recreate tool-tip (use to update dynamic tips)
*/

View File

@@ -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_HAS_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);
@@ -4832,6 +4833,12 @@ static uiBut *ui_def_but_operator_ptr(uiBlock *block,
but->opcontext = opcontext;
but->flag &= ~UI_BUT_UNDO; /* no need for ui_but_is_rna_undo(), we never need undo here */
const bool has_label = str && str[0];
/* Enable quick tooltip label if this is a tool button without a label. */
if (!has_label && !ui_block_is_popover(block) && UI_but_is_tool(but)) {
UI_but_drawflag_enable(but, UI_BUT_HAS_TOOLTIP_LABEL);
}
if (!ot) {
UI_but_disable(but, "");
}
@@ -6076,6 +6083,12 @@ 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 = std::move(func);
UI_but_drawflag_enable(but, UI_BUT_HAS_TOOLTIP_LABEL);
}
void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *arg, uiFreeArgFunc free_arg)
{
but->tip_func = func;
@@ -6577,6 +6590,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;

View File

@@ -219,6 +219,9 @@ struct uiBut {
uiButToolTipFunc tip_func = nullptr;
void *tip_arg = nullptr;
uiFreeArgFunc tip_arg_free = nullptr;
/** Function to get a custom tooltip label, see #UI_BUT_HAS_TOOLTIP_LABEL. Requires
* #UI_BUT_HAS_TOOLTIP_LABEL drawflag. */
std::function<std::string(const uiBut *)> tip_label_func;
/** info on why button is disabled, displayed in tooltip */
const char *disabled_info = nullptr;

View File

@@ -935,6 +935,9 @@ static void ui_item_enum_expand_tabs(uiLayout *layout,
tab = tab->next)
{
UI_but_drawflag_enable(tab, ui_but_align_opposite_to_area_align_get(CTX_wm_region(C)));
if (icon_only) {
UI_but_drawflag_enable(tab, UI_BUT_HAS_TOOLTIP_LABEL);
}
}
const bool use_custom_highlight = (prop_highlight != nullptr);

View File

@@ -144,16 +144,7 @@ bool UI_but_is_tool(const uiBut *but)
bool UI_but_has_tooltip_label(const uiBut *but)
{
/* No tooltip label if the button itself shows a label already. */
if (but->drawstr[0] != '\0') {
return false;
}
if (UI_but_is_tool(but)) {
return !ui_block_is_popover(but->block);
}
return ELEM(but->type, UI_BTYPE_TAB);
return (but->drawflag & UI_BUT_HAS_TOOLTIP_LABEL) != 0;
}
int ui_but_icon(const uiBut *but)

View File

@@ -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,
@@ -795,15 +798,15 @@ static uiTooltipData *ui_tooltip_data_from_button_or_extra_icon(bContext *C,
}
}
/* Tip Label (only for buttons not already showing the label).
* 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) {
if (but_tip_label.strinfo &&
/* 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. */
!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 +989,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);
}