Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorJulian Eisel <julian@blender.org>2021-10-08 15:17:03 +0300
committerJulian Eisel <julian@blender.org>2021-10-08 15:18:10 +0300
commit2aca08fc1cb6448b593afde7b00ba34ce590551b (patch)
tree89ef0a3b3940608d206e988c4829c4086b0b0221 /source
parent86643a4e73fc23055cf346213b0569200bee795d (diff)
UI: Support tooltips for superimposed icons
In a couple of places in the UI, we show superimposed icons on buttons to execute an operation (called "Extra Icons" internally). Hovering them would show the tooltip of the underlying button, which is misleading and confusing. There are cases where it's not obvious what an icon does, so a tooltip would be quite useful here. It's likely we are going to use superimposed icons in more places in the future, e.g. see D11890. The extra icon basically acts as an override for the button in the tooltip code. Differential Revision: https://developer.blender.org/D11894 Reviewed by: Campbell Barton
Diffstat (limited to 'source')
-rw-r--r--source/blender/editors/include/UI_interface.h10
-rw-r--r--source/blender/editors/interface/interface.c84
-rw-r--r--source/blender/editors/interface/interface_handlers.c6
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c89
4 files changed, 146 insertions, 43 deletions
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index e8b71a41439..c536eff771d 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -82,6 +82,7 @@ struct wmWindow;
typedef struct uiBlock uiBlock;
typedef struct uiBut uiBut;
+typedef struct uiButExtraOpIcon uiButExtraOpIcon;
typedef struct uiLayout uiLayout;
typedef struct uiPopupBlockHandle uiPopupBlockHandle;
/* C handle for C++ #ui::AbstractTreeView type. */
@@ -1432,6 +1433,8 @@ typedef struct uiStringInfo {
* Will fill them with translated strings, when possible.
* Strings in uiStringInfo must be MEM_freeN'ed by caller. */
void UI_but_string_info_get(struct bContext *C, uiBut *but, ...) ATTR_SENTINEL(0);
+void UI_but_extra_icon_string_info_get(struct bContext *C, uiButExtraOpIcon *extra_icon, ...)
+ ATTR_SENTINEL(0);
/* Edit i18n stuff. */
/* Name of the main py op from i18n addon. */
@@ -1724,6 +1727,8 @@ struct PointerRNA *UI_but_extra_operator_icon_add(uiBut *but,
const char *opname,
short opcontext,
int icon);
+struct wmOperatorType *UI_but_extra_operator_icon_optype_get(struct uiButExtraOpIcon *extra_icon);
+struct PointerRNA *UI_but_extra_operator_icon_opptr_get(struct uiButExtraOpIcon *extra_icon);
/* Autocomplete
*
@@ -2713,6 +2718,11 @@ struct ARegion *UI_tooltip_create_from_button(struct bContext *C,
struct ARegion *butregion,
uiBut *but,
bool is_label);
+struct ARegion *UI_tooltip_create_from_button_or_extra_icon(struct bContext *C,
+ struct ARegion *butregion,
+ uiBut *but,
+ uiButExtraOpIcon *extra_icon,
+ bool is_label);
struct ARegion *UI_tooltip_create_from_gizmo(struct bContext *C, struct wmGizmo *gz);
void UI_tooltip_free(struct bContext *C, struct bScreen *screen, struct ARegion *region);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 92391a703ef..68595e49871 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1224,16 +1224,21 @@ void ui_but_add_shortcut(uiBut *but, const char *shortcut_str, const bool do_str
* \{ */
static bool ui_but_event_operator_string_from_operator(const bContext *C,
- uiBut *but,
+ wmOperatorCallParams *op_call_params,
char *buf,
const size_t buf_len)
{
- BLI_assert(but->optype != NULL);
+ BLI_assert(op_call_params->optype != NULL);
bool found = false;
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
-
- if (WM_key_event_operator_string(
- C, but->optype->idname, but->opcontext, prop, true, buf, buf_len)) {
+ IDProperty *prop = (op_call_params->opptr) ? op_call_params->opptr->data : NULL;
+
+ if (WM_key_event_operator_string(C,
+ op_call_params->optype->idname,
+ op_call_params->opcontext,
+ prop,
+ true,
+ buf,
+ buf_len)) {
found = true;
}
return found;
@@ -1318,7 +1323,12 @@ static bool ui_but_event_operator_string(const bContext *C,
bool found = false;
if (but->optype != NULL) {
- found = ui_but_event_operator_string_from_operator(C, but, buf, buf_len);
+ found = ui_but_event_operator_string_from_operator(
+ C,
+ &(wmOperatorCallParams){
+ .optype = but->optype, .opptr = but->opptr, .opcontext = but->opcontext},
+ buf,
+ buf_len);
}
else if (UI_but_menutype_get(but) != NULL) {
found = ui_but_event_operator_string_from_menu(C, but, buf, buf_len);
@@ -1330,6 +1340,20 @@ static bool ui_but_event_operator_string(const bContext *C,
return found;
}
+static bool ui_but_extra_icon_event_operator_string(const bContext *C,
+ uiButExtraOpIcon *extra_icon,
+ char *buf,
+ const size_t buf_len)
+{
+ wmOperatorType *extra_icon_optype = UI_but_extra_operator_icon_optype_get(extra_icon);
+
+ if (extra_icon_optype) {
+ return ui_but_event_operator_string_from_operator(C, extra_icon->optype_params, buf, buf_len);
+ }
+
+ return false;
+}
+
static bool ui_but_event_property_operator_string(const bContext *C,
uiBut *but,
char *buf,
@@ -1713,6 +1737,16 @@ PointerRNA *UI_but_extra_operator_icon_add(uiBut *but,
return NULL;
}
+wmOperatorType *UI_but_extra_operator_icon_optype_get(uiButExtraOpIcon *extra_icon)
+{
+ return extra_icon ? extra_icon->optype_params->optype : NULL;
+}
+
+PointerRNA *UI_but_extra_operator_icon_opptr_get(uiButExtraOpIcon *extra_icon)
+{
+ return extra_icon->optype_params->opptr;
+}
+
static bool ui_but_icon_extra_is_visible_text_clear(const uiBut *but)
{
BLI_assert(but->type == UI_BTYPE_TEXT);
@@ -7262,6 +7296,42 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
}
}
+void UI_but_extra_icon_string_info_get(struct bContext *C, uiButExtraOpIcon *extra_icon, ...)
+{
+ va_list args;
+ uiStringInfo *si;
+
+ wmOperatorType *optype = UI_but_extra_operator_icon_optype_get(extra_icon);
+ PointerRNA *opptr = UI_but_extra_operator_icon_opptr_get(extra_icon);
+
+ va_start(args, extra_icon);
+ while ((si = (uiStringInfo *)va_arg(args, void *))) {
+ char *tmp = NULL;
+
+ switch (si->type) {
+ case BUT_GET_LABEL:
+ tmp = BLI_strdup(WM_operatortype_name(optype, opptr));
+ break;
+ case BUT_GET_TIP:
+ tmp = WM_operatortype_description(C, optype, opptr);
+ break;
+ case BUT_GET_OP_KEYMAP: {
+ char buf[128];
+ if (ui_but_extra_icon_event_operator_string(C, extra_icon, buf, sizeof(buf))) {
+ tmp = BLI_strdup(buf);
+ }
+ }
+ /* Other types not supported. The caller should expect that outcome, no need to message or
+ * assert here. */
+ default:
+ break;
+ }
+
+ si->strinfo = tmp;
+ }
+ va_end(args);
+}
+
/* Program Init/Exit */
void UI_init(void)
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index c508cf2f36c..bf9b37c00fa 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -8235,7 +8235,11 @@ static ARegion *ui_but_tooltip_init(
uiBut *but = UI_region_active_but_get(region);
*r_exit_on_event = false;
if (but) {
- return UI_tooltip_create_from_button(C, region, but, is_label);
+ const wmWindow *win = CTX_wm_window(C);
+ uiButExtraOpIcon *extra_icon = ui_but_extra_operator_icon_mouse_over_get(
+ but, but->active, win->eventstate);
+
+ return UI_tooltip_create_from_button_or_extra_icon(C, region, but, extra_icon, is_label);
}
return NULL;
}
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index a8f289702f8..6071e14d153 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -761,7 +761,9 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
return data;
}
-static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
+static uiTooltipData *ui_tooltip_data_from_button_or_extra_icon(bContext *C,
+ uiBut *but,
+ uiButExtraOpIcon *extra_icon)
{
uiStringInfo but_label = {BUT_GET_LABEL, NULL};
uiStringInfo but_tip = {BUT_GET_TIP, NULL};
@@ -774,20 +776,29 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
char buf[512];
+ wmOperatorType *optype = extra_icon ? UI_but_extra_operator_icon_optype_get(extra_icon) :
+ but->optype;
+ PropertyRNA *rnaprop = extra_icon ? NULL : but->rnaprop;
+
/* create tooltip data */
uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
- UI_but_string_info_get(C,
- but,
- &but_label,
- &but_tip,
- &enum_label,
- &enum_tip,
- &op_keymap,
- &prop_keymap,
- &rna_struct,
- &rna_prop,
- NULL);
+ if (extra_icon) {
+ UI_but_extra_icon_string_info_get(C, extra_icon, &but_label, &but_tip, &op_keymap, NULL);
+ }
+ else {
+ UI_but_string_info_get(C,
+ but,
+ &but_label,
+ &but_tip,
+ &enum_label,
+ &enum_tip,
+ &op_keymap,
+ &prop_keymap,
+ &rna_struct,
+ &rna_prop,
+ NULL);
+ }
/* Tip Label (only for buttons not already showing the label).
* Check prefix instead of comparing because the button may include the shortcut. */
@@ -818,8 +829,7 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
}
/* special case enum rna buttons */
- if ((but->type & UI_BTYPE_ROW) && but->rnaprop &&
- RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG) {
+ if ((but->type & UI_BTYPE_ROW) && rnaprop && RNA_property_flag(rnaprop) & PROP_ENUM_FLAG) {
uiTooltipField *field = text_field_add(data,
&(uiTooltipFormat){
.style = UI_TIP_STYLE_NORMAL,
@@ -863,7 +873,7 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
/* better not show the value of a password */
- if ((but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PASSWORD)) == 0) {
+ if ((rnaprop && (RNA_property_subtype(rnaprop) == PROP_PASSWORD)) == 0) {
/* full string */
ui_but_string_get(but, buf, sizeof(buf));
if (buf[0]) {
@@ -878,15 +888,14 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
}
}
- if (but->rnaprop) {
+ if (rnaprop) {
const int unit_type = UI_but_unit_type_get(but);
if (unit_type == PROP_UNIT_ROTATION) {
- if (RNA_property_type(but->rnaprop) == PROP_FLOAT) {
- float value = RNA_property_array_check(but->rnaprop) ?
- RNA_property_float_get_index(
- &but->rnapoin, but->rnaprop, but->rnaindex) :
- RNA_property_float_get(&but->rnapoin, but->rnaprop);
+ if (RNA_property_type(rnaprop) == PROP_FLOAT) {
+ float value = RNA_property_array_check(rnaprop) ?
+ RNA_property_float_get_index(&but->rnapoin, rnaprop, but->rnaindex) :
+ RNA_property_float_get(&but->rnapoin, rnaprop);
uiTooltipField *field = text_field_add(data,
&(uiTooltipFormat){
@@ -920,15 +929,15 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
}
}
}
- else if (but->optype) {
- PointerRNA *opptr;
- char *str;
- opptr = UI_but_operator_ptr_get(but); /* allocated when needed, the button owns it */
+ else if (optype) {
+ PointerRNA *opptr = extra_icon ? UI_but_extra_operator_icon_opptr_get(extra_icon) :
+ /* allocated when needed, the button owns it */
+ UI_but_operator_ptr_get(but);
/* so the context is passed to fieldf functions (some py fieldf functions use it) */
WM_operator_properties_sanitize(opptr, false);
- str = ui_tooltip_text_python_from_op(C, but->optype, opptr);
+ char *str = ui_tooltip_text_python_from_op(C, optype, opptr);
/* operator info */
if (U.flag & USER_TOOLTIPS_PYTHON) {
@@ -973,7 +982,7 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
}
}
- if ((U.flag & USER_TOOLTIPS_PYTHON) && !but->optype && rna_struct.strinfo) {
+ if ((U.flag & USER_TOOLTIPS_PYTHON) && !optype && rna_struct.strinfo) {
{
uiTooltipField *field = text_field_add(data,
&(uiTooltipFormat){
@@ -1002,9 +1011,9 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
/* never fails */
/* move ownership (no need for re-alloc) */
- if (but->rnaprop) {
+ if (rnaprop) {
field->text = RNA_path_full_property_py_ex(
- CTX_data_main(C), &but->rnapoin, but->rnaprop, but->rnaindex, true);
+ CTX_data_main(C), &but->rnapoin, rnaprop, but->rnaindex, true);
}
else {
field->text = RNA_path_full_struct_py(CTX_data_main(C), &but->rnapoin);
@@ -1394,11 +1403,8 @@ static ARegion *ui_tooltip_create_with_data(bContext *C,
/** \name ToolTip Public API
* \{ */
-/**
- * \param is_label: When true, show a small tip that only shows the name,
- * otherwise show the full tooltip.
- */
-ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *but, bool is_label)
+ARegion *UI_tooltip_create_from_button_or_extra_icon(
+ bContext *C, ARegion *butregion, uiBut *but, uiButExtraOpIcon *extra_icon, bool is_label)
{
wmWindow *win = CTX_wm_window(C);
/* aspect values that shrink text are likely unreadable */
@@ -1415,7 +1421,11 @@ ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *b
}
if (data == NULL) {
- data = ui_tooltip_data_from_button(C, but);
+ data = ui_tooltip_data_from_button_or_extra_icon(C, but, extra_icon);
+ }
+
+ if (data == NULL) {
+ data = ui_tooltip_data_from_button_or_extra_icon(C, but, NULL);
}
if (data == NULL) {
@@ -1453,6 +1463,15 @@ ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *b
return region;
}
+/**
+ * \param is_label: When true, show a small tip that only shows the name, otherwise show the full
+ * tooltip.
+ */
+ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *but, bool is_label)
+{
+ return UI_tooltip_create_from_button_or_extra_icon(C, butregion, but, NULL, is_label);
+}
+
ARegion *UI_tooltip_create_from_gizmo(bContext *C, wmGizmo *gz)
{
wmWindow *win = CTX_wm_window(C);