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