Merge branch 'master' into blender2.8
[blender.git] / source / blender / makesrna / intern / rna_ui.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Blender Foundation (2009)
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/makesrna/intern/rna_ui.c
24  *  \ingroup RNA
25  */
26
27
28 #include <stdlib.h>
29
30 #include "DNA_screen_types.h"
31 #include "DNA_space_types.h"
32
33 #include "BLT_translation.h"
34
35 #include "BKE_idprop.h"
36
37 #include "RNA_define.h"
38
39 #include "rna_internal.h"
40 #include "RNA_enum_types.h"
41
42 #include "UI_interface.h"
43
44 #include "WM_types.h"
45 #include "WM_toolsystem.h"
46
47 /* see WM_types.h */
48 const EnumPropertyItem rna_enum_operator_context_items[] = {
49         {WM_OP_INVOKE_DEFAULT, "INVOKE_DEFAULT", 0, "Invoke Default", ""},
50         {WM_OP_INVOKE_REGION_WIN, "INVOKE_REGION_WIN", 0, "Invoke Region Window", ""},
51         {WM_OP_INVOKE_REGION_CHANNELS, "INVOKE_REGION_CHANNELS", 0, "Invoke Region Channels", ""},
52         {WM_OP_INVOKE_REGION_PREVIEW, "INVOKE_REGION_PREVIEW", 0, "Invoke Region Preview", ""},
53         {WM_OP_INVOKE_AREA, "INVOKE_AREA", 0, "Invoke Area", ""},
54         {WM_OP_INVOKE_SCREEN, "INVOKE_SCREEN", 0, "Invoke Screen", ""},
55         {WM_OP_EXEC_DEFAULT, "EXEC_DEFAULT", 0, "Exec Default", ""},
56         {WM_OP_EXEC_REGION_WIN, "EXEC_REGION_WIN", 0, "Exec Region Window", ""},
57         {WM_OP_EXEC_REGION_CHANNELS, "EXEC_REGION_CHANNELS", 0, "Exec Region Channels", ""},
58         {WM_OP_EXEC_REGION_PREVIEW, "EXEC_REGION_PREVIEW", 0, "Exec Region Preview", ""},
59         {WM_OP_EXEC_AREA, "EXEC_AREA", 0, "Exec Area", ""},
60         {WM_OP_EXEC_SCREEN, "EXEC_SCREEN", 0, "Exec Screen", ""},
61         {0, NULL, 0, NULL, NULL}
62 };
63
64 const EnumPropertyItem rna_enum_uilist_layout_type_items[] = {
65         {UILST_LAYOUT_DEFAULT, "DEFAULT", 0, "Default Layout", "Use the default, multi-rows layout"},
66         {UILST_LAYOUT_COMPACT, "COMPACT", 0, "Compact Layout", "Use the compact, single-row layout"},
67         {UILST_LAYOUT_GRID, "GRID", 0, "Grid Layout", "Use the grid-based layout"},
68         {0, NULL, 0, NULL, NULL}
69 };
70
71 #ifdef RNA_RUNTIME
72
73 #include <assert.h>
74
75 #include "MEM_guardedalloc.h"
76
77 #include "RNA_access.h"
78
79 #include "BLI_dynstr.h"
80
81 #include "BKE_context.h"
82 #include "BKE_report.h"
83 #include "BKE_screen.h"
84
85 #include "WM_api.h"
86
87 static ARegionType *region_type_find(ReportList *reports, int space_type, int region_type)
88 {
89         SpaceType *st;
90         ARegionType *art;
91
92         st = BKE_spacetype_from_id(space_type);
93
94         for (art = (st) ? st->regiontypes.first : NULL; art; art = art->next) {
95                 if (art->regionid == region_type)
96                         break;
97         }
98
99         /* region type not found? abort */
100         if (art == NULL) {
101                 BKE_report(reports, RPT_ERROR, "Region not found in space type");
102                 return NULL;
103         }
104
105         return art;
106 }
107
108 /* Panel */
109
110 static bool panel_poll(const bContext *C, PanelType *pt)
111 {
112         extern FunctionRNA rna_Panel_poll_func;
113
114         PointerRNA ptr;
115         ParameterList list;
116         FunctionRNA *func;
117         void *ret;
118         bool visible;
119
120         RNA_pointer_create(NULL, pt->ext.srna, NULL, &ptr); /* dummy */
121         func = &rna_Panel_poll_func; /* RNA_struct_find_function(&ptr, "poll"); */
122
123         RNA_parameter_list_create(&list, &ptr, func);
124         RNA_parameter_set_lookup(&list, "context", &C);
125         pt->ext.call((bContext *)C, &ptr, func, &list);
126
127         RNA_parameter_get_lookup(&list, "visible", &ret);
128         visible = *(bool *)ret;
129
130         RNA_parameter_list_free(&list);
131
132         return visible;
133 }
134
135 static void panel_draw(const bContext *C, Panel *pnl)
136 {
137         extern FunctionRNA rna_Panel_draw_func;
138
139         PointerRNA ptr;
140         ParameterList list;
141         FunctionRNA *func;
142
143         RNA_pointer_create(&CTX_wm_screen(C)->id, pnl->type->ext.srna, pnl, &ptr);
144         func = &rna_Panel_draw_func; /* RNA_struct_find_function(&ptr, "draw"); */
145
146         RNA_parameter_list_create(&list, &ptr, func);
147         RNA_parameter_set_lookup(&list, "context", &C);
148         pnl->type->ext.call((bContext *)C, &ptr, func, &list);
149
150         RNA_parameter_list_free(&list);
151 }
152
153 static void panel_draw_header(const bContext *C, Panel *pnl)
154 {
155         extern FunctionRNA rna_Panel_draw_header_func;
156
157         PointerRNA ptr;
158         ParameterList list;
159         FunctionRNA *func;
160
161         RNA_pointer_create(&CTX_wm_screen(C)->id, pnl->type->ext.srna, pnl, &ptr);
162         func = &rna_Panel_draw_header_func; /* RNA_struct_find_function(&ptr, "draw_header"); */
163
164         RNA_parameter_list_create(&list, &ptr, func);
165         RNA_parameter_set_lookup(&list, "context", &C);
166         pnl->type->ext.call((bContext *)C, &ptr, func, &list);
167
168         RNA_parameter_list_free(&list);
169 }
170
171 static void panel_draw_header_preset(const bContext *C, Panel *pnl)
172 {
173         extern FunctionRNA rna_Panel_draw_header_preset_func;
174
175         PointerRNA ptr;
176         ParameterList list;
177         FunctionRNA *func;
178
179         RNA_pointer_create(&CTX_wm_screen(C)->id, pnl->type->ext.srna, pnl, &ptr);
180         func = &rna_Panel_draw_header_preset_func;
181
182         RNA_parameter_list_create(&list, &ptr, func);
183         RNA_parameter_set_lookup(&list, "context", &C);
184         pnl->type->ext.call((bContext *)C, &ptr, func, &list);
185
186         RNA_parameter_list_free(&list);
187 }
188
189 static void rna_Panel_unregister(Main *UNUSED(bmain), StructRNA *type)
190 {
191         ARegionType *art;
192         PanelType *pt = RNA_struct_blender_type_get(type);
193
194         if (!pt)
195                 return;
196         if (!(art = region_type_find(NULL, pt->space_type, pt->region_type)))
197                 return;
198
199         RNA_struct_free_extension(type, &pt->ext);
200         RNA_struct_free(&BLENDER_RNA, type);
201
202         if (pt->parent) {
203                 LinkData *link = BLI_findptr(&pt->parent->children, pt, offsetof(LinkData, data));
204                 BLI_freelinkN(&pt->parent->children, link);
205         }
206
207         WM_paneltype_remove(pt);
208
209         for (LinkData *link = pt->children.first; link; link = link->next) {
210                 PanelType *child_pt = link->data;
211                 child_pt->parent = NULL;
212         }
213
214         BLI_freelistN(&pt->children);
215         BLI_freelinkN(&art->paneltypes, pt);
216
217         /* update while blender is running */
218         WM_main_add_notifier(NC_WINDOW, NULL);
219 }
220
221 static StructRNA *rna_Panel_register(
222         Main *bmain, ReportList *reports, void *data, const char *identifier,
223         StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
224 {
225         ARegionType *art;
226         PanelType *pt, *parent = NULL, dummypt = {NULL};
227         Panel dummypanel = {NULL};
228         PointerRNA dummyptr;
229         int have_function[4];
230
231         /* setup dummy panel & panel type to store static properties in */
232         dummypanel.type = &dummypt;
233         RNA_pointer_create(NULL, &RNA_Panel, &dummypanel, &dummyptr);
234
235         /* We have to set default context! Else we get a void string... */
236         strcpy(dummypt.translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
237
238         /* validate the python class */
239         if (validate(&dummyptr, data, have_function) != 0)
240                 return NULL;
241
242         if (strlen(identifier) >= sizeof(dummypt.idname)) {
243                 BKE_reportf(reports, RPT_ERROR, "Registering panel class: '%s' is too long, maximum length is %d",
244                             identifier, (int)sizeof(dummypt.idname));
245                 return NULL;
246         }
247
248         if ((1 << dummypt.region_type) & RGN_TYPE_HAS_CATEGORY_MASK) {
249                 if (dummypt.category[0] == '\0') {
250                         /* Use a fallback, otherwise an empty value will draw the panel in every category. */
251                         strcpy(dummypt.category, PNL_CATEGORY_FALLBACK);
252                 }
253         }
254         else {
255                 if (dummypt.category[0] != '\0') {
256                         if ((1 << dummypt.space_type) & WM_TOOLSYSTEM_SPACE_MASK) {
257                                 BKE_reportf(reports, RPT_ERROR, "Registering panel class: '%s' has category '%s' ",
258                                             dummypt.idname, dummypt.category);
259                                 return NULL;
260                         }
261                 }
262         }
263
264         if (!(art = region_type_find(reports, dummypt.space_type, dummypt.region_type)))
265                 return NULL;
266
267         /* check if we have registered this panel type before, and remove it */
268         for (pt = art->paneltypes.first; pt; pt = pt->next) {
269                 if (STREQ(pt->idname, dummypt.idname)) {
270                         if (pt->ext.srna)
271                                 rna_Panel_unregister(bmain, pt->ext.srna);
272                         else
273                                 BLI_freelinkN(&art->paneltypes, pt);
274                         break;
275                 }
276
277                 if (dummypt.parent_id[0] && STREQ(pt->idname, dummypt.parent_id)) {
278                         parent = pt;
279                 }
280         }
281         if (!RNA_struct_available_or_report(reports, dummypt.idname)) {
282                 return NULL;
283         }
284         if (!RNA_struct_bl_idname_ok_or_report(reports, dummypt.idname, "_PT_")) {
285                 return NULL;
286         }
287         if (dummypt.parent_id[0] && !parent) {
288                 BKE_reportf(reports, RPT_ERROR, "Registering panel class: parent '%s' for '%s' not found",
289                             dummypt.parent_id, dummypt.idname);
290                 return NULL;
291         }
292
293         /* create a new panel type */
294         pt = MEM_callocN(sizeof(PanelType), "python buttons panel");
295         memcpy(pt, &dummypt, sizeof(dummypt));
296
297         pt->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, pt->idname, &RNA_Panel);
298         RNA_def_struct_translation_context(pt->ext.srna, pt->translation_context);
299         pt->ext.data = data;
300         pt->ext.call = call;
301         pt->ext.free = free;
302         RNA_struct_blender_type_set(pt->ext.srna, pt);
303         RNA_def_struct_flag(pt->ext.srna, STRUCT_NO_IDPROPERTIES);
304
305         pt->poll = (have_function[0]) ? panel_poll : NULL;
306         pt->draw = (have_function[1]) ? panel_draw : NULL;
307         pt->draw_header = (have_function[2]) ? panel_draw_header : NULL;
308         pt->draw_header_preset = (have_function[3]) ? panel_draw_header_preset : NULL;
309
310         /* XXX use "no header" flag for some ordering of panels until we have real panel ordering */
311         if (pt->flag & PNL_NO_HEADER) {
312                 PanelType *pth = art->paneltypes.first;
313                 while (pth && pth->flag & PNL_NO_HEADER)
314                         pth = pth->next;
315
316                 if (pth)
317                         BLI_insertlinkbefore(&art->paneltypes, pth, pt);
318                 else
319                         BLI_addtail(&art->paneltypes, pt);
320         }
321         else
322                 BLI_addtail(&art->paneltypes, pt);
323
324         if (parent) {
325                 pt->parent = parent;
326                 BLI_addtail(&parent->children, BLI_genericNodeN(pt));
327         }
328
329         {
330                 const char *owner_id = RNA_struct_state_owner_get();
331                 if (owner_id) {
332                         BLI_strncpy(pt->owner_id, owner_id, sizeof(pt->owner_id));
333                 }
334         }
335
336         WM_paneltype_add(pt);
337
338         /* update while blender is running */
339         WM_main_add_notifier(NC_WINDOW, NULL);
340
341         return pt->ext.srna;
342 }
343
344 static StructRNA *rna_Panel_refine(PointerRNA *ptr)
345 {
346         Panel *menu = (Panel *)ptr->data;
347         return (menu->type && menu->type->ext.srna) ? menu->type->ext.srna : &RNA_Panel;
348 }
349
350 /* UIList */
351 static unsigned int rna_UIList_filter_const_FILTER_ITEM_get(PointerRNA *UNUSED(ptr))
352 {
353         return UILST_FLT_ITEM;
354 }
355
356 static IDProperty *rna_UIList_idprops(PointerRNA *ptr, bool create)
357 {
358         uiList *ui_list = (uiList *)ptr->data;
359         if (create && !ui_list->properties) {
360                 IDPropertyTemplate val = {0};
361                 ui_list->properties = IDP_New(IDP_GROUP, &val, "RNA_UIList IDproperties group");
362         }
363
364         return ui_list->properties;
365 }
366
367 static void uilist_draw_item(uiList *ui_list, bContext *C, uiLayout *layout, PointerRNA *dataptr, PointerRNA *itemptr,
368                              int icon, PointerRNA *active_dataptr, const char *active_propname, int index, int flt_flag)
369 {
370         extern FunctionRNA rna_UIList_draw_item_func;
371
372         PointerRNA ul_ptr;
373         ParameterList list;
374         FunctionRNA *func;
375
376         RNA_pointer_create(&CTX_wm_screen(C)->id, ui_list->type->ext.srna, ui_list, &ul_ptr);
377         func = &rna_UIList_draw_item_func; /* RNA_struct_find_function(&ul_ptr, "draw_item"); */
378
379         RNA_parameter_list_create(&list, &ul_ptr, func);
380         RNA_parameter_set_lookup(&list, "context", &C);
381         RNA_parameter_set_lookup(&list, "layout", &layout);
382         RNA_parameter_set_lookup(&list, "data", dataptr);
383         RNA_parameter_set_lookup(&list, "item", itemptr);
384         RNA_parameter_set_lookup(&list, "icon", &icon);
385         RNA_parameter_set_lookup(&list, "active_data", active_dataptr);
386         RNA_parameter_set_lookup(&list, "active_property", &active_propname);
387         RNA_parameter_set_lookup(&list, "index", &index);
388         RNA_parameter_set_lookup(&list, "flt_flag", &flt_flag);
389         ui_list->type->ext.call((bContext *)C, &ul_ptr, func, &list);
390
391         RNA_parameter_list_free(&list);
392 }
393
394 static void uilist_draw_filter(uiList *ui_list, bContext *C, uiLayout *layout, bool reverse)
395 {
396         extern FunctionRNA rna_UIList_draw_filter_func;
397
398         PointerRNA ul_ptr;
399         ParameterList list;
400         FunctionRNA *func;
401
402         RNA_pointer_create(&CTX_wm_screen(C)->id, ui_list->type->ext.srna, ui_list, &ul_ptr);
403         func = &rna_UIList_draw_filter_func; /* RNA_struct_find_function(&ul_ptr, "draw_filter"); */
404
405         RNA_parameter_list_create(&list, &ul_ptr, func);
406         RNA_parameter_set_lookup(&list, "context", &C);
407         RNA_parameter_set_lookup(&list, "layout", &layout);
408         RNA_parameter_set_lookup(&list, "reverse", &reverse);
409         ui_list->type->ext.call((bContext *)C, &ul_ptr, func, &list);
410
411         RNA_parameter_list_free(&list);
412 }
413
414 static void uilist_filter_items(uiList *ui_list, bContext *C, PointerRNA *dataptr, const char *propname)
415 {
416         extern FunctionRNA rna_UIList_filter_items_func;
417
418         PointerRNA ul_ptr;
419         ParameterList list;
420         FunctionRNA *func;
421         PropertyRNA *parm;
422
423         uiListDyn *flt_data = ui_list->dyn_data;
424         int *filter_flags, *filter_neworder;
425         void *ret1, *ret2;
426         int ret_len;
427         int len = flt_data->items_len = RNA_collection_length(dataptr, propname);
428
429         RNA_pointer_create(&CTX_wm_screen(C)->id, ui_list->type->ext.srna, ui_list, &ul_ptr);
430         func = &rna_UIList_filter_items_func; /* RNA_struct_find_function(&ul_ptr, "filter_items"); */
431
432         RNA_parameter_list_create(&list, &ul_ptr, func);
433         RNA_parameter_set_lookup(&list, "context", &C);
434         RNA_parameter_set_lookup(&list, "data", dataptr);
435         RNA_parameter_set_lookup(&list, "property", &propname);
436
437         ui_list->type->ext.call((bContext *)C, &ul_ptr, func, &list);
438
439         parm = RNA_function_find_parameter(NULL, func, "filter_flags");
440         ret_len = RNA_parameter_dynamic_length_get(&list, parm);
441         if (ret_len != len && ret_len != 0) {
442                 printf("%s: Error, py func returned %d items in %s, %d or none were expected.\n", __func__,
443                        RNA_parameter_dynamic_length_get(&list, parm), "filter_flags", len);
444                 /* Note: we cannot return here, we would let flt_data in inconsistent state... see T38356. */
445                 filter_flags = NULL;
446         }
447         else {
448                 RNA_parameter_get(&list, parm, &ret1);
449                 filter_flags = (int *)ret1;
450         }
451
452         parm = RNA_function_find_parameter(NULL, func, "filter_neworder");
453         ret_len = RNA_parameter_dynamic_length_get(&list, parm);
454         if (ret_len != len && ret_len != 0) {
455                 printf("%s: Error, py func returned %d items in %s, %d or none were expected.\n", __func__,
456                        RNA_parameter_dynamic_length_get(&list, parm), "filter_neworder", len);
457                 /* Note: we cannot return here, we would let flt_data in inconsistent state... see T38356. */
458                 filter_neworder = NULL;
459         }
460         else {
461                 RNA_parameter_get(&list, parm, &ret2);
462                 filter_neworder = (int *)ret2;
463         }
464
465         /* We have to do some final checks and transforms... */
466         {
467                 int i, filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE;
468                 if (filter_flags) {
469                         flt_data->items_filter_flags = MEM_mallocN(sizeof(int) * len, __func__);
470                         memcpy(flt_data->items_filter_flags, filter_flags, sizeof(int) * len);
471
472                         if (filter_neworder) {
473                                 /* For sake of simplicity, py filtering is expected to filter all items, but we actually only want
474                                  * reordering data for shown items!
475                                  */
476                                 int items_shown, shown_idx;
477                                 int t_idx, t_ni, prev_ni;
478                                 flt_data->items_shown = 0;
479                                 for (i = 0, shown_idx = 0; i < len; i++) {
480                                         if ((filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude) {
481                                                 filter_neworder[shown_idx++] = filter_neworder[i];
482                                         }
483                                 }
484                                 items_shown = flt_data->items_shown = shown_idx;
485                                 flt_data->items_filter_neworder = MEM_mallocN(sizeof(int) * items_shown, __func__);
486                                 /* And now, bring back new indices into the [0, items_shown[ range!
487                                  * XXX This is O(N²)... :/
488                                  */
489                                 for (shown_idx = 0, prev_ni = -1; shown_idx < items_shown; shown_idx++) {
490                                         for (i = 0, t_ni = len, t_idx = -1; i < items_shown; i++) {
491                                                 int ni = filter_neworder[i];
492                                                 if (ni > prev_ni && ni < t_ni) {
493                                                         t_idx = i;
494                                                         t_ni = ni;
495                                                 }
496                                         }
497                                         if (t_idx >= 0) {
498                                                 prev_ni = t_ni;
499                                                 flt_data->items_filter_neworder[t_idx] = shown_idx;
500                                         }
501                                 }
502                         }
503                         else {
504                                 /* we still have to set flt_data->items_shown... */
505                                 flt_data->items_shown = 0;
506                                 for (i = 0; i < len; i++) {
507                                         if ((filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude) {
508                                                 flt_data->items_shown++;
509                                         }
510                                 }
511                         }
512                 }
513                 else {
514                         flt_data->items_shown = len;
515
516                         if (filter_neworder) {
517                                 flt_data->items_filter_neworder = MEM_mallocN(sizeof(int) * len, __func__);
518                                 memcpy(flt_data->items_filter_neworder, filter_neworder, sizeof(int) * len);
519                         }
520                 }
521         }
522
523         RNA_parameter_list_free(&list);
524 }
525
526 static void rna_UIList_unregister(Main *UNUSED(bmain), StructRNA *type)
527 {
528         uiListType *ult = RNA_struct_blender_type_get(type);
529
530         if (!ult)
531                 return;
532
533         RNA_struct_free_extension(type, &ult->ext);
534         RNA_struct_free(&BLENDER_RNA, type);
535
536         WM_uilisttype_freelink(ult);
537
538         /* update while blender is running */
539         WM_main_add_notifier(NC_WINDOW, NULL);
540 }
541
542 static StructRNA *rna_UIList_register(
543         Main *bmain, ReportList *reports, void *data, const char *identifier,
544         StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
545 {
546         uiListType *ult, dummyult = {NULL};
547         uiList dummyuilist = {NULL};
548         PointerRNA dummyul_ptr;
549         int have_function[3];
550         size_t over_alloc = 0; /* warning, if this becomes a bess, we better do another alloc */
551
552         /* setup dummy menu & menu type to store static properties in */
553         dummyuilist.type = &dummyult;
554         RNA_pointer_create(NULL, &RNA_UIList, &dummyuilist, &dummyul_ptr);
555
556         /* validate the python class */
557         if (validate(&dummyul_ptr, data, have_function) != 0)
558                 return NULL;
559
560         if (strlen(identifier) >= sizeof(dummyult.idname)) {
561                 BKE_reportf(reports, RPT_ERROR, "Registering uilist class: '%s' is too long, maximum length is %d",
562                             identifier, (int)sizeof(dummyult.idname));
563                 return NULL;
564         }
565
566         /* check if we have registered this uilist type before, and remove it */
567         ult = WM_uilisttype_find(dummyult.idname, true);
568         if (ult && ult->ext.srna) {
569                 rna_UIList_unregister(bmain, ult->ext.srna);
570         }
571         if (!RNA_struct_available_or_report(reports, dummyult.idname)) {
572                 return NULL;
573         }
574         if (!RNA_struct_bl_idname_ok_or_report(reports, dummyult.idname, "_UL_")) {
575                 return NULL;
576         }
577
578         /* create a new menu type */
579         ult = MEM_callocN(sizeof(uiListType) + over_alloc, "python uilist");
580         memcpy(ult, &dummyult, sizeof(dummyult));
581
582         ult->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, ult->idname, &RNA_UIList);
583         ult->ext.data = data;
584         ult->ext.call = call;
585         ult->ext.free = free;
586         RNA_struct_blender_type_set(ult->ext.srna, ult);
587
588         ult->draw_item = (have_function[0]) ? uilist_draw_item : NULL;
589         ult->draw_filter = (have_function[1]) ? uilist_draw_filter : NULL;
590         ult->filter_items = (have_function[2]) ? uilist_filter_items : NULL;
591
592         WM_uilisttype_add(ult);
593
594         /* update while blender is running */
595         WM_main_add_notifier(NC_WINDOW, NULL);
596
597         return ult->ext.srna;
598 }
599
600 static StructRNA *rna_UIList_refine(PointerRNA *ptr)
601 {
602         uiList *ui_list = (uiList *)ptr->data;
603         return (ui_list->type && ui_list->type->ext.srna) ? ui_list->type->ext.srna : &RNA_UIList;
604 }
605
606 /* Header */
607
608 static void header_draw(const bContext *C, Header *hdr)
609 {
610         extern FunctionRNA rna_Header_draw_func;
611
612         PointerRNA htr;
613         ParameterList list;
614         FunctionRNA *func;
615
616         RNA_pointer_create(&CTX_wm_screen(C)->id, hdr->type->ext.srna, hdr, &htr);
617         func = &rna_Header_draw_func; /* RNA_struct_find_function(&htr, "draw"); */
618
619         RNA_parameter_list_create(&list, &htr, func);
620         RNA_parameter_set_lookup(&list, "context", &C);
621         hdr->type->ext.call((bContext *)C, &htr, func, &list);
622
623         RNA_parameter_list_free(&list);
624 }
625
626 static void rna_Header_unregister(Main *UNUSED(bmain), StructRNA *type)
627 {
628         ARegionType *art;
629         HeaderType *ht = RNA_struct_blender_type_get(type);
630
631         if (!ht)
632                 return;
633         if (!(art = region_type_find(NULL, ht->space_type, ht->region_type)))
634                 return;
635
636         RNA_struct_free_extension(type, &ht->ext);
637         RNA_struct_free(&BLENDER_RNA, type);
638
639         BLI_freelinkN(&art->headertypes, ht);
640
641         /* update while blender is running */
642         WM_main_add_notifier(NC_WINDOW, NULL);
643 }
644
645 static StructRNA *rna_Header_register(
646         Main *bmain, ReportList *reports, void *data, const char *identifier,
647         StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
648 {
649         ARegionType *art;
650         HeaderType *ht, dummyht = {NULL};
651         Header dummyheader = {NULL};
652         PointerRNA dummyhtr;
653         int have_function[1];
654
655         /* setup dummy header & header type to store static properties in */
656         dummyheader.type = &dummyht;
657         dummyht.region_type = RGN_TYPE_HEADER; /* RGN_TYPE_HEADER by default, may be overridden */
658         RNA_pointer_create(NULL, &RNA_Header, &dummyheader, &dummyhtr);
659
660         /* validate the python class */
661         if (validate(&dummyhtr, data, have_function) != 0)
662                 return NULL;
663
664         if (strlen(identifier) >= sizeof(dummyht.idname)) {
665                 BKE_reportf(reports, RPT_ERROR, "Registering header class: '%s' is too long, maximum length is %d",
666                             identifier, (int)sizeof(dummyht.idname));
667                 return NULL;
668         }
669
670         if (!(art = region_type_find(reports, dummyht.space_type, dummyht.region_type)))
671                 return NULL;
672
673         /* check if we have registered this header type before, and remove it */
674         for (ht = art->headertypes.first; ht; ht = ht->next) {
675                 if (STREQ(ht->idname, dummyht.idname)) {
676                         if (ht->ext.srna)
677                                 rna_Header_unregister(bmain, ht->ext.srna);
678                         break;
679                 }
680         }
681         if (!RNA_struct_available_or_report(reports, dummyht.idname)) {
682                 return NULL;
683         }
684         if (!RNA_struct_bl_idname_ok_or_report(reports, dummyht.idname, "_HT_")) {
685                 return NULL;
686         }
687
688         /* create a new header type */
689         ht = MEM_callocN(sizeof(HeaderType), "python buttons header");
690         memcpy(ht, &dummyht, sizeof(dummyht));
691
692         ht->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, ht->idname, &RNA_Header);
693         ht->ext.data = data;
694         ht->ext.call = call;
695         ht->ext.free = free;
696         RNA_struct_blender_type_set(ht->ext.srna, ht);
697
698         ht->draw = (have_function[0]) ? header_draw : NULL;
699
700         BLI_addtail(&art->headertypes, ht);
701
702         /* update while blender is running */
703         WM_main_add_notifier(NC_WINDOW, NULL);
704
705         return ht->ext.srna;
706 }
707
708 static StructRNA *rna_Header_refine(PointerRNA *htr)
709 {
710         Header *hdr = (Header *)htr->data;
711         return (hdr->type && hdr->type->ext.srna) ? hdr->type->ext.srna : &RNA_Header;
712 }
713
714 /* Menu */
715
716 static bool menu_poll(const bContext *C, MenuType *pt)
717 {
718         extern FunctionRNA rna_Menu_poll_func;
719
720         PointerRNA ptr;
721         ParameterList list;
722         FunctionRNA *func;
723         void *ret;
724         bool visible;
725
726         RNA_pointer_create(NULL, pt->ext.srna, NULL, &ptr); /* dummy */
727         func = &rna_Menu_poll_func; /* RNA_struct_find_function(&ptr, "poll"); */
728
729         RNA_parameter_list_create(&list, &ptr, func);
730         RNA_parameter_set_lookup(&list, "context", &C);
731         pt->ext.call((bContext *)C, &ptr, func, &list);
732
733         RNA_parameter_get_lookup(&list, "visible", &ret);
734         visible = *(bool *)ret;
735
736         RNA_parameter_list_free(&list);
737
738         return visible;
739 }
740
741 static void menu_draw(const bContext *C, Menu *menu)
742 {
743         extern FunctionRNA rna_Menu_draw_func;
744
745         PointerRNA mtr;
746         ParameterList list;
747         FunctionRNA *func;
748
749         RNA_pointer_create(&CTX_wm_screen(C)->id, menu->type->ext.srna, menu, &mtr);
750         func = &rna_Menu_draw_func; /* RNA_struct_find_function(&mtr, "draw"); */
751
752         RNA_parameter_list_create(&list, &mtr, func);
753         RNA_parameter_set_lookup(&list, "context", &C);
754         menu->type->ext.call((bContext *)C, &mtr, func, &list);
755
756         RNA_parameter_list_free(&list);
757 }
758
759 static void rna_Menu_unregister(Main *UNUSED(bmain), StructRNA *type)
760 {
761         MenuType *mt = RNA_struct_blender_type_get(type);
762
763         if (!mt)
764                 return;
765
766         RNA_struct_free_extension(type, &mt->ext);
767         RNA_struct_free(&BLENDER_RNA, type);
768
769         WM_menutype_freelink(mt);
770
771         /* update while blender is running */
772         WM_main_add_notifier(NC_WINDOW, NULL);
773 }
774
775 static StructRNA *rna_Menu_register(
776         Main *bmain, ReportList *reports, void *data, const char *identifier,
777         StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
778 {
779         MenuType *mt, dummymt = {NULL};
780         Menu dummymenu = {NULL};
781         PointerRNA dummymtr;
782         int have_function[2];
783         size_t over_alloc = 0; /* warning, if this becomes a bess, we better do another alloc */
784         size_t description_size = 0;
785         char _menu_descr[RNA_DYN_DESCR_MAX];
786
787         /* setup dummy menu & menu type to store static properties in */
788         dummymenu.type = &dummymt;
789         _menu_descr[0] = '\0';
790         dummymenu.type->description = _menu_descr;
791         RNA_pointer_create(NULL, &RNA_Menu, &dummymenu, &dummymtr);
792
793         /* We have to set default context! Else we get a void string... */
794         strcpy(dummymt.translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
795
796         /* validate the python class */
797         if (validate(&dummymtr, data, have_function) != 0)
798                 return NULL;
799
800         if (strlen(identifier) >= sizeof(dummymt.idname)) {
801                 BKE_reportf(reports, RPT_ERROR, "Registering menu class: '%s' is too long, maximum length is %d",
802                             identifier, (int)sizeof(dummymt.idname));
803                 return NULL;
804         }
805
806         /* check if we have registered this menu type before, and remove it */
807         mt = WM_menutype_find(dummymt.idname, true);
808         if (mt && mt->ext.srna) {
809                 rna_Menu_unregister(bmain, mt->ext.srna);
810         }
811         if (!RNA_struct_available_or_report(reports, dummymt.idname)) {
812                 return NULL;
813         }
814         if (!RNA_struct_bl_idname_ok_or_report(reports, dummymt.idname, "_MT_")) {
815                 return NULL;
816         }
817
818         /* create a new menu type */
819         if (_menu_descr[0]) {
820                 description_size = strlen(_menu_descr) + 1;
821                 over_alloc += description_size;
822         }
823
824         mt = MEM_callocN(sizeof(MenuType) + over_alloc, "python buttons menu");
825         memcpy(mt, &dummymt, sizeof(dummymt));
826
827         if (_menu_descr[0]) {
828                 char *buf = (char *)(mt + 1);
829                 memcpy(buf, _menu_descr, description_size);
830                 mt->description = buf;
831         }
832         else
833                 mt->description = "";
834
835         mt->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, mt->idname, &RNA_Menu);
836         RNA_def_struct_translation_context(mt->ext.srna, mt->translation_context);
837         mt->ext.data = data;
838         mt->ext.call = call;
839         mt->ext.free = free;
840         RNA_struct_blender_type_set(mt->ext.srna, mt);
841         RNA_def_struct_flag(mt->ext.srna, STRUCT_NO_IDPROPERTIES);
842
843         mt->poll = (have_function[0]) ? menu_poll : NULL;
844         mt->draw = (have_function[1]) ? menu_draw : NULL;
845
846         {
847                 const char *owner_id = RNA_struct_state_owner_get();
848                 if (owner_id) {
849                         BLI_strncpy(mt->owner_id, owner_id, sizeof(mt->owner_id));
850                 }
851         }
852
853         WM_menutype_add(mt);
854
855         /* update while blender is running */
856         WM_main_add_notifier(NC_WINDOW, NULL);
857
858         return mt->ext.srna;
859 }
860
861 static StructRNA *rna_Menu_refine(PointerRNA *mtr)
862 {
863         Menu *menu = (Menu *)mtr->data;
864         return (menu->type && menu->type->ext.srna) ? menu->type->ext.srna : &RNA_Menu;
865 }
866
867 static void rna_Menu_bl_description_set(PointerRNA *ptr, const char *value)
868 {
869         Menu *data = (Menu *)(ptr->data);
870         char *str = (char *)data->type->description;
871         if (!str[0]) BLI_strncpy(str, value, RNA_DYN_DESCR_MAX);     /* utf8 already ensured */
872         else assert(!"setting the bl_description on a non-builtin menu");
873 }
874
875 /* UILayout */
876
877 static bool rna_UILayout_active_get(PointerRNA *ptr)
878 {
879         return uiLayoutGetActive(ptr->data);
880 }
881
882 static void rna_UILayout_active_set(PointerRNA *ptr, bool value)
883 {
884         uiLayoutSetActive(ptr->data, value);
885 }
886
887 static bool rna_UILayout_alert_get(PointerRNA *ptr)
888 {
889         return uiLayoutGetRedAlert(ptr->data);
890 }
891
892 static void rna_UILayout_alert_set(PointerRNA *ptr, bool value)
893 {
894         uiLayoutSetRedAlert(ptr->data, value);
895 }
896
897 static void rna_UILayout_op_context_set(PointerRNA *ptr, int value)
898 {
899         uiLayoutSetOperatorContext(ptr->data, value);
900 }
901
902 static int rna_UILayout_op_context_get(PointerRNA *ptr)
903 {
904         return uiLayoutGetOperatorContext(ptr->data);
905 }
906
907 static bool rna_UILayout_enabled_get(PointerRNA *ptr)
908 {
909         return uiLayoutGetEnabled(ptr->data);
910 }
911
912 static void rna_UILayout_enabled_set(PointerRNA *ptr, bool value)
913 {
914         uiLayoutSetEnabled(ptr->data, value);
915 }
916
917 #if 0
918 static int rna_UILayout_red_alert_get(PointerRNA *ptr)
919 {
920         return uiLayoutGetRedAlert(ptr->data);
921 }
922
923 static void rna_UILayout_red_alert_set(PointerRNA *ptr, bool value)
924 {
925         uiLayoutSetRedAlert(ptr->data, value);
926 }
927
928 static bool rna_UILayout_keep_aspect_get(PointerRNA *ptr)
929 {
930         return uiLayoutGetKeepAspect(ptr->data);
931 }
932
933 static void rna_UILayout_keep_aspect_set(PointerRNA *ptr, int value)
934 {
935         uiLayoutSetKeepAspect(ptr->data, value);
936 }
937 #endif
938
939 static int rna_UILayout_alignment_get(PointerRNA *ptr)
940 {
941         return uiLayoutGetAlignment(ptr->data);
942 }
943
944 static void rna_UILayout_alignment_set(PointerRNA *ptr, int value)
945 {
946         uiLayoutSetAlignment(ptr->data, value);
947 }
948
949 static float rna_UILayout_scale_x_get(PointerRNA *ptr)
950 {
951         return uiLayoutGetScaleX(ptr->data);
952 }
953
954 static void rna_UILayout_scale_x_set(PointerRNA *ptr, float value)
955 {
956         uiLayoutSetScaleX(ptr->data, value);
957 }
958
959 static float rna_UILayout_scale_y_get(PointerRNA *ptr)
960 {
961         return uiLayoutGetScaleY(ptr->data);
962 }
963
964 static void rna_UILayout_scale_y_set(PointerRNA *ptr, float value)
965 {
966         uiLayoutSetScaleY(ptr->data, value);
967 }
968
969 static float rna_UILayout_units_x_get(PointerRNA *ptr)
970 {
971         return uiLayoutGetUnitsX(ptr->data);
972 }
973
974 static void rna_UILayout_units_x_set(PointerRNA *ptr, float value)
975 {
976         uiLayoutSetUnitsX(ptr->data, value);
977 }
978
979 static float rna_UILayout_units_y_get(PointerRNA *ptr)
980 {
981         return uiLayoutGetUnitsY(ptr->data);
982 }
983
984 static void rna_UILayout_units_y_set(PointerRNA *ptr, float value)
985 {
986         uiLayoutSetUnitsY(ptr->data, value);
987 }
988
989 static int rna_UILayout_emboss_get(PointerRNA *ptr)
990 {
991         return uiLayoutGetEmboss(ptr->data);
992 }
993
994 static void rna_UILayout_emboss_set(PointerRNA *ptr, int value)
995 {
996         uiLayoutSetEmboss(ptr->data, value);
997 }
998
999 static bool rna_UILayout_property_split_get(PointerRNA *ptr)
1000 {
1001         return uiLayoutGetPropSep(ptr->data);
1002 }
1003
1004 static void rna_UILayout_property_split_set(PointerRNA *ptr, bool value)
1005 {
1006         uiLayoutSetPropSep(ptr->data, value);
1007 }
1008
1009 static bool rna_UILayout_property_decorate_get(PointerRNA *ptr)
1010 {
1011         return uiLayoutGetPropDecorate(ptr->data);
1012 }
1013
1014 static void rna_UILayout_property_decorate_set(PointerRNA *ptr, bool value)
1015 {
1016         uiLayoutSetPropDecorate(ptr->data, value);
1017 }
1018
1019 #else /* RNA_RUNTIME */
1020
1021 static void rna_def_ui_layout(BlenderRNA *brna)
1022 {
1023         StructRNA *srna;
1024         PropertyRNA *prop;
1025
1026         static const EnumPropertyItem alignment_items[] = {
1027                 {UI_LAYOUT_ALIGN_EXPAND, "EXPAND", 0, "Expand", ""},
1028                 {UI_LAYOUT_ALIGN_LEFT, "LEFT", 0, "Left", ""},
1029                 {UI_LAYOUT_ALIGN_CENTER, "CENTER", 0, "Center", ""},
1030                 {UI_LAYOUT_ALIGN_RIGHT, "RIGHT", 0, "Right", ""},
1031                 {0, NULL, 0, NULL, NULL}
1032         };
1033
1034         static const EnumPropertyItem emboss_items[] = {
1035                 {UI_EMBOSS, "NORMAL", 0, "Normal", "Draw standard button emboss style"},
1036                 {UI_EMBOSS_NONE, "NONE", 0, "None", "Draw only text and icons"},
1037                 {UI_EMBOSS_PULLDOWN, "PULLDOWN_MENU", 0, "Pulldown Menu", "Draw pulldown menu style"},
1038                 {UI_EMBOSS_RADIAL, "RADIAL_MENU", 0, "Radial Menu", "Draw radial menu style"},
1039                 {0, NULL, 0, NULL, NULL}
1040         };
1041
1042         /* layout */
1043
1044         srna = RNA_def_struct(brna, "UILayout", NULL);
1045         RNA_def_struct_sdna(srna, "uiLayout");
1046         RNA_def_struct_ui_text(srna, "UI Layout", "User interface layout in a panel or header");
1047
1048         prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
1049         RNA_def_property_boolean_funcs(prop, "rna_UILayout_active_get", "rna_UILayout_active_set");
1050
1051         prop = RNA_def_property(srna, "operator_context", PROP_ENUM, PROP_NONE);
1052         RNA_def_property_enum_items(prop, rna_enum_operator_context_items);
1053         RNA_def_property_enum_funcs(prop, "rna_UILayout_op_context_get", "rna_UILayout_op_context_set", NULL);
1054
1055         prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
1056         RNA_def_property_boolean_funcs(prop, "rna_UILayout_enabled_get", "rna_UILayout_enabled_set");
1057         RNA_def_property_ui_text(prop, "Enabled", "When false, this (sub)layout is grayed out");
1058
1059         prop = RNA_def_property(srna, "alert", PROP_BOOLEAN, PROP_NONE);
1060         RNA_def_property_boolean_funcs(prop, "rna_UILayout_alert_get", "rna_UILayout_alert_set");
1061
1062         prop = RNA_def_property(srna, "alignment", PROP_ENUM, PROP_NONE);
1063         RNA_def_property_enum_items(prop, alignment_items);
1064         RNA_def_property_enum_funcs(prop, "rna_UILayout_alignment_get", "rna_UILayout_alignment_set", NULL);
1065
1066 #if 0
1067         prop = RNA_def_property(srna, "keep_aspect", PROP_BOOLEAN, PROP_NONE);
1068         RNA_def_property_boolean_funcs(prop, "rna_UILayout_keep_aspect_get", "rna_UILayout_keep_aspect_set");
1069 #endif
1070
1071         prop = RNA_def_property(srna, "scale_x", PROP_FLOAT, PROP_UNSIGNED);
1072         RNA_def_property_float_funcs(prop, "rna_UILayout_scale_x_get", "rna_UILayout_scale_x_set", NULL);
1073         RNA_def_property_ui_text(prop, "Scale X", "Scale factor along the X for items in this (sub)layout");
1074
1075         prop = RNA_def_property(srna, "scale_y", PROP_FLOAT, PROP_UNSIGNED);
1076         RNA_def_property_float_funcs(prop, "rna_UILayout_scale_y_get", "rna_UILayout_scale_y_set", NULL);
1077         RNA_def_property_ui_text(prop, "Scale Y", "Scale factor along the Y for items in this (sub)layout");
1078
1079         prop = RNA_def_property(srna, "ui_units_x", PROP_FLOAT, PROP_UNSIGNED);
1080         RNA_def_property_float_funcs(prop, "rna_UILayout_units_x_get", "rna_UILayout_units_x_set", NULL);
1081         RNA_def_property_ui_text(prop, "Units X", "Fixed Size along the X for items in this (sub)layout");
1082
1083         prop = RNA_def_property(srna, "ui_units_y", PROP_FLOAT, PROP_UNSIGNED);
1084         RNA_def_property_float_funcs(prop, "rna_UILayout_units_y_get", "rna_UILayout_units_y_set", NULL);
1085         RNA_def_property_ui_text(prop, "Units Y", "Fixed Size along the Y for items in this (sub)layout");
1086         RNA_api_ui_layout(srna);
1087
1088         prop = RNA_def_property(srna, "emboss", PROP_ENUM, PROP_NONE);
1089         RNA_def_property_enum_items(prop, emboss_items);
1090         RNA_def_property_enum_funcs(prop, "rna_UILayout_emboss_get", "rna_UILayout_emboss_set", NULL);
1091
1092         prop = RNA_def_property(srna, "use_property_split", PROP_BOOLEAN, PROP_NONE);
1093         RNA_def_property_boolean_funcs(prop, "rna_UILayout_property_split_get", "rna_UILayout_property_split_set");
1094
1095         prop = RNA_def_property(srna, "use_property_decorate", PROP_BOOLEAN, PROP_NONE);
1096         RNA_def_property_boolean_funcs(prop, "rna_UILayout_property_decorate_get", "rna_UILayout_property_decorate_set");
1097 }
1098
1099 static void rna_def_panel(BlenderRNA *brna)
1100 {
1101         StructRNA *srna;
1102         PropertyRNA *prop;
1103         PropertyRNA *parm;
1104         FunctionRNA *func;
1105
1106         static const EnumPropertyItem panel_flag_items[] = {
1107                 {PNL_DEFAULT_CLOSED, "DEFAULT_CLOSED", 0, "Default Closed",
1108                                      "Defines if the panel has to be open or collapsed at the time of its creation"},
1109                 {PNL_NO_HEADER, "HIDE_HEADER", 0, "Hide Header",
1110                                 "If set to False, the panel shows a header, which contains a clickable "
1111                                 "arrow to collapse the panel and the label (see bl_label)"},
1112                 {0, NULL, 0, NULL, NULL}
1113         };
1114
1115         srna = RNA_def_struct(brna, "Panel", NULL);
1116         RNA_def_struct_ui_text(srna, "Panel", "Panel containing UI elements");
1117         RNA_def_struct_sdna(srna, "Panel");
1118         RNA_def_struct_refine_func(srna, "rna_Panel_refine");
1119         RNA_def_struct_register_funcs(srna, "rna_Panel_register", "rna_Panel_unregister", NULL);
1120         RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
1121         RNA_def_struct_flag(srna, STRUCT_PUBLIC_NAMESPACE_INHERIT);
1122
1123         /* poll */
1124         func = RNA_def_function(srna, "poll", NULL);
1125         RNA_def_function_ui_description(func, "If this method returns a non-null output, then the panel can be drawn");
1126         RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
1127         RNA_def_function_return(func, RNA_def_boolean(func, "visible", 1, "", ""));
1128         parm = RNA_def_pointer(func, "context", "Context", "", "");
1129         RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
1130
1131         /* draw */
1132         func = RNA_def_function(srna, "draw", NULL);
1133         RNA_def_function_ui_description(func, "Draw UI elements into the panel UI layout");
1134         RNA_def_function_flag(func, FUNC_REGISTER);
1135         parm = RNA_def_pointer(func, "context", "Context", "", "");
1136         RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
1137
1138         func = RNA_def_function(srna, "draw_header", NULL);
1139         RNA_def_function_ui_description(func, "Draw UI elements into the panel's header UI layout");
1140         RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
1141         parm = RNA_def_pointer(func, "context", "Context", "", "");
1142         RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
1143
1144         func = RNA_def_function(srna, "draw_header_preset", NULL);
1145         RNA_def_function_ui_description(func, "Draw UI elements for presets in the panel's header");
1146         RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
1147         parm = RNA_def_pointer(func, "context", "Context", "", "");
1148         RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
1149
1150         prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
1151         RNA_def_property_struct_type(prop, "UILayout");
1152         RNA_def_property_ui_text(prop, "Layout", "Defines the structure of the panel in the UI");
1153
1154         prop = RNA_def_property(srna, "text", PROP_STRING, PROP_NONE);
1155         RNA_def_property_string_sdna(prop, NULL, "drawname");
1156         RNA_def_property_ui_text(prop, "Text", "XXX todo");
1157
1158         /* registration */
1159         prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
1160         RNA_def_property_string_sdna(prop, NULL, "type->idname");
1161         RNA_def_property_flag(prop, PROP_REGISTER);
1162         RNA_def_property_ui_text(prop, "ID Name",
1163                                  "If this is set, the panel gets a custom ID, otherwise it takes the "
1164                                  "name of the class used to define the panel. For example, if the "
1165                                  "class name is \"OBJECT_PT_hello\", and bl_idname is not set by the "
1166                                  "script, then bl_idname = \"OBJECT_PT_hello\"");
1167
1168         prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
1169         RNA_def_property_string_sdna(prop, NULL, "type->label");
1170         RNA_def_property_flag(prop, PROP_REGISTER);
1171         RNA_def_property_ui_text(prop, "Label",
1172                                  "The panel label, shows up in the panel header at the right of the "
1173                                  "triangle used to collapse the panel");
1174
1175         prop = RNA_def_property(srna, "bl_translation_context", PROP_STRING, PROP_NONE);
1176         RNA_def_property_string_sdna(prop, NULL, "type->translation_context");
1177         RNA_def_property_string_default(prop, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
1178         RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1179         RNA_define_verify_sdna(true);
1180
1181         prop = RNA_def_property(srna, "bl_category", PROP_STRING, PROP_NONE);
1182         RNA_def_property_string_sdna(prop, NULL, "type->category");
1183         RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1184
1185         prop = RNA_def_property(srna, "bl_owner_id", PROP_STRING, PROP_NONE);
1186         RNA_def_property_string_sdna(prop, NULL, "type->owner_id");
1187         RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1188
1189         prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE);
1190         RNA_def_property_enum_sdna(prop, NULL, "type->space_type");
1191         RNA_def_property_enum_items(prop, rna_enum_space_type_items);
1192         RNA_def_property_flag(prop, PROP_REGISTER);
1193         RNA_def_property_ui_text(prop, "Space type", "The space where the panel is going to be used in");
1194
1195         prop = RNA_def_property(srna, "bl_region_type", PROP_ENUM, PROP_NONE);
1196         RNA_def_property_enum_sdna(prop, NULL, "type->region_type");
1197         RNA_def_property_enum_items(prop, rna_enum_region_type_items);
1198         RNA_def_property_flag(prop, PROP_REGISTER);
1199         RNA_def_property_ui_text(prop, "Region Type", "The region where the panel is going to be used in");
1200
1201         prop = RNA_def_property(srna, "bl_context", PROP_STRING, PROP_NONE);
1202         RNA_def_property_string_sdna(prop, NULL, "type->context");
1203         RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); /* Only used in Properties Editor and 3D View - Thomas */
1204         RNA_def_property_ui_text(prop, "Context",
1205                                  "The context in which the panel belongs to. (TODO: explain the "
1206                                  "possible combinations bl_context/bl_region_type/bl_space_type)");
1207
1208         prop = RNA_def_property(srna, "bl_options", PROP_ENUM, PROP_NONE);
1209         RNA_def_property_enum_sdna(prop, NULL, "type->flag");
1210         RNA_def_property_enum_items(prop, panel_flag_items);
1211         RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL | PROP_ENUM_FLAG);
1212         RNA_def_property_ui_text(prop, "Options",  "Options for this panel type");
1213
1214         prop = RNA_def_property(srna, "bl_parent_id", PROP_STRING, PROP_NONE);
1215         RNA_def_property_string_sdna(prop, NULL, "type->parent_id");
1216         RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1217         RNA_def_property_ui_text(prop, "Parent ID Name", "If this is set, the panel becomes a subpanel");
1218
1219         prop = RNA_def_property(srna, "bl_ui_units_x", PROP_INT, PROP_UNSIGNED);
1220         RNA_def_property_int_sdna(prop, NULL, "type->ui_units_x");
1221         RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1222         RNA_def_property_ui_text(prop, "Units X", "When set, defines popup panel width");
1223
1224         prop = RNA_def_property(srna, "use_pin", PROP_BOOLEAN, PROP_NONE);
1225         RNA_def_property_boolean_sdna(prop, NULL, "flag", PNL_PIN);
1226         RNA_def_property_ui_text(prop, "Pin",  "");
1227         /* XXX, should only tag region for redraw */
1228         RNA_def_property_update(prop, NC_WINDOW, NULL);
1229
1230         prop = RNA_def_property(srna, "is_popover", PROP_BOOLEAN, PROP_NONE);
1231         RNA_def_property_boolean_sdna(prop, NULL, "flag", PNL_POPOVER);
1232         RNA_def_property_clear_flag(prop, PROP_EDITABLE);
1233         RNA_def_property_ui_text(prop, "Popover",  "");
1234 }
1235
1236 static void rna_def_uilist(BlenderRNA *brna)
1237 {
1238         StructRNA *srna;
1239         PropertyRNA *prop;
1240         PropertyRNA *parm;
1241         FunctionRNA *func;
1242
1243         srna = RNA_def_struct(brna, "UIList", NULL);
1244         RNA_def_struct_ui_text(srna, "UIList", "UI list containing the elements of a collection");
1245         RNA_def_struct_sdna(srna, "uiList");
1246         RNA_def_struct_refine_func(srna, "rna_UIList_refine");
1247         RNA_def_struct_register_funcs(srna, "rna_UIList_register", "rna_UIList_unregister", NULL);
1248         RNA_def_struct_idprops_func(srna, "rna_UIList_idprops");
1249         RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES | STRUCT_PUBLIC_NAMESPACE_INHERIT);
1250
1251         /* Registration */
1252         prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
1253         RNA_def_property_string_sdna(prop, NULL, "type->idname");
1254         RNA_def_property_flag(prop, PROP_REGISTER);
1255         RNA_def_property_ui_text(prop, "ID Name",
1256                                  "If this is set, the uilist gets a custom ID, otherwise it takes the "
1257                                  "name of the class used to define the uilist (for example, if the "
1258                                  "class name is \"OBJECT_UL_vgroups\", and bl_idname is not set by the "
1259                                  "script, then bl_idname = \"OBJECT_UL_vgroups\")");
1260
1261         /* Data */
1262         prop = RNA_def_property(srna, "layout_type", PROP_ENUM, PROP_NONE);
1263         RNA_def_property_enum_items(prop, rna_enum_uilist_layout_type_items);
1264         RNA_def_property_clear_flag(prop, PROP_EDITABLE);
1265
1266         /* Filter options */
1267         prop = RNA_def_property(srna, "use_filter_show", PROP_BOOLEAN, PROP_NONE);
1268         RNA_def_property_boolean_sdna(prop, NULL, "filter_flag", UILST_FLT_SHOW);
1269         RNA_def_property_ui_text(prop, "Show Filter", "Show filtering options");
1270
1271         prop = RNA_def_property(srna, "filter_name", PROP_STRING, PROP_NONE);
1272         RNA_def_property_string_sdna(prop, NULL, "filter_byname");
1273         RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE);
1274         RNA_def_property_ui_text(prop, "Filter by Name", "Only show items matching this name (use '*' as wildcard)");
1275
1276         prop = RNA_def_property(srna, "use_filter_invert", PROP_BOOLEAN, PROP_NONE);
1277         RNA_def_property_boolean_sdna(prop, NULL, "filter_flag", UILST_FLT_EXCLUDE);
1278         RNA_def_property_ui_text(prop, "Invert", "Invert filtering (show hidden items, and vice-versa)");
1279
1280         prop = RNA_def_property(srna, "use_filter_sort_alpha", PROP_BOOLEAN, PROP_NONE);
1281         RNA_def_property_boolean_sdna(prop, NULL, "filter_sort_flag", UILST_FLT_SORT_ALPHA);
1282         RNA_def_property_ui_icon(prop, ICON_SORTALPHA, 0);
1283         RNA_def_property_ui_text(prop, "Sort by Name", "Sort items by their name");
1284
1285         prop = RNA_def_property(srna, "use_filter_sort_reverse", PROP_BOOLEAN, PROP_NONE);
1286         RNA_def_property_boolean_sdna(prop, NULL, "filter_sort_flag", UILST_FLT_SORT_REVERSE);
1287         RNA_def_property_ui_text(prop, "Invert", "Invert the order of shown items");
1288
1289         /* draw_item */
1290         func = RNA_def_function(srna, "draw_item", NULL);
1291         RNA_def_function_ui_description(func, "Draw an item in the list (NOTE: when you define your own draw_item "
1292                                               "function, you may want to check given 'item' is of the right type...)");
1293         RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
1294         parm = RNA_def_pointer(func, "context", "Context", "", "");
1295         RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
1296         parm = RNA_def_pointer(func, "layout", "UILayout", "", "Layout to draw the item");
1297         RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
1298         parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take Collection property");
1299         RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_RNAPTR);
1300         parm = RNA_def_pointer(func, "item", "AnyType", "", "Item of the collection property");
1301         RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_RNAPTR);
1302         parm = RNA_def_int(func, "icon", 0, 0, INT_MAX, "", "Icon of the item in the collection", 0, INT_MAX);
1303         RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
1304         parm = RNA_def_pointer(func, "active_data", "AnyType", "",
1305                                "Data from which to take property for the active element");
1306         RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
1307         parm = RNA_def_string(func, "active_property", NULL, 0, "",
1308                               "Identifier of property in active_data, for the active element");
1309         RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
1310         RNA_def_int(func, "index", 0, 0, INT_MAX, "", "Index of the item in the collection", 0, INT_MAX);
1311         RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_PYFUNC_OPTIONAL);
1312         prop = RNA_def_property(func, "flt_flag", PROP_INT, PROP_UNSIGNED);
1313         RNA_def_property_ui_text(prop, "", "The filter-flag result for this item");
1314         RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_PYFUNC_OPTIONAL);
1315
1316         /* draw_filter */
1317         func = RNA_def_function(srna, "draw_filter", NULL);
1318         RNA_def_function_ui_description(func, "Draw filtering options");
1319         RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
1320         parm = RNA_def_pointer(func, "context", "Context", "", "");
1321         RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
1322         parm = RNA_def_pointer(func, "layout", "UILayout", "", "Layout to draw the item");
1323         RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
1324         RNA_def_boolean(func, "reverse", false, "", "Display items in reverse order");
1325
1326         /* filter */
1327         func = RNA_def_function(srna, "filter_items", NULL);
1328         RNA_def_function_ui_description(func, "Filter and/or re-order items of the collection (output filter results in "
1329                                               "filter_flags, and reorder results in filter_neworder arrays)");
1330         RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
1331         parm = RNA_def_pointer(func, "context", "Context", "", "");
1332         RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
1333         parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take Collection property");
1334         RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_RNAPTR);
1335         parm = RNA_def_string(func, "property", NULL, 0, "", "Identifier of property in data, for the collection");
1336         RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
1337         prop = RNA_def_property(func, "filter_flags", PROP_INT, PROP_UNSIGNED);
1338         RNA_def_property_flag(prop, PARM_REQUIRED | PROP_DYNAMIC);
1339         RNA_def_property_array(prop, 1);  /* XXX Dummy value, default 0 does not work */
1340         RNA_def_property_ui_text(prop, "", "An array of filter flags, one for each item in the collection (NOTE: "
1341                                            "FILTER_ITEM bit is reserved, it defines whether the item is shown or not)");
1342         RNA_def_function_output(func, prop);
1343         prop = RNA_def_property(func, "filter_neworder", PROP_INT, PROP_UNSIGNED);
1344         RNA_def_property_flag(prop, PARM_REQUIRED | PROP_DYNAMIC);
1345         RNA_def_property_array(prop, 1);  /* XXX Dummy value, default 0 does not work */
1346         RNA_def_property_ui_text(prop, "", "An array of indices, one for each item in the collection, mapping the org "
1347                                            "index to the new one");
1348         RNA_def_function_output(func, prop);
1349
1350         /* "Constants"! */
1351         RNA_define_verify_sdna(0); /* not in sdna */
1352
1353         prop = RNA_def_property(srna, "bitflag_filter_item", PROP_INT, PROP_UNSIGNED);
1354         RNA_def_property_ui_text(prop, "FILTER_ITEM",
1355                                        "The value of the reserved bitflag 'FILTER_ITEM' (in filter_flags values)");
1356         RNA_def_property_int_funcs(prop, "rna_UIList_filter_const_FILTER_ITEM_get", NULL, NULL);
1357         RNA_def_property_clear_flag(prop, PROP_EDITABLE);
1358 }
1359
1360 static void rna_def_header(BlenderRNA *brna)
1361 {
1362         StructRNA *srna;
1363         PropertyRNA *prop;
1364         PropertyRNA *parm;
1365         FunctionRNA *func;
1366
1367         srna = RNA_def_struct(brna, "Header", NULL);
1368         RNA_def_struct_ui_text(srna, "Header", "Editor header containing UI elements");
1369         RNA_def_struct_sdna(srna, "Header");
1370         RNA_def_struct_refine_func(srna, "rna_Header_refine");
1371         RNA_def_struct_register_funcs(srna, "rna_Header_register", "rna_Header_unregister", NULL);
1372         RNA_def_struct_flag(srna, STRUCT_PUBLIC_NAMESPACE_INHERIT);
1373
1374         /* draw */
1375         func = RNA_def_function(srna, "draw", NULL);
1376         RNA_def_function_ui_description(func, "Draw UI elements into the header UI layout");
1377         RNA_def_function_flag(func, FUNC_REGISTER);
1378         parm = RNA_def_pointer(func, "context", "Context", "", "");
1379         RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
1380
1381         RNA_define_verify_sdna(0); /* not in sdna */
1382
1383         prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
1384         RNA_def_property_pointer_sdna(prop, NULL, "layout");
1385         RNA_def_property_struct_type(prop, "UILayout");
1386         RNA_def_property_ui_text(prop, "Layout", "Structure of the header in the UI");
1387
1388         /* registration */
1389         prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
1390         RNA_def_property_string_sdna(prop, NULL, "type->idname");
1391         RNA_def_property_flag(prop, PROP_REGISTER);
1392         RNA_def_property_ui_text(prop, "ID Name",
1393                                  "If this is set, the header gets a custom ID, otherwise it takes the "
1394                                  "name of the class used to define the panel; for example, if the "
1395                                  "class name is \"OBJECT_HT_hello\", and bl_idname is not set by the "
1396                                  "script, then bl_idname = \"OBJECT_HT_hello\"");
1397
1398         prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE);
1399         RNA_def_property_enum_sdna(prop, NULL, "type->space_type");
1400         RNA_def_property_enum_items(prop, rna_enum_space_type_items);
1401         RNA_def_property_flag(prop, PROP_REGISTER);
1402         RNA_def_property_ui_text(prop, "Space type", "The space where the header is going to be used in");
1403
1404         prop = RNA_def_property(srna, "bl_region_type", PROP_ENUM, PROP_NONE);
1405         RNA_def_property_enum_sdna(prop, NULL, "type->region_type");
1406         RNA_def_property_enum_default(prop, RGN_TYPE_HEADER);
1407         RNA_def_property_enum_items(prop, rna_enum_region_type_items);
1408         RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1409         RNA_def_property_ui_text(prop, "Region Type", "The region where the header is going to be used in "
1410                                  "(defaults to header region)");
1411
1412         RNA_define_verify_sdna(1);
1413 }
1414
1415 static void rna_def_menu(BlenderRNA *brna)
1416 {
1417         StructRNA *srna;
1418         PropertyRNA *prop;
1419         PropertyRNA *parm;
1420         FunctionRNA *func;
1421
1422         srna = RNA_def_struct(brna, "Menu", NULL);
1423         RNA_def_struct_ui_text(srna, "Menu", "Editor menu containing buttons");
1424         RNA_def_struct_sdna(srna, "Menu");
1425         RNA_def_struct_refine_func(srna, "rna_Menu_refine");
1426         RNA_def_struct_register_funcs(srna, "rna_Menu_register", "rna_Menu_unregister", NULL);
1427         RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
1428         RNA_def_struct_flag(srna, STRUCT_PUBLIC_NAMESPACE_INHERIT);
1429
1430         /* poll */
1431         func = RNA_def_function(srna, "poll", NULL);
1432         RNA_def_function_ui_description(func, "If this method returns a non-null output, then the menu can be drawn");
1433         RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
1434         RNA_def_function_return(func, RNA_def_boolean(func, "visible", 1, "", ""));
1435         parm = RNA_def_pointer(func, "context", "Context", "", "");
1436         RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
1437
1438         /* draw */
1439         func = RNA_def_function(srna, "draw", NULL);
1440         RNA_def_function_ui_description(func, "Draw UI elements into the menu UI layout");
1441         RNA_def_function_flag(func, FUNC_REGISTER);
1442         parm = RNA_def_pointer(func, "context", "Context", "", "");
1443         RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
1444
1445         RNA_define_verify_sdna(false); /* not in sdna */
1446
1447         prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
1448         RNA_def_property_pointer_sdna(prop, NULL, "layout");
1449         RNA_def_property_struct_type(prop, "UILayout");
1450         RNA_def_property_ui_text(prop, "Layout", "Defines the structure of the menu in the UI");
1451
1452         /* registration */
1453         prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
1454         RNA_def_property_string_sdna(prop, NULL, "type->idname");
1455         RNA_def_property_flag(prop, PROP_REGISTER);
1456         RNA_def_property_ui_text(prop, "ID Name",
1457                                  "If this is set, the menu gets a custom ID, otherwise it takes the "
1458                                  "name of the class used to define the menu (for example, if the "
1459                                  "class name is \"OBJECT_MT_hello\", and bl_idname is not set by the "
1460                                  "script, then bl_idname = \"OBJECT_MT_hello\")");
1461
1462         prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
1463         RNA_def_property_string_sdna(prop, NULL, "type->label");
1464         RNA_def_property_flag(prop, PROP_REGISTER);
1465         RNA_def_property_ui_text(prop, "Label", "The menu label");
1466
1467         prop = RNA_def_property(srna, "bl_translation_context", PROP_STRING, PROP_NONE);
1468         RNA_def_property_string_sdna(prop, NULL, "type->translation_context");
1469         RNA_def_property_string_default(prop, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
1470         RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1471
1472         prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_NONE);
1473         RNA_def_property_string_sdna(prop, NULL, "type->description");
1474         RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */
1475         RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Menu_bl_description_set");
1476         /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
1477         RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1478         RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */
1479
1480         prop = RNA_def_property(srna, "bl_owner_id", PROP_STRING, PROP_NONE);
1481         RNA_def_property_string_sdna(prop, NULL, "type->owner_id");
1482         RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1483
1484         RNA_define_verify_sdna(1);
1485 }
1486
1487 void RNA_def_ui(BlenderRNA *brna)
1488 {
1489         rna_def_ui_layout(brna);
1490         rna_def_panel(brna);
1491         rna_def_uilist(brna);
1492         rna_def_header(brna);
1493         rna_def_menu(brna);
1494 }
1495
1496 #endif /* RNA_RUNTIME */