UI: Input Placeholders #112104

Merged
Harley Acheson merged 32 commits from Harley/blender:placeholders into blender-v4.0-release 2023-10-11 00:47:20 +02:00
7 changed files with 79 additions and 4 deletions

View File

@ -588,6 +588,7 @@ def dump_py_messages_from_files(msgs, reports, files, settings):
),
"message": (),
"heading": (),
"placeholder": ((("text_ctxt",), _ctxt_to_ctxt),),
}
context_kw_set = {}
@ -621,7 +622,8 @@ def dump_py_messages_from_files(msgs, reports, files, settings):
for arg_pos, (arg_kw, arg) in enumerate(func.parameters.items()):
if (not arg.is_output) and (arg.type == 'STRING'):
for msgid, msgctxts in context_kw_set.items():
if arg_kw in msgctxts:
# The msgid can be missing if it is used in only some UILayout functions but not all
if arg_kw in msgctxts and msgid in func_translate_args[func_id]:
func_translate_args[func_id][msgid][1][arg_kw] = arg_pos
# The report() func of operators.
for func_id, func in bpy.types.Operator.bl_rna.functions.items():

View File

@ -933,6 +933,11 @@ void UI_but_disable(uiBut *but, const char *disabled_hint);
void UI_but_type_set_menu_from_pulldown(uiBut *but);
/**
* Set at hint that describes the expected value when empty.
*/
void UI_but_placeholder_set(uiBut *but, const char *placeholder_text) ATTR_NONNULL(1);
/**
* Special button case, only draw it when used actively, for outliner etc.
*
@ -2775,7 +2780,8 @@ void uiItemFullR(uiLayout *layout,
int value,
eUI_Item_Flag flag,
const char *name,
int icon);
int icon,
const char *placeholder = nullptr);
/**
* Use a wrapper function since re-implementing all the logic in this function would be messy.
*/

View File

@ -61,6 +61,7 @@
#include "WM_types.hh"
#include "RNA_access.hh"
#include "RNA_enum_types.hh"
#ifdef WITH_PYTHON
# include "BPY_extern_run.h"
@ -3477,6 +3478,10 @@ static void ui_but_free(const bContext *C, uiBut *but)
MEM_freeN(but->hold_argN);
}
if (but->placeholder) {
MEM_freeN(but->placeholder);
}
ui_but_free_type_specific(but);
if (but->active) {
@ -5906,6 +5911,36 @@ void UI_but_disable(uiBut *but, const char *disabled_hint)
but->disabled_info = disabled_hint;
}
void UI_but_placeholder_set(uiBut *but, const char *placeholder_text)
{
MEM_SAFE_FREE(but->placeholder);
but->placeholder = BLI_strdup_null(placeholder_text);
}
const char *ui_but_placeholder_get(uiBut *but)
{
const char *placeholder = (but->placeholder) ? but->placeholder : nullptr;
if (!placeholder && but->rnaprop) {
if (but->type == UI_BTYPE_SEARCH_MENU) {
StructRNA *type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
const short idcode = RNA_type_to_ID_code(type);
if (idcode != 0) {
RNA_enum_name(rna_enum_id_type_items, idcode, &placeholder);
placeholder = CTX_IFACE_(BLT_I18NCONTEXT_ID_ID, placeholder);
}
}
else if (but->type == UI_BTYPE_TEXT) {
const char *identifier = RNA_property_identifier(but->rnaprop);
if (STR_ELEM(identifier, "search_filter", "filter_text", "filter_search")) {
placeholder = CTX_IFACE_(BLT_I18NCONTEXT_ID_WINDOWMANAGER, "Search");
}
}
}
return placeholder;
}
void UI_but_type_set_menu_from_pulldown(uiBut *but)
{
BLI_assert(but->type == UI_BTYPE_PULLDOWN);

View File

@ -175,6 +175,8 @@ struct uiBut {
char strdata[UI_MAX_NAME_STR] = "";
char drawstr[UI_MAX_DRAW_STR] = "";
char *placeholder = nullptr;
rctf rect = {}; /* block relative coords */
char *poin = nullptr;
@ -742,6 +744,11 @@ void ui_but_active_string_clear_and_exit(bContext *C, uiBut *but) ATTR_NONNULL()
void ui_but_set_string_interactive(bContext *C, uiBut *but, const char *value);
uiBut *ui_but_drag_multi_edit_get(uiBut *but);
/**
* Get the hint that describes the expected value when empty.
*/
const char *ui_but_placeholder_get(uiBut *but);
void ui_def_but_icon(uiBut *but, int icon, int flag);
/**
* Avoid using this where possible since it's better not to ask for an icon in the first place.

View File

@ -2055,7 +2055,8 @@ void uiItemFullR(uiLayout *layout,
int value,
eUI_Item_Flag flag,
const char *name,
int icon)
int icon,
const char *placeholder)
{
uiBlock *block = layout->root->block;
char namestr[UI_MAX_NAME_STR];
@ -2468,6 +2469,10 @@ void uiItemFullR(uiLayout *layout,
UI_but_flag_enable(but, UI_BUT_LIST_ITEM);
}
if (but && placeholder) {
UI_but_placeholder_set(but, placeholder);
}
#ifdef UI_PROP_DECORATE
if (ui_decorate.use_prop_decorate) {
uiBut *but_decorate = ui_decorate.but ? ui_decorate.but->next :

View File

@ -2187,6 +2187,22 @@ static void widget_draw_text(const uiFontStyle *fstyle,
}
}
/* Show placeholder text if the input is empty and not being edited. */
if (!drawstr[0] && !but->editstr && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
const char *placeholder = ui_but_placeholder_get(but);
if (placeholder && placeholder[0]) {
uiFontStyleDraw_Params params{};
params.align = align;
uiFontStyle style = *fstyle;
style.shadow = 0;
uchar col[4];
copy_v4_v4_uchar(col, wcol->text);
col[3] *= 0.33f;
UI_fontstyle_draw_ex(
&style, rect, placeholder, strlen(placeholder), col, &params, nullptr, nullptr, nullptr);
}
}
/* part text right aligned */
if (drawstr_right) {
uchar col[4];

View File

@ -84,6 +84,7 @@ static void rna_uiItemR(uiLayout *layout,
const char *text_ctxt,
bool translate,
int icon,
const char *placeholder,
bool expand,
bool slider,
int toggle,
@ -109,6 +110,7 @@ static void rna_uiItemR(uiLayout *layout,
/* Get translated name (label). */
name = rna_translate_ui_text(name, text_ctxt, nullptr, prop, translate);
placeholder = rna_translate_ui_text(placeholder, text_ctxt, nullptr, prop, translate);
if (slider) {
flag |= UI_ITEM_R_SLIDER;
@ -140,7 +142,7 @@ static void rna_uiItemR(uiLayout *layout,
flag |= UI_ITEM_R_CHECKBOX_INVERT;
}
uiItemFullR(layout, ptr, prop, index, 0, flag, name, icon);
uiItemFullR(layout, ptr, prop, index, 0, flag, name, icon, placeholder);
}
static void rna_uiItemR_with_popover(uiLayout *layout,
@ -1147,6 +1149,8 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_function_ui_description(func, "Item. Exposes an RNA item and places it into the layout");
api_ui_item_rna_common(func);
api_ui_item_common(func);
RNA_def_string(
func, "placeholder", nullptr, 0, "", "Hint describing the expected value when empty");
RNA_def_boolean(func, "expand", false, "", "Expand button to show more detail");
RNA_def_boolean(func, "slider", false, "", "Use slider widget for numeric values");
RNA_def_int(func,