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