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