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
diff options
context:
space:
mode:
authorJulian Eisel <julian@blender.org>2020-12-18 20:12:11 +0300
committerJulian Eisel <julian@blender.org>2020-12-18 20:28:04 +0300
commit2250b5cefee7f7cce31e388cb83515543ffe60f0 (patch)
treecbac53205d453f4b1c7ec221b6377a672d9eaa09 /source/blender/editors/interface/interface_templates.c
parent7bee1489c1d81ecf2634df96ba039549c64313c3 (diff)
UI: Redesigned data-block selectors
The previous design is rather old and has a couple of problems: * Scalability: The current solution of adding little icon buttons next to the data-block name field doesn't scale well. It only works if there's a small number of operations. We need to be able to place more items there for better data-block management. Especially with the introduction of library overrides. * Discoverability: It's not obvious what some of the icons do. They appear and disappear, but it's not obvious why some are available at times and others not. * Unclear Status: Currently their library status (linked, indirectly linked, broken link, library override) isn't really clear. * Unusual behavior: Some of the icon buttons allow Shift or Ctrl clicking to invoke alternative behaviors. This is not a usual pattern in Blender. This patch does the following changes: * Adds a menu to the right of the name button to access all kinds of operations (create, delete, unlink, user management, library overrides, etc). * Make good use of the "disabled hint" for tooltips, to explain why buttons are disabled. The UI team wants to establish this as a good practise. * Use superimposed icons for duplicate and unlink, rather than extra buttons (uses less space, looks less distracting and is a nice + consistent design language). * Remove fake user and user count button, they are available from the menu now. * Support tooltips for superimposed icons (committed mouse hover feedback to master already). * Slightly increase size of the name button - it was already a bit small before, and the move from real buttons to superimposed icons reduces usable space for the name itself. * More clearly differentiate between duplicate and creating a new data-block. The latter is only available in the menu. * Display library status icon on the left (linked, missing library, overridden, asset) * Disables "Make Single User" button - in review we weren't sure if there are good use-cases for it, so better to see if we can remove it. Note that I do expect some aspects of this design to change still. I think some changes are problematic, but others disagreed. I will open a feedback thread on devtalk to see what others think. Differential Revision: https://developer.blender.org/D8554 Reviewed by: Bastien Montagne Design discussed and agreed on with the UI team, also see T79959.
Diffstat (limited to 'source/blender/editors/interface/interface_templates.c')
-rw-r--r--source/blender/editors/interface/interface_templates.c1086
1 files changed, 680 insertions, 406 deletions
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index b895f1702f4..6e96704271f 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -102,9 +102,16 @@
// #define USE_OP_RESET_BUT
/* defines for templateID/TemplateSearch */
-#define TEMPLATE_SEARCH_TEXTBUT_WIDTH (UI_UNIT_X * 6)
+#define TEMPLATE_SEARCH_TEXTBUT_WIDTH (UI_UNIT_X * 8)
#define TEMPLATE_SEARCH_TEXTBUT_HEIGHT UI_UNIT_Y
+/* Add "Make Single User" button to templateID. Users can just manually duplicate an ID, it's
+ * unclear what the use-case of this specific button is. So for now disabling it, we can bring it
+ * back or remove it later.
+ * - Julian
+ */
+//#define USE_TEMPLATE_ID_MAKE_SINGLE_USER
+
void UI_template_fix_linking(void)
{
}
@@ -308,6 +315,12 @@ typedef struct TemplateID {
ListBase *idlb;
short idcode;
+
+ const char *new_op;
+ const char *duplicate_op;
+ const char *unlink_op;
+ const char *open_op;
+
short filter;
int prv_rows, prv_cols;
bool preview;
@@ -564,80 +577,64 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
memset(&idptr, 0, sizeof(idptr));
RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);
RNA_property_update(C, &template_ui->ptr, template_ui->prop);
-
- if (id && CTX_wm_window(C)->eventstate->shift) {
- /* only way to force-remove data (on save) */
- id_us_clear_real(id);
- id_fake_user_clear(id);
- id->us = 0;
- undo_push_label = "Delete Data-Block";
- }
-
break;
- case UI_ID_FAKE_USER:
+ case UI_ID_MAKE_LOCAL:
if (id) {
- if (id->flag & LIB_FAKEUSER) {
- id_us_plus(id);
- }
- else {
- id_us_min(id);
+ Main *bmain = CTX_data_main(C);
+ if (BKE_lib_id_make_local(bmain, id, false, 0)) {
+ BKE_main_id_clear_newpoins(bmain);
+
+ /* reassign to get get proper updates/notifiers */
+ idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
+ RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);
+ RNA_property_update(C, &template_ui->ptr, template_ui->prop);
+ undo_push_label = "Make Local";
}
- undo_push_label = "Fake User";
- }
- else {
- return;
}
break;
- case UI_ID_LOCAL:
- if (id) {
+ case UI_ID_LIB_OVERRIDE_ADD:
+ if (id && ID_IS_OVERRIDABLE_LIBRARY(id)) {
Main *bmain = CTX_data_main(C);
- if (CTX_wm_window(C)->eventstate->shift) {
- if (ID_IS_OVERRIDABLE_LIBRARY(id)) {
- /* Only remap that specific ID usage to overriding local data-block. */
- ID *override_id = BKE_lib_override_library_create_from_id(bmain, id, false);
- if (override_id != NULL) {
- BKE_main_id_clear_newpoins(bmain);
-
- if (GS(override_id->name) == ID_OB) {
- Scene *scene = CTX_data_scene(C);
- if (!BKE_collection_has_object_recursive(scene->master_collection,
- (Object *)override_id)) {
- BKE_collection_object_add_from(
- bmain, scene, (Object *)id, (Object *)override_id);
- }
- }
-
- /* Assign new pointer, takes care of updates/notifiers */
- RNA_id_pointer_create(override_id, &idptr);
+ /* Only remap that specific ID usage to overriding local data-block. */
+ ID *override_id = BKE_lib_override_library_create_from_id(bmain, id, false);
+ if (override_id != NULL) {
+ BKE_main_id_clear_newpoins(bmain);
+
+ if (GS(override_id->name) == ID_OB) {
+ Scene *scene = CTX_data_scene(C);
+ if (!BKE_collection_has_object_recursive(scene->master_collection,
+ (Object *)override_id)) {
+ BKE_collection_object_add_from(bmain, scene, (Object *)id, (Object *)override_id);
}
- undo_push_label = "Make Library Override";
}
- }
- else {
- if (BKE_lib_id_make_local(bmain, id, false, 0)) {
- BKE_main_id_clear_newpoins(bmain);
- /* reassign to get get proper updates/notifiers */
- idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
- undo_push_label = "Make Local";
- }
- }
- if (undo_push_label != NULL) {
- RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);
- RNA_property_update(C, &template_ui->ptr, template_ui->prop);
+ /* Assign new pointer, takes care of updates/notifiers */
+ RNA_id_pointer_create(override_id, &idptr);
}
+ /* reassign to get get proper updates/notifiers */
+ RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);
+ RNA_property_update(C, &template_ui->ptr, template_ui->prop);
+ undo_push_label = "Make Library Override";
}
break;
- case UI_ID_OVERRIDE:
+ case UI_ID_LIB_OVERRIDE_RESET:
+ if (id && ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ Main *bmain = CTX_data_main(C);
+ BKE_lib_override_library_id_reset(bmain, id);
+ undo_push_label = "Reset Library Override";
+ }
+ break;
+ case UI_ID_LIB_OVERRIDE_REMOVE:
if (id && ID_IS_OVERRIDE_LIBRARY(id)) {
BKE_lib_override_library_free(&id->override_library, true);
/* reassign to get get proper updates/notifiers */
idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);
RNA_property_update(C, &template_ui->ptr, template_ui->prop);
- undo_push_label = "Override Data-Block";
+ undo_push_label = "Remove Library Override";
}
break;
+#ifdef USE_TEMPLATE_ID_MAKE_SINGLE_USER
case UI_ID_ALONE:
if (id) {
const bool do_scene_obj = ((GS(id->name) == ID_OB) &&
@@ -659,6 +656,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
undo_push_label = "Make Single User";
}
break;
+#endif
#if 0
case UI_ID_AUTO_NAME:
break;
@@ -772,17 +770,221 @@ static const char *template_id_context(StructRNA *type)
# define template_id_context(type) 0
#endif
-static uiBut *template_id_def_new_but(uiBlock *block,
- const ID *id,
- const TemplateID *template_ui,
- StructRNA *type,
- const char *const newop,
- const bool editable,
- const bool id_open,
- const bool use_tab_but,
- int but_height)
-{
+static void template_id_linked_operation_button(
+ uiBlock *block, Main *bmain, ID *id, TemplateID *template_ui, int operation)
+{
+ BLI_assert(ELEM(operation, UI_ID_MAKE_LOCAL, UI_ID_LIB_OVERRIDE_ADD));
+
+ const char *label = (operation == UI_ID_MAKE_LOCAL) ?
+ CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Make Local") :
+ CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Library Override");
+ const char *tip = (operation == UI_ID_MAKE_LOCAL) ?
+ N_("Make library linked data-block local to this file") :
+ N_("Create a local override of this library linked data-block");
+ BIFIconID icon = (operation == UI_ID_MAKE_LOCAL) ? ICON_BLANK1 : ICON_LIBRARY_DATA_OVERRIDE;
+
+ uiBut *but = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ icon,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, label),
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_(tip));
+
+ bool disabled = false;
+
+ if (!ID_IS_LINKED(id)) {
+ disabled = true;
+ but->disabled_info = TIP_("Data-block is not linked");
+ }
+ else if (id->tag & LIB_TAG_INDIRECT) {
+ disabled = true;
+ but->disabled_info = TIP_("Indirect library data-block, cannot change");
+ }
+ else if (!BKE_lib_id_make_local(bmain, id, true /* test */, 0)) {
+ disabled = true;
+ but->disabled_info = TIP_("Data-blocks of this type cannot be made local");
+ }
+ else if (!RNA_property_editable_info(
+ &template_ui->ptr, template_ui->prop, &but->disabled_info)) {
+ disabled = true;
+ }
+
+ if (disabled) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ else {
+ UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(operation));
+ }
+}
+
+static void template_id_library_overridden_button(uiBlock *block,
+ ID *id,
+ TemplateID *template_ui,
+ int operation)
+{
+ BLI_assert(ELEM(operation, UI_ID_LIB_OVERRIDE_RESET, UI_ID_LIB_OVERRIDE_REMOVE) &&
+ ID_IS_OVERRIDE_LIBRARY(id));
+
+ if (operation == UI_ID_LIB_OVERRIDE_RESET && ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ uiBut *but = uiDefIconTextBut(
+ block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_BLANK1,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset Library Override"),
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Reset the local override to the state of "
+ "the overridden data-block"));
+ if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ but->disabled_info = TIP_("Data-block is a virtual, not a real override");
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ else {
+ UI_but_funcN_set(but,
+ template_id_cb,
+ MEM_dupallocN(template_ui),
+ POINTER_FROM_INT(UI_ID_LIB_OVERRIDE_RESET));
+ }
+ }
+ else if (operation == UI_ID_LIB_OVERRIDE_REMOVE) {
+ uiBut *but = uiDefIconTextBut(
+ block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_BLANK1,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Make Local"),
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Remove library override and make the library linked data-block "
+ "fully local to this file"));
+ UI_but_funcN_set(but,
+ template_id_cb,
+ MEM_dupallocN(template_ui),
+ POINTER_FROM_INT(UI_ID_LIB_OVERRIDE_REMOVE));
+ }
+}
+
+#ifdef USE_TEMPLATE_ID_MAKE_SINGLE_USER
+static uiBut *template_id_make_single_user_button(uiBlock *block, ID *id, TemplateID *template_ui)
+{
+ uiBut *but = uiDefIconTextBut(
+ block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_BLANK1,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Make Single-User Copy"),
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Duplicate the data-block and assign the newly created copy"));
+
+ if (ID_REAL_USERS(id) <= 1) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ but->disabled_info = TIP_("Data-block already is a single-user");
+ /* No need for further setup. */
+ return but;
+ }
+
+ UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ALONE));
+
ID *idfrom = template_ui->ptr.owner_id;
+ bool disabled = false;
+
+ if (!RNA_property_editable_info(&template_ui->ptr, template_ui->prop, &but->disabled_info)) {
+ disabled = true;
+ }
+ if (!BKE_id_copy_is_allowed(id)) {
+ but->disabled_info = TIP_("Data-blocks of this type cannot be copied");
+ disabled = true;
+ }
+ /* object in editmode - don't change data */
+ if (idfrom && GS(idfrom->name) == ID_OB && (((Object *)idfrom)->mode & OB_MODE_EDIT)) {
+ but->disabled_info = TIP_("Cannot change object data in Edit Mode");
+ disabled = true;
+ }
+
+ if (disabled) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+
+ return but;
+}
+#endif
+
+static void template_id_use_fake_user_button(uiBlock *block, PointerRNA *idptr)
+{
+ const bool use_fake_user = ID_FAKE_USERS(idptr->data) > 0;
+ uiBut *but = uiDefIconTextButR(
+ block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ ICON_FAKE_USER_OFF,
+ use_fake_user ? CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Fake User") :
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Fake User"),
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ idptr,
+ "use_fake_user",
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ TIP_("When set, ensures the data-block is kept when reloading the file, even if not used at "
+ "all"));
+
+ if ((ELEM(GS(((ID *)idptr->data)->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) {
+ but->disabled_info = TIP_("Data-block type does not support fake user");
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+}
+
+enum TemplateIDCreateType {
+ TEMPLATE_ID_CREATE_NEW,
+ TEMPLATE_ID_CREATE_DUPLICATE,
+};
+
+static uiBut *template_id_new_button(uiBlock *block,
+ const ID *id,
+ TemplateID *template_ui,
+ enum TemplateIDCreateType create_type,
+ StructRNA *type,
+ const bool id_open,
+ const bool use_tab_but,
+ int but_height)
+{
uiBut *but;
const int w = id ? UI_UNIT_X : id_open ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
const int but_type = use_tab_but ? UI_BTYPE_TAB : UI_BTYPE_BUT;
@@ -820,54 +1022,384 @@ static uiBut *template_id_def_new_but(uiBlock *block,
BLT_I18NCONTEXT_ID_POINTCLOUD,
BLT_I18NCONTEXT_ID_VOLUME,
BLT_I18NCONTEXT_ID_SIMULATION, );
+ BLT_I18N_MSGID_MULTI_CTXT("Duplicate",
+ BLT_I18NCONTEXT_DEFAULT,
+ BLT_I18NCONTEXT_ID_SCENE,
+ BLT_I18NCONTEXT_ID_OBJECT,
+ BLT_I18NCONTEXT_ID_MESH,
+ BLT_I18NCONTEXT_ID_CURVE,
+ BLT_I18NCONTEXT_ID_METABALL,
+ BLT_I18NCONTEXT_ID_MATERIAL,
+ BLT_I18NCONTEXT_ID_TEXTURE,
+ BLT_I18NCONTEXT_ID_IMAGE,
+ BLT_I18NCONTEXT_ID_LATTICE,
+ BLT_I18NCONTEXT_ID_LIGHT,
+ BLT_I18NCONTEXT_ID_CAMERA,
+ BLT_I18NCONTEXT_ID_WORLD,
+ BLT_I18NCONTEXT_ID_SCREEN,
+ BLT_I18NCONTEXT_ID_TEXT, );
+ BLT_I18N_MSGID_MULTI_CTXT("Duplicate",
+ BLT_I18NCONTEXT_ID_SPEAKER,
+ BLT_I18NCONTEXT_ID_SOUND,
+ BLT_I18NCONTEXT_ID_ARMATURE,
+ BLT_I18NCONTEXT_ID_ACTION,
+ BLT_I18NCONTEXT_ID_NODETREE,
+ BLT_I18NCONTEXT_ID_BRUSH,
+ BLT_I18NCONTEXT_ID_PARTICLESETTINGS,
+ BLT_I18NCONTEXT_ID_GPENCIL,
+ BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE,
+ BLT_I18NCONTEXT_ID_WORKSPACE,
+ BLT_I18NCONTEXT_ID_LIGHTPROBE,
+ BLT_I18NCONTEXT_ID_HAIR,
+ BLT_I18NCONTEXT_ID_POINTCLOUD,
+ BLT_I18NCONTEXT_ID_VOLUME,
+ BLT_I18NCONTEXT_ID_SIMULATION, );
/* Note: BLT_I18N_MSGID_MULTI_CTXT takes a maximum number of parameters,
* check the definition to see if a new call must be added when the limit
* is exceeded. */
- if (newop) {
+ const char *text;
+ const char *op;
+ BIFIconID icon;
+
+ switch (create_type) {
+ case TEMPLATE_ID_CREATE_NEW:
+ icon = ICON_ADD;
+ text = CTX_IFACE_(template_id_context(type), "New");
+ op = template_ui->new_op;
+ break;
+ case TEMPLATE_ID_CREATE_DUPLICATE:
+ icon = ICON_DUPLICATE;
+ text = CTX_IFACE_(template_id_context(type), "Duplicate");
+ op = template_ui->duplicate_op;
+ break;
+ }
+
+ const bool icon_only = use_tab_but;
+ if (icon_only) {
+ text = "";
+ }
+
+ if (op) {
+ but = uiDefIconTextButO(
+ block, but_type, op, WM_OP_INVOKE_DEFAULT, icon, text, 0, 0, w, but_height, NULL);
+ UI_but_funcN_set(
+ but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ADD_NEW));
+
+ if (!RNA_property_editable_info(&template_ui->ptr, template_ui->prop, &but->disabled_info)) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ }
+ else {
+ but = uiDefIconTextBut(block,
+ but_type,
+ 0,
+ icon,
+ text,
+ 0,
+ 0,
+ w,
+ but_height,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Create a new data-block"));
+ but->disabled_info = TIP_("Creating a new data-block is not supported here");
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ if (icon_only) {
+ UI_but_drawflag_disable(but, UI_BUT_ICON_LEFT);
+ }
+
+#ifndef WITH_INTERNATIONAL
+ UNUSED_VARS(type);
+#endif
+
+ return but;
+}
+
+static void template_id_unlink_button(uiBlock *block,
+ TemplateID *template_ui,
+ bool hide_if_disabled)
+{
+ const char *disable_info;
+ const bool is_menu = ui_block_is_menu(block);
+ const bool editable = RNA_property_editable_info(
+ &template_ui->ptr, template_ui->prop, &disable_info);
+ /* allow unlink if 'unlinkop' is passed, even when 'PROP_NEVER_UNLINK' is set */
+ uiBut *but = NULL;
+
+ if (hide_if_disabled && !editable) {
+ /* Add no button. */
+ }
+ else if (template_ui->unlink_op) {
+ but = uiDefIconTextButO(block,
+ UI_BTYPE_BUT,
+ template_ui->unlink_op,
+ WM_OP_INVOKE_DEFAULT,
+ ICON_X,
+ is_menu ? NULL : "",
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL);
+ /* so we can access the template from operators, font unlinking needs this */
+ UI_but_funcN_set(but, NULL, MEM_dupallocN(template_ui), NULL);
+ }
+ else {
+ const bool never_unlink = RNA_property_flag(template_ui->prop) &
+ (PROP_NEVER_UNLINK | PROP_NEVER_NULL);
+
+ if (!never_unlink || !hide_if_disabled) {
+ but = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_X,
+ is_menu ? CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Unlink") : "",
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Remove this usage of the data-block"));
+ if (!never_unlink) {
+ UI_but_funcN_set(
+ but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_DELETE));
+ }
+ if (!is_menu) {
+ UI_but_drawflag_disable(but, UI_BUT_ICON_LEFT);
+ }
+ }
+
+ if (but && never_unlink) {
+ but->disabled_info = TIP_("Property must never be in an unlinked state");
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ }
+
+ if (but) {
+ if (!editable) {
+ but->disabled_info = disable_info;
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ }
+}
+
+static void template_id_open_button(uiBlock *block,
+ ID *id,
+ TemplateID *template_ui,
+ const bool compact)
+{
+ const bool is_menu = ui_block_is_menu(block);
+ const int w = compact ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
+ char text[UI_MAX_NAME_STR] = "";
+ const bool icon_only = !is_menu && id;
+ uiBut *but;
+
+ if (!icon_only) {
+ BLI_snprintf(text,
+ sizeof(text),
+ "%s%s",
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open"),
+ is_menu ? "..." : "");
+ }
+
+ if (template_ui->open_op) {
but = uiDefIconTextButO(block,
- but_type,
- newop,
+ UI_BTYPE_BUT,
+ template_ui->open_op,
WM_OP_INVOKE_DEFAULT,
- (id && !use_tab_but) ? ICON_DUPLICATE : ICON_ADD,
- (id) ? "" : CTX_IFACE_(template_id_context(type), "New"),
+ ICON_FILEBROWSER,
+ text,
0,
0,
w,
- but_height,
+ UI_UNIT_Y,
NULL);
UI_but_funcN_set(
- but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ADD_NEW));
+ but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_OPEN));
}
else {
but = uiDefIconTextBut(block,
- but_type,
+ UI_BTYPE_BUT,
0,
- (id && !use_tab_but) ? ICON_DUPLICATE : ICON_ADD,
- (id) ? "" : CTX_IFACE_(template_id_context(type), "New"),
+ ICON_FILEBROWSER,
+ text,
0,
0,
w,
- but_height,
+ UI_UNIT_Y,
NULL,
0,
0,
0,
0,
NULL);
- UI_but_funcN_set(
- but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ADD_NEW));
+ but->disabled_info = TIP_("Browsing for a new data-block is not supported here");
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
}
- if ((idfrom && idfrom->lib) || !editable) {
+ if (!RNA_property_editable_info(&template_ui->ptr, template_ui->prop, &but->disabled_info)) {
UI_but_flag_enable(but, UI_BUT_DISABLED);
}
+}
-#ifndef WITH_INTERNATIONAL
- UNUSED_VARS(type);
+static void template_id_unpack_button(uiBlock *block, ID *id)
+{
+ wmOperatorType *optype = WM_operatortype_find("FILE_OT_unpack_item", false);
+ uiBut *but;
+
+ but = uiDefIconTextButO_ptr(block,
+ UI_BTYPE_BUT,
+ optype,
+ WM_OP_INVOKE_REGION_WIN,
+ ICON_PACKAGE,
+ NULL,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL);
+
+ if (!BKE_packedfile_id_check(id)) {
+ but->disabled_info = TIP_("File is not packed");
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ UI_but_operator_ptr_get(but);
+
+ RNA_string_set(but->opptr, "id_name", id->name + 2);
+ RNA_int_set(but->opptr, "id_type", GS(id->name));
+}
+
+static void template_id_user_count_label(uiLayout *layout, const ID *id)
+{
+ char numstr[UI_MAX_NAME_STR];
+ BLI_snprintf(numstr,
+ sizeof(numstr),
+ "%d %s",
+ ID_REAL_USERS(id),
+ ID_REAL_USERS(id) > 1 ? IFACE_("Users") : IFACE_("User"));
+ uiItemL(layout, numstr, ICON_NONE);
+}
+
+static void template_id_menu(bContext *C, uiLayout *layout, void *arg)
+{
+ /* Button that spawned the menu. */
+ const uiBut *menu_parent_but = arg;
+ TemplateID *template_ui = menu_parent_but->func_argN;
+ PointerRNA idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
+ ID *id = idptr.data;
+ uiBlock *block = uiLayoutGetBlock(layout);
+
+ BLI_assert(id);
+
+ template_id_new_button(
+ block, id, template_ui, TEMPLATE_ID_CREATE_NEW, idptr.type, false, false, UI_UNIT_X);
+ template_id_new_button(
+ block, id, template_ui, TEMPLATE_ID_CREATE_DUPLICATE, idptr.type, false, false, UI_UNIT_X);
+ template_id_unlink_button(block, template_ui, false);
+
+#ifdef USE_TEMPLATE_ID_MAKE_SINGLE_USER
+ template_id_make_single_user_button(block, id, template_ui);
#endif
+ template_id_use_fake_user_button(block, &idptr);
- return but;
+ if (template_ui->open_op || BKE_packedfile_id_check(id)) {
+ uiItemS(layout);
+
+ template_id_open_button(block, id, template_ui, false);
+ template_id_unpack_button(block, id);
+ }
+
+ /* Library operators. */
+ if (ID_IS_OVERRIDE_LIBRARY(id)) {
+ uiItemS(layout);
+
+ template_id_library_overridden_button(block, id, template_ui, UI_ID_LIB_OVERRIDE_RESET);
+ template_id_library_overridden_button(block, id, template_ui, UI_ID_LIB_OVERRIDE_REMOVE);
+ }
+ else if (ID_IS_LINKED(id)) {
+ uiItemS(layout);
+
+ Main *bmain = CTX_data_main(C);
+ template_id_linked_operation_button(block, bmain, id, template_ui, UI_ID_MAKE_LOCAL);
+ template_id_linked_operation_button(block, bmain, id, template_ui, UI_ID_LIB_OVERRIDE_ADD);
+ }
+
+ uiItemS(layout);
+ template_id_user_count_label(layout, id);
+}
+
+static void template_id_name_button(
+ uiBlock *block, StructRNA *type, TemplateID *template_ui, int flag, const bool hide_extras)
+{
+ PointerRNA idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
+ ID *id = idptr.data;
+ BIFIconID lib_icon = UI_icon_from_library(id);
+
+ char name[UI_MAX_NAME_STR] = "";
+ uiBut *but = uiDefIconTextButR(block,
+ UI_BTYPE_TEXT,
+ 0,
+ lib_icon,
+ name,
+ 0,
+ 0,
+ TEMPLATE_SEARCH_TEXTBUT_WIDTH,
+ TEMPLATE_SEARCH_TEXTBUT_HEIGHT,
+ &idptr,
+ "name",
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ RNA_struct_ui_description(type));
+ /* Note: Also needed for the extra icons below (their operators access the TemplateID). */
+ UI_but_funcN_set(
+ but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_RENAME));
+
+ const bool user_alert = (id->us <= 0);
+ if (user_alert) {
+ UI_but_flag_enable(but, UI_BUT_REDALERT);
+ }
+
+ if (hide_extras) {
+ return;
+ }
+
+ if (template_ui->duplicate_op && (flag & UI_ID_ADD_NEW)) {
+ UI_but_extra_operator_icon_add(
+ but, template_ui->duplicate_op, WM_OP_INVOKE_DEFAULT, ICON_DUPLICATE);
+ }
+
+ if (id && (flag & UI_ID_DELETE)) {
+ const bool never_unlink = RNA_property_flag(template_ui->prop) &
+ (PROP_NEVER_UNLINK | PROP_NEVER_NULL);
+ if (template_ui->unlink_op) {
+ UI_but_extra_operator_icon_add(but, template_ui->unlink_op, WM_OP_INVOKE_DEFAULT, ICON_X);
+ }
+ else if (!never_unlink) {
+ UI_but_extra_operator_icon_add(but, "ED_OT_lib_unlink", WM_OP_INVOKE_DEFAULT, ICON_X);
+ }
+ }
+
+ /* Disable fake user icon for now, only have it in the menu. */
+ const bool add_extra_fake_user_icon = false;
+ if (add_extra_fake_user_icon && id->lib == NULL &&
+ !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) {
+ UI_but_extra_operator_icon_add(but,
+ "ED_OT_lib_fake_user_toggle",
+ WM_OP_INVOKE_DEFAULT,
+ ID_FAKE_USERS(id) ? ICON_FAKE_USER_ON : ICON_FAKE_USER_OFF);
+ }
}
static void template_ID(const bContext *C,
@@ -875,9 +1407,6 @@ static void template_ID(const bContext *C,
TemplateID *template_ui,
StructRNA *type,
int flag,
- const char *newop,
- const char *openop,
- const char *unlinkop,
const char *text,
const bool live_icon,
const bool hide_buttons)
@@ -885,15 +1414,12 @@ static void template_ID(const bContext *C,
uiBut *but;
uiBlock *block;
PointerRNA idptr;
- // ListBase *lb; // UNUSED
- ID *id, *idfrom;
+ ID *id;
const bool editable = RNA_property_editable(&template_ui->ptr, template_ui->prop);
const bool use_previews = template_ui->preview = (flag & UI_ID_PREVIEWS) != 0;
idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
id = idptr.data;
- idfrom = template_ui->ptr.owner_id;
- // lb = template_ui->idlb;
/* Allow opertators to take the ID from context. */
uiLayoutSetContextPointer(layout, "id", &idptr);
@@ -926,277 +1452,39 @@ static void template_ID(const bContext *C,
/* text button with name */
if (id) {
- char name[UI_MAX_NAME_STR];
- const bool user_alert = (id->us <= 0);
-
- // text_idbutton(id, name);
- name[0] = '\0';
- but = uiDefButR(block,
- UI_BTYPE_TEXT,
- 0,
- name,
- 0,
- 0,
- TEMPLATE_SEARCH_TEXTBUT_WIDTH,
- TEMPLATE_SEARCH_TEXTBUT_HEIGHT,
- &idptr,
- "name",
- -1,
- 0,
- 0,
- -1,
- -1,
- RNA_struct_ui_description(type));
- UI_but_funcN_set(
- but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_RENAME));
- if (user_alert) {
- UI_but_flag_enable(but, UI_BUT_REDALERT);
- }
-
- if (id->lib) {
- if (id->tag & LIB_TAG_INDIRECT) {
- but = uiDefIconBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_LIBRARY_DATA_INDIRECT,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- TIP_("Indirect library data-block, cannot change"));
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- else {
- const bool disabled = (!BKE_lib_id_make_local(CTX_data_main(C), id, true /* test */, 0) ||
- (idfrom && idfrom->lib));
- but = uiDefIconBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_LIBRARY_DATA_DIRECT,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- TIP_("Direct linked library data-block, click to make local, "
- "Shift + Click to create a library override"));
- if (disabled) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- else {
- UI_but_funcN_set(
- but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_LOCAL));
- }
- }
- }
- else if (ID_IS_OVERRIDE_LIBRARY(id)) {
- but = uiDefIconBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_LIBRARY_DATA_OVERRIDE,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- TIP_("Library override of linked data-block, click to make fully local"));
- UI_but_funcN_set(
- but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_OVERRIDE));
- }
-
- if ((ID_REAL_USERS(id) > 1) && (hide_buttons == false)) {
- char numstr[32];
- short numstr_len;
-
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", ID_REAL_USERS(id));
-
- but = uiDefBut(
- block,
- UI_BTYPE_BUT,
- 0,
- numstr,
- 0,
- 0,
- numstr_len * 0.2f * UI_UNIT_X + UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- TIP_("Display number of users of this data (click to make a single-user copy)"));
- but->flag |= UI_BUT_UNDO;
-
- UI_but_funcN_set(
- but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ALONE));
- if ((!BKE_id_copy_is_allowed(id)) || (idfrom && idfrom->lib) || (!editable) ||
- /* object in editmode - don't change data */
- (idfrom && GS(idfrom->name) == ID_OB && (((Object *)idfrom)->mode & OB_MODE_EDIT))) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- }
-
- if (user_alert) {
- UI_but_flag_enable(but, UI_BUT_REDALERT);
- }
-
- if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS)) &&
- (hide_buttons == false)) {
- uiDefIconButR(block,
- UI_BTYPE_ICON_TOGGLE,
- 0,
- ICON_FAKE_USER_OFF,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- &idptr,
- "use_fake_user",
- -1,
- 0,
- 0,
- -1,
- -1,
- NULL);
- }
+ template_id_name_button(block, type, template_ui, flag, hide_buttons);
}
-
- if ((flag & UI_ID_ADD_NEW) && (hide_buttons == false)) {
- template_id_def_new_but(
- block, id, template_ui, type, newop, editable, flag & UI_ID_OPEN, false, UI_UNIT_X);
+ /* If no ID is set, show a "new" button instead of a text button. */
+ else if ((flag & UI_ID_ADD_NEW) && (hide_buttons == false)) {
+ template_id_new_button(
+ block, id, template_ui, TEMPLATE_ID_CREATE_NEW, type, flag & UI_ID_OPEN, false, UI_UNIT_X);
}
- /* Due to space limit in UI - skip the "open" icon for packed data, and allow to unpack.
- * Only for images, sound and fonts */
- if (id && BKE_packedfile_id_check(id)) {
- but = uiDefIconButO(block,
- UI_BTYPE_BUT,
- "FILE_OT_unpack_item",
- WM_OP_INVOKE_REGION_WIN,
- ICON_PACKAGE,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- TIP_("Packed File, click to unpack"));
- UI_but_operator_ptr_get(but);
-
- RNA_string_set(but->opptr, "id_name", id->name + 2);
- RNA_int_set(but->opptr, "id_type", GS(id->name));
+ if ((flag & UI_ID_OPEN) && !id) {
+ template_id_open_button(block, id, template_ui, flag & UI_ID_ADD_NEW);
}
- else if (flag & UI_ID_OPEN) {
- const int w = id ? UI_UNIT_X : (flag & UI_ID_ADD_NEW) ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
-
- if (openop) {
- but = uiDefIconTextButO(block,
- UI_BTYPE_BUT,
- openop,
- WM_OP_INVOKE_DEFAULT,
- ICON_FILEBROWSER,
- (id) ? "" : IFACE_("Open"),
- 0,
- 0,
- w,
- UI_UNIT_Y,
- NULL);
- UI_but_funcN_set(
- but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_OPEN));
- }
- else {
- but = uiDefIconTextBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_FILEBROWSER,
- (id) ? "" : IFACE_("Open"),
- 0,
- 0,
- w,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- NULL);
- UI_but_funcN_set(
- but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_OPEN));
- }
- if ((idfrom && idfrom->lib) || !editable) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
+ if (template_ui->idcode == ID_TE) {
+ uiTemplateTextureShow(layout, C, &template_ui->ptr, template_ui->prop);
}
- /* delete button */
- /* don't use RNA_property_is_unlink here */
- if (id && (flag & UI_ID_DELETE) && (hide_buttons == false)) {
- /* allow unlink if 'unlinkop' is passed, even when 'PROP_NEVER_UNLINK' is set */
- but = NULL;
-
- if (unlinkop) {
- but = uiDefIconButO(block,
- UI_BTYPE_BUT,
- unlinkop,
- WM_OP_INVOKE_DEFAULT,
- ICON_X,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL);
- /* so we can access the template from operators, font unlinking needs this */
- UI_but_funcN_set(but, NULL, MEM_dupallocN(template_ui), NULL);
- }
- else {
- if ((RNA_property_flag(template_ui->prop) & PROP_NEVER_UNLINK) == 0) {
- but = uiDefIconBut(
- block,
- UI_BTYPE_BUT,
- 0,
- ICON_X,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- TIP_("Unlink data-block "
- "(Shift + Click to set users to zero, data will then not be saved)"));
- UI_but_funcN_set(
- but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_DELETE));
-
- if (RNA_property_flag(template_ui->prop) & PROP_NEVER_NULL) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- }
- }
-
- if (but) {
- if ((idfrom && idfrom->lib) || !editable) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- }
+ if (id && !hide_buttons) {
+ /* Additional operations menu ("Make Local", overrides, etc). */
+ but = uiDefIconMenuBut(block,
+ template_id_menu,
+ NULL,
+ ICON_DOWNARROW_HLT,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ TIP_("Show more operations for the selected data-block"));
+ UI_but_type_set_menu_from_pulldown(but);
+ /* Same hack as ui_item_menu() to allow allocated arg. */
+ but->poin = (char *)but;
+ but->func_argN = MEM_dupallocN(template_ui);
}
- if (template_ui->idcode == ID_TE) {
- uiTemplateTextureShow(layout, C, &template_ui->ptr, template_ui->prop);
- }
UI_block_align_end(block);
}
@@ -1215,7 +1503,6 @@ static void template_ID_tabs(const bContext *C,
TemplateID *template,
StructRNA *type,
int flag,
- const char *newop,
const char *menu)
{
const ARegion *region = CTX_wm_region(C);
@@ -1263,22 +1550,20 @@ static void template_ID_tabs(const bContext *C,
BLI_freelistN(&ordered);
if (flag & UI_ID_ADD_NEW) {
- const bool editable = RNA_property_editable(&template->ptr, template->prop);
uiBut *but;
if (active_ptr.type) {
type = active_ptr.type;
}
- but = template_id_def_new_but(block,
- active_ptr.data,
- template,
- type,
- newop,
- editable,
- flag & UI_ID_OPEN,
- true,
- but_height);
+ but = template_id_new_button(block,
+ active_ptr.data,
+ template,
+ TEMPLATE_ID_CREATE_NEW,
+ type,
+ flag & UI_ID_OPEN,
+ true,
+ but_height);
UI_but_drawflag_enable(but, but_align);
}
}
@@ -1288,6 +1573,7 @@ static void ui_template_id(uiLayout *layout,
PointerRNA *ptr,
const char *propname,
const char *newop,
+ const char *duplicateop,
const char *openop,
const char *unlinkop,
/* Only respected by tabs (use_tabs). */
@@ -1317,6 +1603,10 @@ static void ui_template_id(uiLayout *layout,
template_ui = MEM_callocN(sizeof(TemplateID), "TemplateID");
template_ui->ptr = *ptr;
template_ui->prop = prop;
+ template_ui->new_op = newop;
+ template_ui->duplicate_op = duplicateop;
+ template_ui->unlink_op = unlinkop;
+ template_ui->open_op = openop;
template_ui->prv_rows = prv_rows;
template_ui->prv_cols = prv_cols;
template_ui->scale = scale;
@@ -1328,7 +1618,7 @@ static void ui_template_id(uiLayout *layout,
template_ui->filter = 0;
}
- if (newop) {
+ if (newop || duplicateop) {
flag |= UI_ID_ADD_NEW;
}
if (openop) {
@@ -1346,21 +1636,11 @@ static void ui_template_id(uiLayout *layout,
if (template_ui->idlb) {
if (use_tabs) {
layout = uiLayoutRow(layout, true);
- template_ID_tabs(C, layout, template_ui, type, flag, newop, menu);
+ template_ID_tabs(C, layout, template_ui, type, flag, menu);
}
else {
layout = uiLayoutRow(layout, true);
- template_ID(C,
- layout,
- template_ui,
- type,
- flag,
- newop,
- openop,
- unlinkop,
- text,
- live_icon,
- hide_buttons);
+ template_ID(C, layout, template_ui, type, flag, text, live_icon, hide_buttons);
}
}
@@ -1372,6 +1652,7 @@ void uiTemplateID(uiLayout *layout,
PointerRNA *ptr,
const char *propname,
const char *newop,
+ const char *duplicateop,
const char *openop,
const char *unlinkop,
int filter,
@@ -1383,6 +1664,7 @@ void uiTemplateID(uiLayout *layout,
ptr,
propname,
newop,
+ duplicateop,
openop,
unlinkop,
NULL,
@@ -1412,6 +1694,7 @@ void uiTemplateIDBrowse(uiLayout *layout,
ptr,
propname,
newop,
+ NULL,
openop,
unlinkop,
NULL,
@@ -1443,6 +1726,7 @@ void uiTemplateIDPreview(uiLayout *layout,
ptr,
propname,
newop,
+ NULL,
openop,
unlinkop,
NULL,
@@ -1475,6 +1759,7 @@ void uiTemplateGpencilColorPreview(uiLayout *layout,
NULL,
NULL,
NULL,
+ NULL,
UI_ID_BROWSE | UI_ID_PREVIEWS | UI_ID_DELETE,
rows,
cols,
@@ -1503,6 +1788,7 @@ void uiTemplateIDTabs(uiLayout *layout,
newop,
NULL,
NULL,
+ NULL,
menu,
NULL,
UI_ID_BROWSE | UI_ID_RENAME,
@@ -1662,35 +1948,25 @@ static void template_search_add_button_searchmenu(const bContext *C,
static void template_search_add_button_name(uiBlock *block,
PointerRNA *active_ptr,
- const StructRNA *type)
+ const StructRNA *type,
+ const char *newop,
+ const char *unlinkop)
{
- uiDefAutoButR(block,
- active_ptr,
- RNA_struct_name_property(type),
- 0,
- "",
- ICON_NONE,
- 0,
- 0,
- TEMPLATE_SEARCH_TEXTBUT_WIDTH,
- TEMPLATE_SEARCH_TEXTBUT_HEIGHT);
-}
-
-static void template_search_add_button_operator(uiBlock *block,
- const char *const operator_name,
- const int opcontext,
- const int icon,
- const bool editable)
-{
- if (!operator_name) {
- return;
+ uiBut *but = uiDefAutoButR(block,
+ active_ptr,
+ RNA_struct_name_property(type),
+ 0,
+ "",
+ ICON_NONE,
+ 0,
+ 0,
+ TEMPLATE_SEARCH_TEXTBUT_WIDTH,
+ TEMPLATE_SEARCH_TEXTBUT_HEIGHT);
+ if (newop) {
+ UI_but_extra_operator_icon_add(but, newop, WM_OP_INVOKE_DEFAULT, ICON_DUPLICATE);
}
-
- uiBut *but = uiDefIconButO(
- block, UI_BTYPE_BUT, operator_name, opcontext, icon, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
-
- if (!editable) {
- UI_but_drawflag_enable(but, UI_BUT_DISABLED);
+ if (unlinkop) {
+ UI_but_extra_operator_icon_add(but, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X);
}
}
@@ -1716,10 +1992,7 @@ static void template_search_buttons(const bContext *C,
UI_block_align_begin(block);
template_search_add_button_searchmenu(C, layout, block, template_search, editable, false);
- template_search_add_button_name(block, &active_ptr, type);
- template_search_add_button_operator(
- block, newop, WM_OP_INVOKE_DEFAULT, ICON_DUPLICATE, editable);
- template_search_add_button_operator(block, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, editable);
+ template_search_add_button_name(block, &active_ptr, type, newop, unlinkop);
UI_block_align_end(block);
}
@@ -7191,6 +7464,7 @@ void uiTemplateCacheFile(uiLayout *layout,
ptr,
propname,
NULL,
+ NULL,
"CACHEFILE_OT_open",
NULL,
UI_TEMPLATE_ID_FILTER_ALL,