Fix for errors caused by fixing RNA function register flags. Default UIList class...
[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 "RNA_define.h"
33
34 #include "rna_internal.h"
35 #include "RNA_enum_types.h"
36
37 #include "UI_interface.h"
38
39 #include "WM_types.h"
40
41 /* see WM_types.h */
42 EnumPropertyItem operator_context_items[] = {
43         {WM_OP_INVOKE_DEFAULT, "INVOKE_DEFAULT", 0, "Invoke Default", ""},
44         {WM_OP_INVOKE_REGION_WIN, "INVOKE_REGION_WIN", 0, "Invoke Region Window", ""},
45         {WM_OP_INVOKE_REGION_CHANNELS, "INVOKE_REGION_CHANNELS", 0, "Invoke Region Channels", ""},
46         {WM_OP_INVOKE_REGION_PREVIEW, "INVOKE_REGION_PREVIEW", 0, "Invoke Region Preview", ""},
47         {WM_OP_INVOKE_AREA, "INVOKE_AREA", 0, "Invoke Area", ""},
48         {WM_OP_INVOKE_SCREEN, "INVOKE_SCREEN", 0, "Invoke Screen", ""},
49         {WM_OP_EXEC_DEFAULT, "EXEC_DEFAULT", 0, "Exec Default", ""},
50         {WM_OP_EXEC_REGION_WIN, "EXEC_REGION_WIN", 0, "Exec Region Window", ""},
51         {WM_OP_EXEC_REGION_CHANNELS, "EXEC_REGION_CHANNELS", 0, "Exec Region Channels", ""},
52         {WM_OP_EXEC_REGION_PREVIEW, "EXEC_REGION_PREVIEW", 0, "Exec Region Preview", ""},
53         {WM_OP_EXEC_AREA, "EXEC_AREA", 0, "Exec Area", ""},
54         {WM_OP_EXEC_SCREEN, "EXEC_SCREEN", 0, "Exec Screen", ""},
55         {0, NULL, 0, NULL, NULL}
56 };
57
58 EnumPropertyItem uilist_layout_type_items[] = {
59         {UILST_LAYOUT_DEFAULT, "DEFAULT", 0, "Default Layout",
60                                "Use the default, multi-rows layout"},
61         {UILST_LAYOUT_COMPACT, "COMPACT", 0, "Compact Layout",
62                                "Use the compact, single-row layout"},
63         {UILST_LAYOUT_GRID, "GRID", 0, "Grid Layout",
64                             "Use the grid-based layout"},
65         {0, NULL, 0, NULL, NULL}
66 };
67
68 #ifdef RNA_RUNTIME
69
70 #include <assert.h>
71
72 #include "MEM_guardedalloc.h"
73
74 #include "RNA_access.h"
75
76 #include "BLI_dynstr.h"
77
78 #include "BKE_context.h"
79 #include "BKE_report.h"
80 #include "BKE_screen.h"
81
82 #include "WM_api.h"
83
84 static ARegionType *region_type_find(ReportList *reports, int space_type, int region_type)
85 {
86         SpaceType *st;
87         ARegionType *art;
88
89         st = BKE_spacetype_from_id(space_type);
90
91         for (art = (st) ? st->regiontypes.first : NULL; art; art = art->next) {
92                 if (art->regionid == region_type)
93                         break;
94         }
95         
96         /* region type not found? abort */
97         if (art == NULL) {
98                 BKE_report(reports, RPT_ERROR, "Region not found in space type");
99                 return NULL;
100         }
101
102         return art;
103 }
104
105 /* Panel */
106
107 static int panel_poll(const bContext *C, PanelType *pt)
108 {
109         extern FunctionRNA rna_Panel_poll_func;
110
111         PointerRNA ptr;
112         ParameterList list;
113         FunctionRNA *func;
114         void *ret;
115         int visible;
116
117         RNA_pointer_create(NULL, pt->ext.srna, NULL, &ptr); /* dummy */
118         func = &rna_Panel_poll_func; /* RNA_struct_find_function(&ptr, "poll"); */
119
120         RNA_parameter_list_create(&list, &ptr, func);
121         RNA_parameter_set_lookup(&list, "context", &C);
122         pt->ext.call((bContext *)C, &ptr, func, &list);
123
124         RNA_parameter_get_lookup(&list, "visible", &ret);
125         visible = *(int *)ret;
126
127         RNA_parameter_list_free(&list);
128
129         return visible;
130 }
131
132 static void panel_draw(const bContext *C, Panel *pnl)
133 {
134         extern FunctionRNA rna_Panel_draw_func;
135
136         PointerRNA ptr;
137         ParameterList list;
138         FunctionRNA *func;
139
140         RNA_pointer_create(&CTX_wm_screen(C)->id, pnl->type->ext.srna, pnl, &ptr);
141         func = &rna_Panel_draw_func; /* RNA_struct_find_function(&ptr, "draw"); */
142
143         RNA_parameter_list_create(&list, &ptr, func);
144         RNA_parameter_set_lookup(&list, "context", &C);
145         pnl->type->ext.call((bContext *)C, &ptr, func, &list);
146
147         RNA_parameter_list_free(&list);
148 }
149
150 static void panel_draw_header(const bContext *C, Panel *pnl)
151 {
152         extern FunctionRNA rna_Panel_draw_header_func;
153
154         PointerRNA ptr;
155         ParameterList list;
156         FunctionRNA *func;
157
158         RNA_pointer_create(&CTX_wm_screen(C)->id, pnl->type->ext.srna, pnl, &ptr);
159         func = &rna_Panel_draw_header_func; /* RNA_struct_find_function(&ptr, "draw_header"); */
160
161         RNA_parameter_list_create(&list, &ptr, func);
162         RNA_parameter_set_lookup(&list, "context", &C);
163         pnl->type->ext.call((bContext *)C, &ptr, func, &list);
164
165         RNA_parameter_list_free(&list);
166 }
167
168 static void rna_Panel_unregister(Main *bmain, StructRNA *type)
169 {
170         ARegionType *art;
171         PanelType *pt = RNA_struct_blender_type_get(type);
172
173         if (!pt)
174                 return;
175         if (!(art = region_type_find(NULL, pt->space_type, pt->region_type)))
176                 return;
177         
178         RNA_struct_free_extension(type, &pt->ext);
179
180         BLI_freelinkN(&art->paneltypes, pt);
181         RNA_struct_free(&BLENDER_RNA, type);
182
183         /* update while blender is running */
184         WM_main_add_notifier(NC_WINDOW, NULL);
185 }
186
187 static StructRNA *rna_Panel_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
188                                      StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
189 {
190         ARegionType *art;
191         PanelType *pt, dummypt = {NULL};
192         Panel dummypanel = {NULL};
193         PointerRNA dummyptr;
194         int have_function[3];
195
196         /* setup dummy panel & panel type to store static properties in */
197         dummypanel.type = &dummypt;
198         RNA_pointer_create(NULL, &RNA_Panel, &dummypanel, &dummyptr);
199
200         /* validate the python class */
201         if (validate(&dummyptr, data, have_function) != 0)
202                 return NULL;
203                 
204         if (strlen(identifier) >= sizeof(dummypt.idname)) {
205                 BKE_reportf(reports, RPT_ERROR, "Registering panel class: '%s' is too long, maximum length is %d",
206                             identifier, (int)sizeof(dummypt.idname));
207                 return NULL;
208         }
209         
210         if (!(art = region_type_find(reports, dummypt.space_type, dummypt.region_type)))
211                 return NULL;
212
213         /* check if we have registered this panel type before, and remove it */
214         for (pt = art->paneltypes.first; pt; pt = pt->next) {
215                 if (strcmp(pt->idname, dummypt.idname) == 0) {
216                         if (pt->ext.srna)
217                                 rna_Panel_unregister(bmain, pt->ext.srna);
218                         else
219                                 BLI_freelinkN(&art->paneltypes, pt);
220                         break;
221                 }
222         }
223         
224         /* create a new panel type */
225         pt = MEM_callocN(sizeof(PanelType), "python buttons panel");
226         memcpy(pt, &dummypt, sizeof(dummypt));
227
228         pt->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, pt->idname, &RNA_Panel);
229         pt->ext.data = data;
230         pt->ext.call = call;
231         pt->ext.free = free;
232         RNA_struct_blender_type_set(pt->ext.srna, pt);
233         RNA_def_struct_flag(pt->ext.srna, STRUCT_NO_IDPROPERTIES);
234
235         pt->poll = (have_function[0]) ? panel_poll : NULL;
236         pt->draw = (have_function[1]) ? panel_draw : NULL;
237         pt->draw_header = (have_function[2]) ? panel_draw_header : NULL;
238
239         /* XXX use "no header" flag for some ordering of panels until we have real panel ordering */
240         if (pt->flag & PNL_NO_HEADER) {
241                 PanelType *pth = art->paneltypes.first;
242                 while (pth && pth->flag & PNL_NO_HEADER)
243                         pth = pth->next;
244
245                 if (pth)
246                         BLI_insertlinkbefore(&art->paneltypes, pth, pt);
247                 else
248                         BLI_addtail(&art->paneltypes, pt);
249         }
250         else
251                 BLI_addtail(&art->paneltypes, pt);
252
253         /* update while blender is running */
254         WM_main_add_notifier(NC_WINDOW, NULL);
255         
256         return pt->ext.srna;
257 }
258
259 static StructRNA *rna_Panel_refine(PointerRNA *ptr)
260 {
261         Panel *hdr = (Panel *)ptr->data;
262         return (hdr->type && hdr->type->ext.srna) ? hdr->type->ext.srna : &RNA_Panel;
263 }
264
265 /* UIList */
266 static void uilist_draw_item(uiList *ui_list, bContext *C, uiLayout *layout, PointerRNA *dataptr, PointerRNA *itemptr,
267                              int icon, PointerRNA *active_dataptr, const char *active_propname, int index)
268 {
269         extern FunctionRNA rna_UIList_draw_item_func;
270
271         PointerRNA ul_ptr;
272         ParameterList list;
273         FunctionRNA *func;
274
275         RNA_pointer_create(&CTX_wm_screen(C)->id, ui_list->type->ext.srna, ui_list, &ul_ptr);
276         func = &rna_UIList_draw_item_func; /* RNA_struct_find_function(&ul_ptr, "draw_item"); */
277
278         RNA_parameter_list_create(&list, &ul_ptr, func);
279         RNA_parameter_set_lookup(&list, "context", &C);
280         RNA_parameter_set_lookup(&list, "layout", &layout);
281         RNA_parameter_set_lookup(&list, "data", dataptr);
282         RNA_parameter_set_lookup(&list, "item", itemptr);
283         RNA_parameter_set_lookup(&list, "icon", &icon);
284         RNA_parameter_set_lookup(&list, "active_data", active_dataptr);
285         RNA_parameter_set_lookup(&list, "active_property", &active_propname);
286         RNA_parameter_set_lookup(&list, "index", &index);
287         ui_list->type->ext.call((bContext *)C, &ul_ptr, func, &list);
288
289         RNA_parameter_list_free(&list);
290 }
291
292 static void rna_UIList_unregister(Main *UNUSED(bmain), StructRNA *type)
293 {
294         uiListType *ult = RNA_struct_blender_type_get(type);
295
296         if (!ult)
297                 return;
298
299         RNA_struct_free_extension(type, &ult->ext);
300
301         WM_uilisttype_freelink(ult);
302
303         RNA_struct_free(&BLENDER_RNA, type);
304
305         /* update while blender is running */
306         WM_main_add_notifier(NC_WINDOW, NULL);
307 }
308
309 static StructRNA *rna_UIList_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
310                                       StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
311 {
312         uiListType *ult, dummyult = {NULL};
313         uiList dummyuilist = {NULL};
314         PointerRNA dummyul_ptr;
315         int have_function[1];
316         size_t over_alloc = 0; /* warning, if this becomes a bess, we better do another alloc */
317
318         /* setup dummy menu & menu type to store static properties in */
319         dummyuilist.type = &dummyult;
320         RNA_pointer_create(NULL, &RNA_UIList, &dummyuilist, &dummyul_ptr);
321
322         /* validate the python class */
323         if (validate(&dummyul_ptr, data, have_function) != 0)
324                 return NULL;
325
326         if (strlen(identifier) >= sizeof(dummyult.idname)) {
327                 BKE_reportf(reports, RPT_ERROR, "Registering uilist class: '%s' is too long, maximum length is %d",
328                             identifier, (int)sizeof(dummyult.idname));
329                 return NULL;
330         }
331
332         /* check if we have registered this uilist type before, and remove it */
333         ult = WM_uilisttype_find(dummyult.idname, TRUE);
334         if (ult && ult->ext.srna)
335                 rna_UIList_unregister(bmain, ult->ext.srna);
336
337         /* create a new menu type */
338         ult = MEM_callocN(sizeof(uiListType) + over_alloc, "python uilist");
339         memcpy(ult, &dummyult, sizeof(dummyult));
340
341         ult->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, ult->idname, &RNA_UIList);
342         ult->ext.data = data;
343         ult->ext.call = call;
344         ult->ext.free = free;
345         RNA_struct_blender_type_set(ult->ext.srna, ult);
346         RNA_def_struct_flag(ult->ext.srna, STRUCT_NO_IDPROPERTIES);
347
348         ult->draw_item = (have_function[0]) ? uilist_draw_item : NULL;
349
350         WM_uilisttype_add(ult);
351
352         /* update while blender is running */
353         WM_main_add_notifier(NC_WINDOW, NULL);
354
355         return ult->ext.srna;
356 }
357
358 static StructRNA *rna_UIList_refine(PointerRNA *ptr)
359 {
360         uiList *ui_list = (uiList *)ptr->data;
361         return (ui_list->type && ui_list->type->ext.srna) ? ui_list->type->ext.srna : &RNA_UIList;
362 }
363
364 /* Header */
365
366 static void header_draw(const bContext *C, Header *hdr)
367 {
368         extern FunctionRNA rna_Header_draw_func;
369
370         PointerRNA htr;
371         ParameterList list;
372         FunctionRNA *func;
373
374         RNA_pointer_create(&CTX_wm_screen(C)->id, hdr->type->ext.srna, hdr, &htr);
375         func = &rna_Header_draw_func; /* RNA_struct_find_function(&htr, "draw"); */
376
377         RNA_parameter_list_create(&list, &htr, func);
378         RNA_parameter_set_lookup(&list, "context", &C);
379         hdr->type->ext.call((bContext *)C, &htr, func, &list);
380
381         RNA_parameter_list_free(&list);
382 }
383
384 static void rna_Header_unregister(Main *UNUSED(bmain), StructRNA *type)
385 {
386         ARegionType *art;
387         HeaderType *ht = RNA_struct_blender_type_get(type);
388
389         if (!ht)
390                 return;
391         if (!(art = region_type_find(NULL, ht->space_type, RGN_TYPE_HEADER)))
392                 return;
393         
394         RNA_struct_free_extension(type, &ht->ext);
395
396         BLI_freelinkN(&art->headertypes, ht);
397         RNA_struct_free(&BLENDER_RNA, type);
398
399         /* update while blender is running */
400         WM_main_add_notifier(NC_WINDOW, NULL);
401 }
402
403 static StructRNA *rna_Header_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
404                                       StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
405 {
406         ARegionType *art;
407         HeaderType *ht, dummyht = {NULL};
408         Header dummyheader = {NULL};
409         PointerRNA dummyhtr;
410         int have_function[1];
411
412         /* setup dummy header & header type to store static properties in */
413         dummyheader.type = &dummyht;
414         RNA_pointer_create(NULL, &RNA_Header, &dummyheader, &dummyhtr);
415
416         /* validate the python class */
417         if (validate(&dummyhtr, data, have_function) != 0)
418                 return NULL;
419
420         if (strlen(identifier) >= sizeof(dummyht.idname)) {
421                 BKE_reportf(reports, RPT_ERROR, "Registering header class: '%s' is too long, maximum length is %d",
422                             identifier, (int)sizeof(dummyht.idname));
423                 return NULL;
424         }
425
426         if (!(art = region_type_find(reports, dummyht.space_type, RGN_TYPE_HEADER)))
427                 return NULL;
428
429         /* check if we have registered this header type before, and remove it */
430         for (ht = art->headertypes.first; ht; ht = ht->next) {
431                 if (strcmp(ht->idname, dummyht.idname) == 0) {
432                         if (ht->ext.srna)
433                                 rna_Header_unregister(bmain, ht->ext.srna);
434                         break;
435                 }
436         }
437         
438         /* create a new header type */
439         ht = MEM_callocN(sizeof(HeaderType), "python buttons header");
440         memcpy(ht, &dummyht, sizeof(dummyht));
441
442         ht->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, ht->idname, &RNA_Header);
443         ht->ext.data = data;
444         ht->ext.call = call;
445         ht->ext.free = free;
446         RNA_struct_blender_type_set(ht->ext.srna, ht);
447
448         ht->draw = (have_function[0]) ? header_draw : NULL;
449
450         BLI_addtail(&art->headertypes, ht);
451
452         /* update while blender is running */
453         WM_main_add_notifier(NC_WINDOW, NULL);
454         
455         return ht->ext.srna;
456 }
457
458 static StructRNA *rna_Header_refine(PointerRNA *htr)
459 {
460         Header *hdr = (Header *)htr->data;
461         return (hdr->type && hdr->type->ext.srna) ? hdr->type->ext.srna : &RNA_Header;
462 }
463
464 /* Menu */
465
466 static int menu_poll(const bContext *C, MenuType *pt)
467 {
468         extern FunctionRNA rna_Menu_poll_func;
469
470         PointerRNA ptr;
471         ParameterList list;
472         FunctionRNA *func;
473         void *ret;
474         int visible;
475
476         RNA_pointer_create(NULL, pt->ext.srna, NULL, &ptr); /* dummy */
477         func = &rna_Menu_poll_func; /* RNA_struct_find_function(&ptr, "poll"); */
478
479         RNA_parameter_list_create(&list, &ptr, func);
480         RNA_parameter_set_lookup(&list, "context", &C);
481         pt->ext.call((bContext *)C, &ptr, func, &list);
482
483         RNA_parameter_get_lookup(&list, "visible", &ret);
484         visible = *(int *)ret;
485
486         RNA_parameter_list_free(&list);
487
488         return visible;
489 }
490
491 static void menu_draw(const bContext *C, Menu *hdr)
492 {
493         extern FunctionRNA rna_Menu_draw_func;
494
495         PointerRNA mtr;
496         ParameterList list;
497         FunctionRNA *func;
498
499         RNA_pointer_create(&CTX_wm_screen(C)->id, hdr->type->ext.srna, hdr, &mtr);
500         func = &rna_Menu_draw_func; /* RNA_struct_find_function(&mtr, "draw"); */
501
502         RNA_parameter_list_create(&list, &mtr, func);
503         RNA_parameter_set_lookup(&list, "context", &C);
504         hdr->type->ext.call((bContext *)C, &mtr, func, &list);
505
506         RNA_parameter_list_free(&list);
507 }
508
509 static void rna_Menu_unregister(Main *UNUSED(bmain), StructRNA *type)
510 {
511         MenuType *mt = RNA_struct_blender_type_get(type);
512
513         if (!mt)
514                 return;
515         
516         RNA_struct_free_extension(type, &mt->ext);
517
518         WM_menutype_freelink(mt);
519
520         RNA_struct_free(&BLENDER_RNA, type);
521
522         /* update while blender is running */
523         WM_main_add_notifier(NC_WINDOW, NULL);
524 }
525
526 static char _menu_descr[RNA_DYN_DESCR_MAX];
527 static StructRNA *rna_Menu_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
528                                     StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
529 {
530         MenuType *mt, dummymt = {NULL};
531         Menu dummymenu = {NULL};
532         PointerRNA dummymtr;
533         int have_function[2];
534         size_t over_alloc = 0; /* warning, if this becomes a bess, we better do another alloc */
535         size_t description_size = 0;
536
537         /* setup dummy menu & menu type to store static properties in */
538         dummymenu.type = &dummymt;
539         dummymenu.type->description = _menu_descr;
540         RNA_pointer_create(NULL, &RNA_Menu, &dummymenu, &dummymtr);
541
542         /* clear in case they are left unset */
543         _menu_descr[0] = '\0';
544
545         /* validate the python class */
546         if (validate(&dummymtr, data, have_function) != 0)
547                 return NULL;
548         
549         if (strlen(identifier) >= sizeof(dummymt.idname)) {
550                 BKE_reportf(reports, RPT_ERROR, "Registering menu class: '%s' is too long, maximum length is %d",
551                             identifier, (int)sizeof(dummymt.idname));
552                 return NULL;
553         }
554
555         /* check if we have registered this menu type before, and remove it */
556         mt = WM_menutype_find(dummymt.idname, TRUE);
557         if (mt && mt->ext.srna)
558                 rna_Menu_unregister(bmain, mt->ext.srna);
559         
560         /* create a new menu type */
561         if (_menu_descr[0]) {
562                 description_size = strlen(_menu_descr) + 1;
563                 over_alloc += description_size;
564         }
565
566         mt = MEM_callocN(sizeof(MenuType) + over_alloc, "python buttons menu");
567         memcpy(mt, &dummymt, sizeof(dummymt));
568
569         if (_menu_descr[0]) {
570                 char *buf = (char *)(mt + 1);
571                 memcpy(buf, _menu_descr, description_size);
572                 mt->description = buf;
573         }
574
575         mt->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, mt->idname, &RNA_Menu);
576         mt->ext.data = data;
577         mt->ext.call = call;
578         mt->ext.free = free;
579         RNA_struct_blender_type_set(mt->ext.srna, mt);
580         RNA_def_struct_flag(mt->ext.srna, STRUCT_NO_IDPROPERTIES);
581
582         mt->poll = (have_function[0]) ? menu_poll : NULL;
583         mt->draw = (have_function[1]) ? menu_draw : NULL;
584
585         WM_menutype_add(mt);
586
587         /* update while blender is running */
588         WM_main_add_notifier(NC_WINDOW, NULL);
589         
590         return mt->ext.srna;
591 }
592
593 static StructRNA *rna_Menu_refine(PointerRNA *mtr)
594 {
595         Menu *hdr = (Menu *)mtr->data;
596         return (hdr->type && hdr->type->ext.srna) ? hdr->type->ext.srna : &RNA_Menu;
597 }
598
599 static void rna_Menu_bl_description_set(PointerRNA *ptr, const char *value)
600 {
601         Menu *data = (Menu *)(ptr->data);
602         char *str = (char *)data->type->description;
603         if (!str[0]) BLI_strncpy(str, value, RNA_DYN_DESCR_MAX);     /* utf8 already ensured */
604         else assert(!"setting the bl_description on a non-builtin menu");
605 }
606
607 /* UILayout */
608
609 static int rna_UILayout_active_get(PointerRNA *ptr)
610 {
611         return uiLayoutGetActive(ptr->data);
612 }
613
614 static void rna_UILayout_active_set(PointerRNA *ptr, int value)
615 {
616         uiLayoutSetActive(ptr->data, value);
617 }
618
619 static int rna_UILayout_alert_get(PointerRNA *ptr)
620 {
621         return uiLayoutGetRedAlert(ptr->data);
622 }
623
624 static void rna_UILayout_alert_set(PointerRNA *ptr, int value)
625 {
626         uiLayoutSetRedAlert(ptr->data, value);
627 }
628
629 static void rna_UILayout_op_context_set(PointerRNA *ptr, int value)
630 {
631         uiLayoutSetOperatorContext(ptr->data, value);
632 }
633
634 static int rna_UILayout_op_context_get(PointerRNA *ptr)
635 {
636         return uiLayoutGetOperatorContext(ptr->data);
637 }
638
639 static int rna_UILayout_enabled_get(PointerRNA *ptr)
640 {
641         return uiLayoutGetEnabled(ptr->data);
642 }
643
644 static void rna_UILayout_enabled_set(PointerRNA *ptr, int value)
645 {
646         uiLayoutSetEnabled(ptr->data, value);
647 }
648
649 #if 0
650 static int rna_UILayout_red_alert_get(PointerRNA *ptr)
651 {
652         return uiLayoutGetRedAlert(ptr->data);
653 }
654
655 static void rna_UILayout_red_alert_set(PointerRNA *ptr, int value)
656 {
657         uiLayoutSetRedAlert(ptr->data, value);
658 }
659
660 static int rna_UILayout_keep_aspect_get(PointerRNA *ptr)
661 {
662         return uiLayoutGetKeepAspect(ptr->data);
663 }
664
665 static void rna_UILayout_keep_aspect_set(PointerRNA *ptr, int value)
666 {
667         uiLayoutSetKeepAspect(ptr->data, value);
668 }
669 #endif
670
671 static int rna_UILayout_alignment_get(PointerRNA *ptr)
672 {
673         return uiLayoutGetAlignment(ptr->data);
674 }
675
676 static void rna_UILayout_alignment_set(PointerRNA *ptr, int value)
677 {
678         uiLayoutSetAlignment(ptr->data, value);
679 }
680
681 static float rna_UILayout_scale_x_get(PointerRNA *ptr)
682 {
683         return uiLayoutGetScaleX(ptr->data);
684 }
685
686 static void rna_UILayout_scale_x_set(PointerRNA *ptr, float value)
687 {
688         uiLayoutSetScaleX(ptr->data, value);
689 }
690
691 static float rna_UILayout_scale_y_get(PointerRNA *ptr)
692 {
693         return uiLayoutGetScaleY(ptr->data);
694 }
695
696 static void rna_UILayout_scale_y_set(PointerRNA *ptr, float value)
697 {
698         uiLayoutSetScaleY(ptr->data, value);
699 }
700
701 #else /* RNA_RUNTIME */
702
703 static void rna_def_ui_layout(BlenderRNA *brna)
704 {
705         StructRNA *srna;
706         PropertyRNA *prop;
707
708         static EnumPropertyItem alignment_items[] = {
709                 {UI_LAYOUT_ALIGN_EXPAND, "EXPAND", 0, "Expand", ""},
710                 {UI_LAYOUT_ALIGN_LEFT, "LEFT", 0, "Left", ""},
711                 {UI_LAYOUT_ALIGN_CENTER, "CENTER", 0, "Center", ""},
712                 {UI_LAYOUT_ALIGN_RIGHT, "RIGHT", 0, "Right", ""},
713                 {0, NULL, 0, NULL, NULL}
714         };
715         
716         /* layout */
717
718         srna = RNA_def_struct(brna, "UILayout", NULL);
719         RNA_def_struct_sdna(srna, "uiLayout");
720         RNA_def_struct_ui_text(srna, "UI Layout", "User interface layout in a panel or header");
721
722         prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
723         RNA_def_property_boolean_funcs(prop, "rna_UILayout_active_get", "rna_UILayout_active_set");
724         
725         prop = RNA_def_property(srna, "operator_context", PROP_ENUM, PROP_NONE);
726         RNA_def_property_enum_items(prop, operator_context_items);
727         RNA_def_property_enum_funcs(prop, "rna_UILayout_op_context_get", "rna_UILayout_op_context_set", NULL);
728         
729         prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
730         RNA_def_property_boolean_funcs(prop, "rna_UILayout_enabled_get", "rna_UILayout_enabled_set");
731         RNA_def_property_ui_text(prop, "Enabled", "When false, this (sub)layout is grayed out");
732         
733         prop = RNA_def_property(srna, "alert", PROP_BOOLEAN, PROP_NONE);
734         RNA_def_property_boolean_funcs(prop, "rna_UILayout_alert_get", "rna_UILayout_alert_set");
735
736         prop = RNA_def_property(srna, "alignment", PROP_ENUM, PROP_NONE);
737         RNA_def_property_enum_items(prop, alignment_items);
738         RNA_def_property_enum_funcs(prop, "rna_UILayout_alignment_get", "rna_UILayout_alignment_set", NULL);
739
740 #if 0
741         prop = RNA_def_property(srna, "keep_aspect", PROP_BOOLEAN, PROP_NONE);
742         RNA_def_property_boolean_funcs(prop, "rna_UILayout_keep_aspect_get", "rna_UILayout_keep_aspect_set");
743 #endif
744
745         prop = RNA_def_property(srna, "scale_x", PROP_FLOAT, PROP_UNSIGNED);
746         RNA_def_property_float_funcs(prop, "rna_UILayout_scale_x_get", "rna_UILayout_scale_x_set", NULL);
747         RNA_def_property_ui_text(prop, "Scale X", "Scale factor along the X for items in this (sub)layout");
748         
749         prop = RNA_def_property(srna, "scale_y", PROP_FLOAT, PROP_UNSIGNED);
750         RNA_def_property_float_funcs(prop, "rna_UILayout_scale_y_get", "rna_UILayout_scale_y_set", NULL);
751         RNA_def_property_ui_text(prop, "Scale Y", "Scale factor along the Y for items in this (sub)layout");
752         RNA_api_ui_layout(srna);
753 }
754
755 static void rna_def_panel(BlenderRNA *brna)
756 {
757         StructRNA *srna;
758         PropertyRNA *prop;
759         PropertyRNA *parm;
760         FunctionRNA *func;
761         
762         static EnumPropertyItem panel_flag_items[] = {
763                 {PNL_DEFAULT_CLOSED, "DEFAULT_CLOSED", 0, "Default Closed",
764                                      "Defines if the panel has to be open or collapsed at the time of its creation"},
765                 {PNL_NO_HEADER, "HIDE_HEADER", 0, "Hide Header",
766                                 "If set to False, the panel shows a header, which contains a clickable "
767                                 "arrow to collapse the panel and the label (see bl_label)"},
768                 {0, NULL, 0, NULL, NULL}
769         };
770         
771         srna = RNA_def_struct(brna, "Panel", NULL);
772         RNA_def_struct_ui_text(srna, "Panel", "Panel containing UI elements");
773         RNA_def_struct_sdna(srna, "Panel");
774         RNA_def_struct_refine_func(srna, "rna_Panel_refine");
775         RNA_def_struct_register_funcs(srna, "rna_Panel_register", "rna_Panel_unregister", NULL);
776
777         /* poll */
778         func = RNA_def_function(srna, "poll", NULL);
779         RNA_def_function_ui_description(func, "If this method returns a non-null output, then the panel can be drawn");
780         RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
781         RNA_def_function_return(func, RNA_def_boolean(func, "visible", 1, "", ""));
782         parm = RNA_def_pointer(func, "context", "Context", "", "");
783         RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
784
785         /* draw */
786         func = RNA_def_function(srna, "draw", NULL);
787         RNA_def_function_ui_description(func, "Draw UI elements into the panel UI layout");
788         RNA_def_function_flag(func, FUNC_REGISTER);
789         parm = RNA_def_pointer(func, "context", "Context", "", "");
790         RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
791
792         func = RNA_def_function(srna, "draw_header", NULL);
793         RNA_def_function_ui_description(func, "Draw UI elements into the panel's header UI layout");
794         RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
795         parm = RNA_def_pointer(func, "context", "Context", "", "");
796         RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
797
798         prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
799         RNA_def_property_struct_type(prop, "UILayout");
800         RNA_def_property_ui_text(prop, "Layout", "Defines the structure of the panel in the UI");
801         
802         prop = RNA_def_property(srna, "text", PROP_STRING, PROP_NONE);
803         RNA_def_property_string_sdna(prop, NULL, "drawname");
804         RNA_def_property_ui_text(prop, "Text", "XXX todo");
805         
806         /* registration */
807         prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
808         RNA_def_property_string_sdna(prop, NULL, "type->idname");
809         RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
810         RNA_def_property_ui_text(prop, "ID Name",
811                                  "If this is set, the panel gets a custom ID, otherwise it takes the "
812                                  "name of the class used to define the panel. For example, if the "
813                                  "class name is \"OBJECT_PT_hello\", and bl_idname is not set by the "
814                                  "script, then bl_idname = \"OBJECT_PT_hello\"");
815
816         prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
817         RNA_def_property_string_sdna(prop, NULL, "type->label");
818         RNA_def_property_flag(prop, PROP_REGISTER);
819         RNA_def_property_ui_text(prop, "Label",
820                                  "The panel label, shows up in the panel header at the right of the "
821                                  "triangle used to collapse the panel");
822         
823         prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE);
824         RNA_def_property_enum_sdna(prop, NULL, "type->space_type");
825         RNA_def_property_enum_items(prop, space_type_items);
826         RNA_def_property_flag(prop, PROP_REGISTER);
827         RNA_def_property_ui_text(prop, "Space type", "The space where the panel is going to be used in");
828         
829         prop = RNA_def_property(srna, "bl_region_type", PROP_ENUM, PROP_NONE);
830         RNA_def_property_enum_sdna(prop, NULL, "type->region_type");
831         RNA_def_property_enum_items(prop, region_type_items);
832         RNA_def_property_flag(prop, PROP_REGISTER);
833         RNA_def_property_ui_text(prop, "Region Type", "The region where the panel is going to be used in");
834
835         prop = RNA_def_property(srna, "bl_context", PROP_STRING, PROP_NONE);
836         RNA_def_property_string_sdna(prop, NULL, "type->context");
837         RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); /* Only used in Properties Editor and 3D View - Thomas */
838         RNA_def_property_ui_text(prop, "Context",
839                                  "The context in which the panel belongs to. (TODO: explain the "
840                                  "possible combinations bl_context/bl_region_type/bl_space_type)");
841         
842         prop = RNA_def_property(srna, "bl_options", PROP_ENUM, PROP_NONE);
843         RNA_def_property_enum_sdna(prop, NULL, "type->flag");
844         RNA_def_property_enum_items(prop, panel_flag_items);
845         RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL | PROP_ENUM_FLAG);
846         RNA_def_property_ui_text(prop, "Options",  "Options for this panel type");
847 }
848
849 static void rna_def_uilist(BlenderRNA *brna)
850 {
851         StructRNA *srna;
852         PropertyRNA *prop;
853         PropertyRNA *parm;
854         FunctionRNA *func;
855
856         srna = RNA_def_struct(brna, "UIList", NULL);
857         RNA_def_struct_ui_text(srna, "UIList", "UI list containing the elements of a collection");
858         RNA_def_struct_sdna(srna, "uiList");
859         RNA_def_struct_refine_func(srna, "rna_UIList_refine");
860         RNA_def_struct_register_funcs(srna, "rna_UIList_register", "rna_UIList_unregister", NULL);
861
862         /* draw */
863         func = RNA_def_function(srna, "draw_item", NULL);
864         RNA_def_function_ui_description(func, "Draw an item in the list (NOTE: when you define your own draw_item "
865                                               "function, you may want to check given 'item' is of the right type...)");
866         RNA_def_function_flag(func, FUNC_REGISTER);
867         parm = RNA_def_pointer(func, "context", "Context", "", "");
868         RNA_def_property_flag(parm, PROP_REQUIRED);
869         parm = RNA_def_pointer(func, "layout", "UILayout", "", "Layout to draw the item");
870         RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
871         parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take Collection property");
872         RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
873         parm = RNA_def_pointer(func, "item", "AnyType", "", "Item of the collection property");
874         RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
875         parm = RNA_def_int(func, "icon", 0, 0, INT_MAX, "", "Icon of the item in the collection", 0, INT_MAX);
876         RNA_def_property_flag(parm, PROP_REQUIRED);
877         parm = RNA_def_pointer(func, "active_data", "AnyType", "",
878                                "Data from which to take property for the active element");
879         RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
880         parm = RNA_def_string(func, "active_property", "", 0, "",
881                               "Identifier of property in active_data, for the active element");
882         RNA_def_property_flag(parm, PROP_REQUIRED);
883         RNA_def_int(func, "index", 0, 0, INT_MAX, "", "Index of the item in the collection", 0, INT_MAX);
884         RNA_def_property_flag(parm, PROP_REQUIRED);
885
886         prop = RNA_def_property(srna, "layout_type", PROP_ENUM, PROP_NONE);
887         RNA_def_property_enum_items(prop, uilist_layout_type_items);
888         RNA_def_property_clear_flag(prop, PROP_EDITABLE);
889
890         /* registration */
891         prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
892         RNA_def_property_string_sdna(prop, NULL, "type->idname");
893         RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
894         RNA_def_property_ui_text(prop, "ID Name",
895                                  "If this is set, the uilist gets a custom ID, otherwise it takes the "
896                                  "name of the class used to define the uilist (for example, if the "
897                                  "class name is \"OBJECT_UL_vgroups\", and bl_idname is not set by the "
898                                  "script, then bl_idname = \"OBJECT_UL_vgroups\")");
899 }
900
901 static void rna_def_header(BlenderRNA *brna)
902 {
903         StructRNA *srna;
904         PropertyRNA *prop;
905         PropertyRNA *parm;
906         FunctionRNA *func;
907         
908         srna = RNA_def_struct(brna, "Header", NULL);
909         RNA_def_struct_ui_text(srna, "Header", "Editor header containing UI elements");
910         RNA_def_struct_sdna(srna, "Header");
911         RNA_def_struct_refine_func(srna, "rna_Header_refine");
912         RNA_def_struct_register_funcs(srna, "rna_Header_register", "rna_Header_unregister", NULL);
913
914         /* draw */
915         func = RNA_def_function(srna, "draw", NULL);
916         RNA_def_function_ui_description(func, "Draw UI elements into the header UI layout");
917         RNA_def_function_flag(func, FUNC_REGISTER);
918         parm = RNA_def_pointer(func, "context", "Context", "", "");
919         RNA_def_property_flag(parm, PROP_REQUIRED);
920
921         RNA_define_verify_sdna(0); /* not in sdna */
922
923         prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
924         RNA_def_property_pointer_sdna(prop, NULL, "layout");
925         RNA_def_property_struct_type(prop, "UILayout");
926         RNA_def_property_ui_text(prop, "Layout", "Structure of the header in the UI");
927
928         /* registration */
929         prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
930         RNA_def_property_string_sdna(prop, NULL, "type->idname");
931         RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
932         RNA_def_property_ui_text(prop, "ID Name",
933                                  "If this is set, the header gets a custom ID, otherwise it takes the "
934                                  "name of the class used to define the panel; for example, if the "
935                                  "class name is \"OBJECT_HT_hello\", and bl_idname is not set by the "
936                                  "script, then bl_idname = \"OBJECT_HT_hello\"");
937
938         prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE);
939         RNA_def_property_enum_sdna(prop, NULL, "type->space_type");
940         RNA_def_property_enum_items(prop, space_type_items);
941         RNA_def_property_flag(prop, PROP_REGISTER);
942         RNA_def_property_ui_text(prop, "Space type", "The space where the header is going to be used in");
943
944         RNA_define_verify_sdna(1);
945 }
946
947 static void rna_def_menu(BlenderRNA *brna)
948 {
949         StructRNA *srna;
950         PropertyRNA *prop;
951         PropertyRNA *parm;
952         FunctionRNA *func;
953         
954         srna = RNA_def_struct(brna, "Menu", NULL);
955         RNA_def_struct_ui_text(srna, "Menu", "Editor menu containing buttons");
956         RNA_def_struct_sdna(srna, "Menu");
957         RNA_def_struct_refine_func(srna, "rna_Menu_refine");
958         RNA_def_struct_register_funcs(srna, "rna_Menu_register", "rna_Menu_unregister", NULL);
959
960         /* poll */
961         func = RNA_def_function(srna, "poll", NULL);
962         RNA_def_function_ui_description(func, "If this method returns a non-null output, then the menu can be drawn");
963         RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
964         RNA_def_function_return(func, RNA_def_boolean(func, "visible", 1, "", ""));
965         parm = RNA_def_pointer(func, "context", "Context", "", "");
966         RNA_def_property_flag(parm, PROP_REQUIRED);
967
968         /* draw */
969         func = RNA_def_function(srna, "draw", NULL);
970         RNA_def_function_ui_description(func, "Draw UI elements into the menu UI layout");
971         RNA_def_function_flag(func, FUNC_REGISTER);
972         parm = RNA_def_pointer(func, "context", "Context", "", "");
973         RNA_def_property_flag(parm, PROP_REQUIRED);
974
975         RNA_define_verify_sdna(0); /* not in sdna */
976
977         prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
978         RNA_def_property_pointer_sdna(prop, NULL, "layout");
979         RNA_def_property_struct_type(prop, "UILayout");
980         RNA_def_property_ui_text(prop, "Layout", "Defines the structure of the menu in the UI");
981
982         /* registration */
983         prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
984         RNA_def_property_string_sdna(prop, NULL, "type->idname");
985         RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
986         RNA_def_property_ui_text(prop, "ID Name",
987                                  "If this is set, the menu gets a custom ID, otherwise it takes the "
988                                  "name of the class used to define the menu (for example, if the "
989                                  "class name is \"OBJECT_MT_hello\", and bl_idname is not set by the "
990                                  "script, then bl_idname = \"OBJECT_MT_hello\")");
991
992         prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
993         RNA_def_property_string_sdna(prop, NULL, "type->label");
994         RNA_def_property_flag(prop, PROP_REGISTER);
995         RNA_def_property_ui_text(prop, "Label", "The menu label");
996
997         prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_NONE);
998         RNA_def_property_string_sdna(prop, NULL, "type->description");
999         RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */
1000         RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Menu_bl_description_set");
1001         /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
1002         RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1003         RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */
1004
1005         RNA_define_verify_sdna(1);
1006 }
1007
1008 void RNA_def_ui(BlenderRNA *brna)
1009 {
1010         rna_def_ui_layout(brna);
1011         rna_def_panel(brna);
1012         rna_def_uilist(brna);
1013         rna_def_header(brna);
1014         rna_def_menu(brna);
1015 }
1016
1017 #endif /* RNA_RUNTIME */
1018