UI: Allow label for Template-ID (respecting property split layout)
authorJulian Eisel <eiseljulian@gmail.com>
Mon, 25 Nov 2019 18:41:30 +0000 (19:41 +0100)
committerJulian Eisel <eiseljulian@gmail.com>
Mon, 25 Nov 2019 18:50:34 +0000 (19:50 +0100)
Adds a `text` parameter to `bpy.types.uiLayout.template_ID()` which
causes a label to be added, as usual. Adding the label also makes the
template respect the `bpy.types.uiLayout.use_property_split` option.

Also fixes wrong layout being used in the template-ID, although I think
that didn't cause issues in practice.

Sergey requested this for usage in the Movie Clip Editor.

source/blender/editors/include/UI_interface.h
source/blender/editors/interface/interface_layout.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/space_clip/clip_buttons.c
source/blender/editors/space_image/image_buttons.c
source/blender/editors/space_nla/nla_buttons.c
source/blender/editors/space_node/drawnode.c
source/blender/makesrna/intern/rna_ui_api.c

index 69229f25917833042beb01b8576eef280a3dd8d0..b81fa4ae483814e4d909b790bddf29a30363e628 100644 (file)
@@ -1875,7 +1875,8 @@ void uiTemplateID(uiLayout *layout,
                   const char *openop,
                   const char *unlinkop,
                   int filter,
-                  const bool live_icon);
+                  const bool live_icon,
+                  const char *text);
 void uiTemplateIDBrowse(uiLayout *layout,
                         struct bContext *C,
                         struct PointerRNA *ptr,
@@ -1883,7 +1884,8 @@ void uiTemplateIDBrowse(uiLayout *layout,
                         const char *newop,
                         const char *openop,
                         const char *unlinkop,
-                        int filter);
+                        int filter,
+                        const char *text);
 void uiTemplateIDPreview(uiLayout *layout,
                          struct bContext *C,
                          struct PointerRNA *ptr,
@@ -2270,6 +2272,7 @@ void uiItemsFullEnumO_items(uiLayout *layout,
                             int totitem);
 
 void uiItemL(uiLayout *layout, const char *name, int icon); /* label */
+uiLayout *uiItemL_respect_property_split(uiLayout *layout, const char *text, int icon);
 /* label icon for dragging */
 void uiItemLDrag(uiLayout *layout, struct PointerRNA *ptr, const char *name, int icon);
 /* menu */
index 2a4c2aba4a174e264a2d79ab4612c225eec93127..52696475c20637049f88d86a305b2a7ce0c81911 100644 (file)
@@ -2956,6 +2956,41 @@ void uiItemL(uiLayout *layout, const char *name, int icon)
   uiItemL_(layout, name, icon);
 }
 
