Add ctrl-click rename to most lists in Blender UI and templates/examples.
[blender.git] / doc / python_api / examples / bpy.types.UIList.1.py
1 """
2 Basic UIList Example
3 ++++++++++++++++++++
4
5 This script is the UIList subclass used to show material slots, with a bunch of additional commentaries.
6
7 Notice the name of the class, this naming convention is similar as the one for panels or menus.
8
9 .. note::
10
11    UIList subclasses must be registered for blender to use them.
12 """
13 import bpy
14
15
16 class MATERIAL_UL_matslots_example(bpy.types.UIList):
17     # The draw_item function is called for each item of the collection that is visible in the list.
18     #   data is the RNA object containing the collection,
19     #   item is the current drawn item of the collection,
20     #   icon is the "computed" icon for the item (as an integer, because some objects like materials or textures
21     #   have custom icons ID, which are not available as enum items).
22     #   active_data is the RNA object containing the active property for the collection (i.e. integer pointing to the
23     #   active item of the collection).
24     #   active_propname is the name of the active property (use 'getattr(active_data, active_propname)').
25     #   index is index of the current item in the collection.
26     #   flt_flag is the result of the filtering process for this item.
27     #   Note: as index and flt_flag are optional arguments, you do not have to use/declare them here if you don't
28     #         need them.
29     def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
30         ob = data
31         slot = item
32         ma = slot.material
33         # draw_item must handle the three layout types... Usually 'DEFAULT' and 'COMPACT' can share the same code.
34         if self.layout_type in {'DEFAULT', 'COMPACT'}:
35             # You should always start your row layout by a label (icon + text), or a non-embossed text field,
36             # this will also make the row easily selectable in the list! The later also enables ctrl-click rename.
37             # We use icon_value of label, as our given icon is an integer value, not an enum ID.
38             # Note "data" names should never be translated!
39             if ma:
40                 layout.prop(ma, "name", text="", emboss=False, icon_value=icon)
41             else:
42                 layout.label(text="", translate=False, icon_value=icon)
43             # And now we can add other UI stuff...
44             # Here, we add nodes info if this material uses (old!) shading nodes.
45             if ma and not context.scene.render.use_shading_nodes:
46                 manode = ma.active_node_material
47                 if manode:
48                     # The static method UILayout.icon returns the integer value of the icon ID "computed" for the given
49                     # RNA object.
50                     layout.label(text="Node %s" % manode.name, translate=False, icon_value=layout.icon(manode))
51                 elif ma.use_nodes:
52                     layout.label(text="Node <none>", translate=False)
53                 else:
54                     layout.label(text="")
55         # 'GRID' layout type should be as compact as possible (typically a single icon!).
56         elif self.layout_type in {'GRID'}:
57             layout.alignment = 'CENTER'
58             layout.label(text="", icon_value=icon)
59
60
61 # And now we can use this list everywhere in Blender. Here is a small example panel.
62 class UIListPanelExample(bpy.types.Panel):
63     """Creates a Panel in the Object properties window"""
64     bl_label = "UIList Panel"
65     bl_idname = "OBJECT_PT_ui_list_example"
66     bl_space_type = 'PROPERTIES'
67     bl_region_type = 'WINDOW'
68     bl_context = "object"
69
70     def draw(self, context):
71         layout = self.layout
72
73         obj = context.object
74
75         # template_list now takes two new args.
76         # The first one is the identifier of the registered UIList to use (if you want only the default list,
77         # with no custom draw code, use "UI_UL_list").
78         layout.template_list("MATERIAL_UL_matslots_example", "", obj, "material_slots", obj, "active_material_index")
79
80         # The second one can usually be left as an empty string.
81         # It's an additional ID used to distinguish lists in case you use the same list several times in a given area.
82         layout.template_list("MATERIAL_UL_matslots_example", "compact", obj, "material_slots",
83                              obj, "active_material_index", type='COMPACT')
84
85
86 def register():
87     bpy.utils.register_class(MATERIAL_UL_matslots_example)
88     bpy.utils.register_class(UIListPanelExample)
89
90
91 def unregister():
92     bpy.utils.unregister_class(MATERIAL_UL_matslots_example)
93     bpy.utils.unregister_class(UIListPanelExample)
94
95
96 if __name__ == "__main__":
97     register()