+/**
+ * Helper to add a label, which handles logic for split property layout if needed.
+ *
+ * Normally, we handle the split layout in #uiItemFullR(), but there are other cases where we may
+ * want to use the logic. For those this helper was added, although it will likely have to be
+ * extended to support more cases.
+ * Ideally, #uiItemFullR() could just call this, but it currently has too many special needs.
+ *
+ * \return the layout to place the item(s) associated to the label in.
+ */
+uiLayout *uiItemL_respect_property_split(uiLayout *layout, const char *text, int icon)
+{
+  if (layout->item.flag & UI_ITEM_PROP_SEP) {
+    uiLayout *layout_split = uiLayoutSplit(layout, UI_ITEM_PROP_SEP_DIVIDE, true);
+    uiLayout *layout_sub = uiLayoutColumn(layout_split, true);
+
+    layout_split->space = layout_sub->space = layout->space = 0;
+    layout_sub->alignment = UI_LAYOUT_ALIGN_RIGHT;
+
+    uiItemL_(layout_sub, text, icon);
+
+    /* Give caller a new sub-row to place items in. */
+    return uiLayoutRow(layout_split, true);
+  }
+  else {
+    char namestr[UI_MAX_NAME_STR];
+    if (text) {
+      text = ui_item_name_add_colon(text, namestr);
+    }
+    uiItemL_(layout, text, icon);
+
+    return layout;
+  }
+}
+
 void uiItemLDrag(uiLayout *layout, PointerRNA *ptr, const char *name, int icon)
 {
   uiBut *but = uiItemL_(layout, name, icon);
index a65e70d41096320436337458ca8eda289e5b5c7a..5788b7411081b46772e59af3b9dbebd0e471eade 100644 (file)
@@ -780,6 +780,7 @@ static void template_ID(bContext *C,
                         const char *newop,
                         const char *openop,
                         const char *unlinkop,
+                        const char *text,
                         const bool live_icon,
                         const bool hide_buttons)
 {
@@ -803,6 +804,11 @@ static void template_ID(bContext *C,
     type = idptr.type;
   }
 
+  if (text) {
+    /* Add label resepecting the seperated layout property split state. */
+    layout = uiItemL_respect_property_split(layout, text, ICON_NONE);
+  }
+
   if (flag & UI_ID_BROWSE) {
     template_add_button_search_menu(C,
                                     layout,
@@ -1187,6 +1193,7 @@ static void ui_template_id(uiLayout *layout,
                            const char *newop,
                            const char *openop,
                            const char *unlinkop,
+                           const char *text,
                            int flag,
                            int prv_rows,
                            int prv_cols,
@@ -1239,13 +1246,22 @@ static void ui_template_id(uiLayout *layout,
    */
   if (template_ui->idlb) {
     if (use_tabs) {
-      uiLayoutRow(layout, true);
+      layout = uiLayoutRow(layout, true);
       template_ID_tabs(C, layout, template_ui, type, flag, newop, unlinkop);
     }
     else {
-      uiLayoutRow(layout, true);
-      template_ID(
-          C, layout, template_ui, type, flag, newop, openop, unlinkop, live_icon, hide_buttons);
+      layout = uiLayoutRow(layout, true);
+      template_ID(C,
+                  layout,
+                  template_ui,
+                  type,
+                  flag,
+                  newop,
+                  openop,
+                  unlinkop,
+                  text,
+                  live_icon,
+                  hide_buttons);
     }
   }
 
@@ -1260,7 +1276,8 @@ void uiTemplateID(uiLayout *layout,
                   const char *openop,
                   const char *unlinkop,
                   int filter,
-                  const bool live_icon)
+                  const bool live_icon,
+                  const char *text)
 {
   ui_template_id(layout,
                  C,
@@ -1269,6 +1286,7 @@ void uiTemplateID(uiLayout *layout,
                  newop,
                  openop,
                  unlinkop,
+                 text,
                  UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE,
                  0,
                  0,
@@ -1286,7 +1304,8 @@ void uiTemplateIDBrowse(uiLayout *layout,
                         const char *newop,
                         const char *openop,
                         const char *unlinkop,
-                        int filter)
+                        int filter,
+                        const char *text)
 {
   ui_template_id(layout,
                  C,
@@ -1295,6 +1314,7 @@ void uiTemplateIDBrowse(uiLayout *layout,
                  newop,
                  openop,
                  unlinkop,
+                 text,
                  UI_ID_BROWSE | UI_ID_RENAME,
                  0,
                  0,
@@ -1324,6 +1344,7 @@ void uiTemplateIDPreview(uiLayout *layout,
                  newop,
                  openop,
                  unlinkop,
+                 NULL,
                  UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS,
                  rows,
                  cols,
@@ -1350,6 +1371,7 @@ void uiTemplateGpencilColorPreview(uiLayout *layout,
                  NULL,
                  NULL,
                  NULL,
+                 NULL,
                  UI_ID_BROWSE | UI_ID_PREVIEWS | UI_ID_DELETE,
                  rows,
                  cols,
@@ -1378,6 +1400,7 @@ void uiTemplateIDTabs(uiLayout *layout,
                  newop,
                  NULL,
                  unlinkop,
+                 NULL,
                  UI_ID_BROWSE | UI_ID_RENAME,
                  0,
                  0,
@@ -7485,8 +7508,16 @@ void uiTemplateCacheFile(uiLayout *layout, bContext *C, PointerRNA *ptr, const c
 
   uiLayoutSetContextPointer(layout, "edit_cachefile", &fileptr);
 
-  uiTemplateID(
-      layout, C, ptr, propname, NULL, "CACHEFILE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+  uiTemplateID(layout,
+               C,
+               ptr,
+               propname,
+               NULL,
+               "CACHEFILE_OT_open",
+               NULL,
+               UI_TEMPLATE_ID_FILTER_ALL,
+               false,
+               NULL);
 
   if (!file) {
     return;
index 45707d74d2ead507060981282420cbeb66062eeb..34b4967beaf67c685fa6c06a6257cac3e6cc938e 100644 (file)
@@ -135,8 +135,16 @@ void uiTemplateMovieClip(
   uiLayoutSetContextPointer(layout, "edit_movieclip", &clipptr);
 
   if (!compact) {
-    uiTemplateID(
-        layout, C, ptr, propname, NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+    uiTemplateID(layout,
+                 C,
+                 ptr,
+                 propname,
+                 NULL,
+                 "CLIP_OT_open",
+                 NULL,
+                 UI_TEMPLATE_ID_FILTER_ALL,
+                 false,
+                 NULL);
   }
 
   if (clip) {
index 64e1c02590ec41e7978941754fa4ef7f33139909..270fe0c59dcd0e419e88aa8713cf622070a5b013 100644 (file)
@@ -813,7 +813,8 @@ void uiTemplateImage(uiLayout *layout,
                  "IMAGE_OT_open",
                  NULL,
                  UI_TEMPLATE_ID_FILTER_ALL,
-                 false);
+                 false,
+                 NULL);
 
     if (ima != NULL) {
       uiItemS(layout);
index 126b20a028ee230b39bbcac51c62eed4bf6a9f1a..b908ed2b7eee36e59bfb9f7dcf2dcd6663bd189c 100644 (file)
@@ -296,7 +296,8 @@ static void nla_panel_animdata(const bContext *C, Panel *pa)
                NULL,
                "NLA_OT_action_unlink",
                UI_TEMPLATE_ID_FILTER_ALL,
-               false);
+               false,
+               NULL);
 
   /* extrapolation */
   row = uiLayoutRow(layout, true);
index a5b18ff7589bc373693435f0bd452df98ff309b4..b60764c410d0a42d7bb57cd65d93586119eba0f1 100644 (file)
@@ -293,7 +293,8 @@ static int node_resize_area_default(bNode *node, int x, int y)
 
 static void node_draw_buttons_group(uiLayout *layout, bContext *C, PointerRNA *ptr)
 {
-  uiTemplateIDBrowse(layout, C, ptr, "node_tree", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL);
+  uiTemplateIDBrowse(
+      layout, C, ptr, "node_tree", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, NULL);
 }
 
 /* XXX Does a bounding box update by iterating over all children.
@@ -770,7 +771,8 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA
                "IMAGE_OT_open",
                NULL,
                UI_TEMPLATE_ID_FILTER_ALL,
-               false);
+               false,
+               NULL);
   uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE);
   uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
 
@@ -806,7 +808,8 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin
                "IMAGE_OT_open",
                NULL,
                UI_TEMPLATE_ID_FILTER_ALL,
-               false);
+               false,
+               NULL);
 
   uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE);
   uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
@@ -1337,7 +1340,8 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *
                "IMAGE_OT_open",
                NULL,
                UI_TEMPLATE_ID_FILTER_ALL,
-               false);
+               false,
+               NULL);
   if (!node->id) {
     return;
   }
@@ -1369,7 +1373,7 @@ static void node_composit_buts_viewlayers(uiLayout *layout, bContext *C, Pointer
   const char *layer_name;
   char scene_name[MAX_ID_NAME - 2];
 
-  uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+  uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
 
   if (!node->id) {
     return;
@@ -1489,7 +1493,7 @@ static void node_composit_buts_defocus(uiLayout *layout, bContext *C, PointerRNA
   col = uiLayoutColumn(layout, false);
   uiItemR(col, ptr, "use_preview", 0, NULL, ICON_NONE);
 
-  uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+  uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
 
   col = uiLayoutColumn(layout, false);
   uiItemR(col, ptr, "use_zbuffer", 0, NULL, ICON_NONE);
@@ -2107,7 +2111,7 @@ static void node_composit_buts_ycc(uiLayout *layout, bContext *UNUSED(C), Pointe
 static void node_composit_buts_movieclip(uiLayout *layout, bContext *C, PointerRNA *ptr)
 {
   uiTemplateID(
-      layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+      layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
 }
 
 static void node_composit_buts_movieclip_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -2116,7 +2120,7 @@ static void node_composit_buts_movieclip_ex(uiLayout *layout, bContext *C, Point
   PointerRNA clipptr;
 
   uiTemplateID(
-      layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+      layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
 
   if (!node->id) {
     return;
@@ -2132,7 +2136,7 @@ static void node_composit_buts_stabilize2d(uiLayout *layout, bContext *C, Pointe
   bNode *node = ptr->data;
 
   uiTemplateID(
-      layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+      layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
 
   if (!node->id) {
     return;
@@ -2158,7 +2162,7 @@ static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, Po
   bNode *node = ptr->data;
 
   uiTemplateID(
-      layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+      layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
 
   if (!node->id) {
     return;
@@ -2481,7 +2485,7 @@ static void node_composit_buts_mask(uiLayout *layout, bContext *C, PointerRNA *p
 {
   bNode *node = ptr->data;
 
-  uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+  uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
   uiItemR(layout, ptr, "use_feather", 0, NULL, ICON_NONE);
 
   uiItemR(layout, ptr, "size_source", 0, "", ICON_NONE);
@@ -2502,7 +2506,7 @@ static void node_composit_buts_keyingscreen(uiLayout *layout, bContext *C, Point
 {
   bNode *node = ptr->data;
 
-  uiTemplateID(layout, C, ptr, "clip", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+  uiTemplateID(layout, C, ptr, "clip", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
 
   if (node->id) {
     MovieClip *clip = (MovieClip *)node->id;
@@ -2539,7 +2543,7 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN
   bNode *node = ptr->data;
 
   uiTemplateID(
-      layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+      layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
 
   if (node->id) {
     MovieClip *clip = (MovieClip *)node->id;
@@ -2580,7 +2584,7 @@ static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, P
   NodePlaneTrackDeformData *data = node->storage;
 
   uiTemplateID(
-      layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+      layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
 
   if (node->id) {
     MovieClip *clip = (MovieClip *)node->id;
@@ -3013,7 +3017,8 @@ static void node_texture_buts_image(uiLayout *layout, bContext *C, PointerRNA *p
                "IMAGE_OT_open",
                NULL,
                UI_TEMPLATE_ID_FILTER_ALL,
-               false);
+               false,
+               NULL);
 }
 
 static void node_texture_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
index c734720fdcd365c95b49b016741b374c77ae3183..527df695f5bfa4630ddddd4df294aeb985593b29 100644 (file)
@@ -435,6 +435,32 @@ static void rna_uiItemPopoverPanelFromGroup(uiLayout *layout,
   uiItemPopoverPanelFromGroup(layout, C, space_id, region_id, context, category);
 }
 
+static void rna_uiTemplateID(uiLayout *layout,
+                             bContext *C,
+                             PointerRNA *ptr,
+                             const char *propname,
+                             const char *newop,
+                             const char *openop,
+                             const char *unlinkop,
+                             int filter,
+                             const bool live_icon,
+                             const char *name,
+                             const char *text_ctxt,
+                             bool translate)
+{
+  PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+
+  if (!prop) {
+    RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+    return;
+  }
+
+  /* Get translated name (label). */
+  name = rna_translate_ui_text(name, text_ctxt, NULL, prop, translate);
+
+  uiTemplateID(layout, C, ptr, propname, newop, openop, unlinkop, filter, live_icon, name);
+}
+
 static void rna_uiTemplateAnyID(uiLayout *layout,
                                 PointerRNA *ptr,
                                 const char *propname,
@@ -1014,7 +1040,7 @@ void RNA_api_ui_layout(StructRNA *srna)
   RNA_def_function_flag(func, FUNC_USE_CONTEXT);
   RNA_def_function_ui_description(func, "Inserts common Space header UI (editor type selector)");
 
-  func = RNA_def_function(srna, "template_ID", "uiTemplateID");
+  func = RNA_def_function(srna, "template_ID", "rna_uiTemplateID");
   RNA_def_function_flag(func, FUNC_USE_CONTEXT);
   api_ui_item_rna_common(func);
   RNA_def_string(func, "new", NULL, 0, "", "Operator identifier to create a new ID block");
@@ -1028,6 +1054,7 @@ void RNA_api_ui_layout(StructRNA *srna)
                "",
                "Optionally limit the items which can be selected");
   RNA_def_boolean(func, "live_icon", false, "", "Show preview instead of fixed icon");
+  api_ui_item_common_text(func);
 
   func = RNA_def_function(srna, "template_ID_preview", "uiTemplateIDPreview");
   RNA_def_function_flag(func, FUNC_USE_CONTEXT);