Merged changes in the trunk up to revision 46787.
[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 #ifdef RNA_RUNTIME
59
60 #include <assert.h>
61
62 #include "MEM_guardedalloc.h"
63
64 #include "RNA_access.h"
65
66 #include "BLI_dynstr.h"
67
68 #include "BKE_context.h"
69 #include "BKE_report.h"
70 #include "BKE_screen.h"
71
72 #include "WM_api.h"
73
74 static ARegionType *region_type_find(ReportList *reports, int space_type, int region_type)
75 {
76         SpaceType *st;
77         ARegionType *art;
78
79         st = BKE_spacetype_from_id(space_type);
80
81         for (art = (st) ? st->regiontypes.first : NULL; art; art = art->next) {
82                 if (art->regionid == region_type)
83                         break;
84         }
85         
86         /* region type not found? abort */
87         if (art == NULL) {
88                 BKE_report(reports, RPT_ERROR, "Region not found in spacetype");
89                 return NULL;
90         }
91
92         return art;
93 }
94
95 /* Panel */
96
97 static int panel_poll(const bContext *C, PanelType *pt)
98 {
99         extern FunctionRNA rna_Panel_poll_func;
100
101         PointerRNA ptr;
102         ParameterList list;
103         FunctionRNA *func;
104         void *ret;
105         int visible;
106
107         RNA_pointer_create(NULL, pt->ext.srna, NULL, &ptr); /* dummy */
108         func = &rna_Panel_poll_func; /* RNA_struct_find_function(&ptr, "poll"); */
109
110         RNA_parameter_list_create(&list, &ptr, func);
111         RNA_parameter_set_lookup(&list, "context", &C);
112         pt->ext.call((bContext *)C, &ptr, func, &list);
113
114         RNA_parameter_get_lookup(&list, "visible", &ret);
115         visible = *(int *)ret;
116
117         RNA_parameter_list_free(&list);
118
119         return visible;
120 }
121
122 static void panel_draw(const bContext *C, Panel *pnl)
123 {
124         extern FunctionRNA rna_Panel_draw_func;
125
126         PointerRNA ptr;
127         ParameterList list;
128         FunctionRNA *func;
129
130         RNA_pointer_create(&CTX_wm_screen(C)->id, pnl->type->ext.srna, pnl, &ptr);
131         func = &rna_Panel_draw_func; /* RNA_struct_find_function(&ptr, "draw"); */
132
133         RNA_parameter_list_create(&list, &ptr, func);
134         RNA_parameter_set_lookup(&list, "context", &C);
135         pnl->type->ext.call((bContext *)C, &ptr, func, &list);
136
137         RNA_parameter_list_free(&list);
138 }
139
140 static void panel_draw_header(const bContext *C, Panel *pnl)
141 {
142         extern FunctionRNA rna_Panel_draw_header_func;
143
144         PointerRNA ptr;
145         ParameterList list;
146         FunctionRNA *func;
147
148         RNA_pointer_create(&CTX_wm_screen(C)->id, pnl->type->ext.srna, pnl, &ptr);
149         func = &rna_Panel_draw_header_func; /* RNA_struct_find_function(&ptr, "draw_header"); */
150
151         RNA_parameter_list_create(&list, &ptr, func);
152         RNA_parameter_set_lookup(&list, "context", &C);
153         pnl->type->ext.call((bContext *)C, &ptr, func, &list);
154
155         RNA_parameter_list_free(&list);
156 }
157
158 static void rna_Panel_unregister(Main *UNUSED(bmain), StructRNA *type)
159 {
160         ARegionType *art;
161         PanelType *pt = RNA_struct_blender_type_get(type);
162
163         if (!pt)
164                 return;
165         if (!(art = region_type_find(NULL, pt->space_type, pt->region_type)))
166                 return;
167         
168         RNA_struct_free_extension(type, &pt->ext);
169
170         BLI_freelinkN(&art->paneltypes, pt);
171         RNA_struct_free(&BLENDER_RNA, type);
172
173         /* update while blender is running */
174         WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
175 }
176
177 static StructRNA *rna_Panel_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
178                                      StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
179 {
180         ARegionType *art;
181         PanelType *pt, dummypt = {NULL};
182         Panel dummypanel = {NULL};
183         PointerRNA dummyptr;
184         int have_function[3];
185
186         /* setup dummy panel & panel type to store static properties in */
187         dummypanel.type = &dummypt;
188         RNA_pointer_create(NULL, &RNA_Panel, &dummypanel, &dummyptr);
189
190         /* validate the python class */
191         if (validate(&dummyptr, data, have_function) != 0)
192                 return NULL;
193                 
194         if (strlen(identifier) >= sizeof(dummypt.idname)) {
195                 BKE_reportf(reports, RPT_ERROR, "registering panel class: '%s' is too long, maximum length is %d",
196                             identifier, (int)sizeof(dummypt.idname));
197                 return NULL;
198         }
199         
200         if (!(art = region_type_find(reports, dummypt.space_type, dummypt.region_type)))
201                 return NULL;
202
203         /* check if we have registered this panel type before, and remove it */
204         for (pt = art->paneltypes.first; pt; pt = pt->next) {
205                 if (strcmp(pt->idname, dummypt.idname) == 0) {
206                         if (pt->ext.srna)
207                                 rna_Panel_unregister(bmain, pt->ext.srna);
208                         else
209                                 BLI_freelinkN(&art->paneltypes, pt);
210                         break;
211                 }
212         }
213         
214         /* create a new panel type */
215         pt = MEM_callocN(sizeof(PanelType), "python buttons panel");
216         memcpy(pt, &dummypt, sizeof(dummypt));
217
218         pt->ext.srna = RNA_def_struct(&BLENDER_RNA, pt->idname, "Panel");
219         pt->ext.data = data;
220         pt->ext.call = call;
221         pt->ext.free = free;
222         RNA_struct_blender_type_set(pt->ext.srna, pt);
223         RNA_def_struct_flag(pt->ext.srna, STRUCT_NO_IDPROPERTIES);
224
225         pt->poll = (have_function[0]) ? panel_poll : NULL;
226         pt->draw = (have_function[1]) ? panel_draw : NULL;
227         pt->draw_header = (have_function[2]) ? panel_draw_header : NULL;
228
229         /* XXX use "no header" flag for some ordering of panels until we have real panel ordering */
230         if (pt->flag & PNL_NO_HEADER) {
231                 PanelType *pth = art->paneltypes.first;
232                 while (pth && pth->flag & PNL_NO_HEADER)
233                         pth = pth->next;
234
235                 if (pth)
236                         BLI_insertlinkbefore(&art->paneltypes, pth, pt);
237                 else
238                         BLI_addtail(&art->paneltypes, pt);
239         }
240         else
241                 BLI_addtail(&art->paneltypes, pt);
242
243         /* update while blender is running */
244         WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
245         
246         return pt->ext.srna;
247 }
248
249 static StructRNA *rna_Panel_refine(PointerRNA *ptr)
250 {
251         Panel *hdr = (Panel *)ptr->data;
252         return (hdr->type && hdr->type->ext.srna) ? hdr->type->ext.srna : &RNA_Panel;
253 }
254
255 /* Header */
256
257 static void header_draw(const bContext *C, Header *hdr)
258 {
259         extern FunctionRNA rna_Header_draw_func;
260
261         PointerRNA htr;
262         ParameterList list;
263         FunctionRNA *func;
264
265         RNA_pointer_create(&CTX_wm_screen(C)->id, hdr->type->ext.srna, hdr, &htr);
266         func = &rna_Header_draw_func; /* RNA_struct_find_function(&htr, "draw"); */
267
268         RNA_parameter_list_create(&list, &htr, func);
269         RNA_parameter_set_lookup(&list, "context", &C);
270         hdr->type->ext.call((bContext *)C, &htr, func, &list);
271
272         RNA_parameter_list_free(&list);
273 }
274
275 static void rna_Header_unregister(Main *UNUSED(bmain), StructRNA *type)
276 {
277         ARegionType *art;
278         HeaderType *ht = RNA_struct_blender_type_get(type);
279
280         if (!ht)
281                 return;
282         if (!(art = region_type_find(NULL, ht->space_type, RGN_TYPE_HEADER)))
283                 return;
284         
285         RNA_struct_free_extension(type, &ht->ext);
286
287         BLI_freelinkN(&art->headertypes, ht);
288         RNA_struct_free(&BLENDER_RNA, type);
289
290         /* update while blender is running */
291         WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
292 }
293
294 static StructRNA *rna_Header_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
295                                       StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
296 {
297         ARegionType *art;
298         HeaderType *ht, dummyht = {NULL};
299         Header dummyheader = {NULL};
300         PointerRNA dummyhtr;
301         int have_function[1];
302
303         /* setup dummy header & header type to store static properties in */
304         dummyheader.type = &dummyht;
305         RNA_pointer_create(NULL, &RNA_Header, &dummyheader, &dummyhtr);
306
307         /* validate the python class */
308         if (validate(&dummyhtr, data, have_function) != 0)
309                 return NULL;
310
311         if (strlen(identifier) >= sizeof(dummyht.idname)) {
312                 BKE_reportf(reports, RPT_ERROR, "registering header class: '%s' is too long, maximum length is %d",
313                             identifier, (int)sizeof(dummyht.idname));
314                 return NULL;
315         }
316
317         if (!(art = region_type_find(reports, dummyht.space_type, RGN_TYPE_HEADER)))
318                 return NULL;
319
320         /* check if we have registered this header type before, and remove it */
321         for (ht = art->headertypes.first; ht; ht = ht->next) {
322                 if (strcmp(ht->idname, dummyht.idname) == 0) {
323                         if (ht->ext.srna)
324                                 rna_Header_unregister(bmain, ht->ext.srna);
325                         break;
326                 }
327         }
328         
329         /* create a new header type */
330         ht = MEM_callocN(sizeof(HeaderType), "python buttons header");
331         memcpy(ht, &dummyht, sizeof(dummyht));
332
333         ht->ext.srna = RNA_def_struct(&BLENDER_RNA, ht->idname, "Header");
334         ht->ext.data = data;
335         ht->ext.call = call;
336         ht->ext.free = free;
337         RNA_struct_blender_type_set(ht->ext.srna, ht);
338
339         ht->draw = (have_function[0]) ? header_draw : NULL;
340
341         BLI_addtail(&art->headertypes, ht);
342
343         /* update while blender is running */
344         WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
345         
346         return ht->ext.srna;
347 }
348
349 static StructRNA *rna_Header_refine(PointerRNA *htr)
350 {
351         Header *hdr = (Header *)htr->data;
352         return (hdr->type && hdr->type->ext.srna) ? hdr->type->ext.srna : &RNA_Header;
353 }
354
355 /* Menu */
356
357 static int menu_poll(const bContext *C, MenuType *pt)
358 {
359         extern FunctionRNA rna_Menu_poll_func;
360
361         PointerRNA ptr;
362         ParameterList list;
363         FunctionRNA *func;
364         void *ret;
365         int visible;
366
367         RNA_pointer_create(NULL, pt->ext.srna, NULL, &ptr); /* dummy */
368         func = &rna_Menu_poll_func; /* RNA_struct_find_function(&ptr, "poll"); */
369
370         RNA_parameter_list_create(&list, &ptr, func);
371         RNA_parameter_set_lookup(&list, "context", &C);
372         pt->ext.call((bContext *)C, &ptr, func, &list);
373
374         RNA_parameter_get_lookup(&list, "visible", &ret);
375         visible = *(int *)ret;
376
377         RNA_parameter_list_free(&list);
378
379         return visible;
380 }
381
382 static void menu_draw(const bContext *C, Menu *hdr)
383 {
384         extern FunctionRNA rna_Menu_draw_func;
385
386         PointerRNA mtr;
387         ParameterList list;
388         FunctionRNA *func;
389
390         RNA_pointer_create(&CTX_wm_screen(C)->id, hdr->type->ext.srna, hdr, &mtr);
391         func = &rna_Menu_draw_func; /* RNA_struct_find_function(&mtr, "draw"); */
392
393         RNA_parameter_list_create(&list, &mtr, func);
394         RNA_parameter_set_lookup(&list, "context", &C);
395         hdr->type->ext.call((bContext *)C, &mtr, func, &list);
396
397         RNA_parameter_list_free(&list);
398 }
399
400 static void rna_Menu_unregister(Main *UNUSED(bmain), StructRNA *type)
401 {
402         MenuType *mt = RNA_struct_blender_type_get(type);
403
404         if (!mt)
405                 return;
406         
407         RNA_struct_free_extension(type, &mt->ext);
408
409         WM_menutype_freelink(mt);
410
411         RNA_struct_free(&BLENDER_RNA, type);
412
413         /* update while blender is running */
414         WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
415 }
416
417 static char _menu_descr[RNA_DYN_DESCR_MAX];
418 static StructRNA *rna_Menu_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
419                                     StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
420 {
421         MenuType *mt, dummymt = {NULL};
422         Menu dummymenu = {NULL};
423         PointerRNA dummymtr;
424         int have_function[2];
425         size_t over_alloc = 0; /* warning, if this becomes a bess, we better do another alloc */
426         size_t description_size = 0;
427
428         /* setup dummy menu & menu type to store static properties in */
429         dummymenu.type = &dummymt;
430         dummymenu.type->description = _menu_descr;
431         RNA_pointer_create(NULL, &RNA_Menu, &dummymenu, &dummymtr);
432
433         /* clear in case they are left unset */
434         _menu_descr[0] = '\0';
435
436         /* validate the python class */
437         if (validate(&dummymtr, data, have_function) != 0)
438                 return NULL;
439         
440         if (strlen(identifier) >= sizeof(dummymt.idname)) {
441                 BKE_reportf(reports, RPT_ERROR, "registering menu class: '%s' is too long, maximum length is %d",
442                             identifier, (int)sizeof(dummymt.idname));
443                 return NULL;
444         }
445
446         /* check if we have registered this menu type before, and remove it */
447         mt = WM_menutype_find(dummymt.idname, TRUE);
448         if (mt && mt->ext.srna)
449                 rna_Menu_unregister(bmain, mt->ext.srna);
450         
451         /* create a new menu type */
452         if (_menu_descr[0]) {
453                 description_size = strlen(_menu_descr) + 1;
454                 over_alloc += description_size;
455         }
456
457         mt = MEM_callocN(sizeof(MenuType) + over_alloc, "python buttons menu");
458         memcpy(mt, &dummymt, sizeof(dummymt));
459
460         if (_menu_descr[0]) {
461                 char *buf = (char *)(mt + 1);
462                 memcpy(buf, _menu_descr, description_size);
463                 mt->description = buf;
464         }
465
466         mt->ext.srna = RNA_def_struct(&BLENDER_RNA, mt->idname, "Menu");
467         mt->ext.data = data;
468         mt->ext.call = call;
469         mt->ext.free = free;
470         RNA_struct_blender_type_set(mt->ext.srna, mt);
471         RNA_def_struct_flag(mt->ext.srna, STRUCT_NO_IDPROPERTIES);
472
473         mt->poll = (have_function[0]) ? menu_poll : NULL;
474         mt->draw = (have_function[1]) ? menu_draw : NULL;
475
476         WM_menutype_add(mt);
477
478         /* update while blender is running */
479         WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
480         
481         return mt->ext.srna;
482 }
483
484 static StructRNA *rna_Menu_refine(PointerRNA *mtr)
485 {
486         Menu *hdr = (Menu *)mtr->data;
487         return (hdr->type && hdr->type->ext.srna) ? hdr->type->ext.srna : &RNA_Menu;
488 }
489
490 static void rna_Menu_bl_description_set(PointerRNA *ptr, const char *value)
491 {
492         Menu *data = (Menu *)(ptr->data);
493         char *str = (char *)data->type->description;
494         if (!str[0]) BLI_strncpy(str, value, RNA_DYN_DESCR_MAX);     /* utf8 already ensured */
495         else assert(!"setting the bl_description on a non-builtin menu");
496 }
497
498 static int rna_UILayout_active_get(PointerRNA *ptr)
499 {
500         return uiLayoutGetActive(ptr->data);
501 }
502
503 static void rna_UILayout_active_set(PointerRNA *ptr, int value)
504 {
505         uiLayoutSetActive(ptr->data, value);
506 }
507
508 static int rna_UILayout_alert_get(PointerRNA *ptr)
509 {
510         return uiLayoutGetRedAlert(ptr->data);
511 }
512
513 static void rna_UILayout_alert_set(PointerRNA *ptr, int value)
514 {
515         uiLayoutSetRedAlert(ptr->data, value);
516 }
517
518 static void rna_UILayout_op_context_set(PointerRNA *ptr, int value)
519 {
520         uiLayoutSetOperatorContext(ptr->data, value);
521 }
522
523 static int rna_UILayout_op_context_get(PointerRNA *ptr)
524 {
525         return uiLayoutGetOperatorContext(ptr->data);
526 }
527
528 static int rna_UILayout_enabled_get(PointerRNA *ptr)
529 {
530         return uiLayoutGetEnabled(ptr->data);
531 }
532
533 static void rna_UILayout_enabled_set(PointerRNA *ptr, int value)
534 {
535         uiLayoutSetEnabled(ptr->data, value);
536 }
537
538 #if 0
539 static int rna_UILayout_red_alert_get(PointerRNA *ptr)
540 {
541         return uiLayoutGetRedAlert(ptr->data);
542 }
543
544 static void rna_UILayout_red_alert_set(PointerRNA *ptr, int value)
545 {
546         uiLayoutSetRedAlert(ptr->data, value);
547 }
548
549 static int rna_UILayout_keep_aspect_get(PointerRNA *ptr)
550 {
551         return uiLayoutGetKeepAspect(ptr->data);
552 }
553
554 static void rna_UILayout_keep_aspect_set(PointerRNA *ptr, int value)
555 {
556         uiLayoutSetKeepAspect(ptr->data, value);
557 }
558 #endif
559
560 static int rna_UILayout_alignment_get(PointerRNA *ptr)
561 {
562         return uiLayoutGetAlignment(ptr->data);
563 }
564
565 static void rna_UILayout_alignment_set(PointerRNA *ptr, int value)
566 {
567         uiLayoutSetAlignment(ptr->data, value);
568 }
569
570 static float rna_UILayout_scale_x_get(PointerRNA *ptr)
571 {
572         return uiLayoutGetScaleX(ptr->data);
573 }
574
575 static void rna_UILayout_scale_x_set(PointerRNA *ptr, float value)
576 {
577         uiLayoutSetScaleX(ptr->data, value);
578 }
579
580 static float rna_UILayout_scale_y_get(PointerRNA *ptr)
581 {
582         return uiLayoutGetScaleY(ptr->data);
583 }
584
585 static void rna_UILayout_scale_y_set(PointerRNA *ptr, float value)
586 {
587         uiLayoutSetScaleY(ptr->data, value);
588 }
589
590 #else /* RNA_RUNTIME */
591
592 static void rna_def_ui_layout(BlenderRNA *brna)
593 {
594         StructRNA *srna;
595         PropertyRNA *prop;
596
597         static EnumPropertyItem alignment_items[] = {
598                 {UI_LAYOUT_ALIGN_EXPAND, "EXPAND", 0, "Expand", ""},
599                 {UI_LAYOUT_ALIGN_LEFT, "LEFT", 0, "Left", ""},
600                 {UI_LAYOUT_ALIGN_CENTER, "CENTER", 0, "Center", ""},
601                 {UI_LAYOUT_ALIGN_RIGHT, "RIGHT", 0, "Right", ""},
602                 {0, NULL, 0, NULL, NULL}
603         };
604         
605         /* layout */
606
607         srna = RNA_def_struct(brna, "UILayout", NULL);
608         RNA_def_struct_sdna(srna, "uiLayout");
609         RNA_def_struct_ui_text(srna, "UI Layout", "User interface layout in a panel or header");
610
611         prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
612         RNA_def_property_boolean_funcs(prop, "rna_UILayout_active_get", "rna_UILayout_active_set");
613         
614         prop = RNA_def_property(srna, "operator_context", PROP_ENUM, PROP_NONE);
615         RNA_def_property_enum_items(prop, operator_context_items);
616         RNA_def_property_enum_funcs(prop, "rna_UILayout_op_context_get", "rna_UILayout_op_context_set", NULL);
617         
618         prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
619         RNA_def_property_boolean_funcs(prop, "rna_UILayout_enabled_get", "rna_UILayout_enabled_set");
620         RNA_def_property_ui_text(prop, "Enabled", "When false, this (sub)layout is greyed out");
621         
622         prop = RNA_def_property(srna, "alert", PROP_BOOLEAN, PROP_NONE);
623         RNA_def_property_boolean_funcs(prop, "rna_UILayout_alert_get", "rna_UILayout_alert_set");
624
625         prop = RNA_def_property(srna, "alignment", PROP_ENUM, PROP_NONE);
626         RNA_def_property_enum_items(prop, alignment_items);
627         RNA_def_property_enum_funcs(prop, "rna_UILayout_alignment_get", "rna_UILayout_alignment_set", NULL);
628
629 #if 0
630         prop = RNA_def_property(srna, "keep_aspect", PROP_BOOLEAN, PROP_NONE);
631         RNA_def_property_boolean_funcs(prop, "rna_UILayout_keep_aspect_get", "rna_UILayout_keep_aspect_set");
632 #endif
633
634         prop = RNA_def_property(srna, "scale_x", PROP_FLOAT, PROP_UNSIGNED);
635         RNA_def_property_float_funcs(prop, "rna_UILayout_scale_x_get", "rna_UILayout_scale_x_set", NULL);
636         RNA_def_property_ui_text(prop, "Scale X", "Scale factor along the X for items in this (sub)layout");
637         
638         prop = RNA_def_property(srna, "scale_y", PROP_FLOAT, PROP_UNSIGNED);
639         RNA_def_property_float_funcs(prop, "rna_UILayout_scale_y_get", "rna_UILayout_scale_y_set", NULL);
640         RNA_def_property_ui_text(prop, "Scale Y", "Scale factor along the Y for items in this (sub)layout");
641         RNA_api_ui_layout(srna);
642 }
643
644 static void rna_def_panel(BlenderRNA *brna)
645 {
646         StructRNA *srna;
647         PropertyRNA *prop;
648         PropertyRNA *parm;
649         FunctionRNA *func;
650         
651         static EnumPropertyItem panel_flag_items[] = {
652                 {PNL_DEFAULT_CLOSED, "DEFAULT_CLOSED", 0, "Default Closed",
653                                      "Defines if the panel has to be open or collapsed at the time of its creation"},
654                 {PNL_NO_HEADER, "HIDE_HEADER", 0, "Show Header",
655                                 "If set to True, the panel shows a header, which contains a clickable "
656                                 "arrow to collapse the panel and the label (see bl_label)"},
657                 {0, NULL, 0, NULL, NULL}
658         };
659         
660         srna = RNA_def_struct(brna, "Panel", NULL);
661         RNA_def_struct_ui_text(srna, "Panel", "Panel containing UI elements");
662         RNA_def_struct_sdna(srna, "Panel");
663         RNA_def_struct_refine_func(srna, "rna_Panel_refine");
664         RNA_def_struct_register_funcs(srna, "rna_Panel_register", "rna_Panel_unregister", NULL);
665
666         /* poll */
667         func = RNA_def_function(srna, "poll", NULL);
668         RNA_def_function_ui_description(func, "If this method returns a non-null output, then the panel can be drawn");
669         RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
670         RNA_def_function_return(func, RNA_def_boolean(func, "visible", 1, "", ""));
671         parm = RNA_def_pointer(func, "context", "Context", "", "");
672         RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
673
674         /* draw */
675         func = RNA_def_function(srna, "draw", NULL);
676         RNA_def_function_ui_description(func, "Draw UI elements into the panel UI layout");
677         RNA_def_function_flag(func, FUNC_REGISTER);
678         parm = RNA_def_pointer(func, "context", "Context", "", "");
679         RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
680
681         func = RNA_def_function(srna, "draw_header", NULL);
682         RNA_def_function_ui_description(func, "Draw UI elements into the panel's header UI layout");
683         RNA_def_function_flag(func, FUNC_REGISTER);
684         parm = RNA_def_pointer(func, "context", "Context", "", "");
685         RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
686
687         prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
688         RNA_def_property_struct_type(prop, "UILayout");
689         RNA_def_property_ui_text(prop, "Layout", "Defines the structure of the panel in the UI");
690         
691         prop = RNA_def_property(srna, "text", PROP_STRING, PROP_NONE);
692         RNA_def_property_string_sdna(prop, NULL, "drawname");
693         RNA_def_property_ui_text(prop, "Text", "XXX todo");
694         
695         /* registration */
696         prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
697         RNA_def_property_string_sdna(prop, NULL, "type->idname");
698         RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
699         RNA_def_property_ui_text(prop, "ID Name",
700                                  "If this is set, the panel gets a custom ID, otherwise it takes the "
701                                  "name of the class used to define the panel. For example, if the "
702                                  "class name is \"OBJECT_PT_hello\", and bl_idname is not set by the "
703                                  "script, then bl_idname = \"OBJECT_PT_hello\"");
704
705         /* panel's label indeed doesn't need PROP_TRANSLATE flag: translation of label happens in runtime
706          * when drawing panel and having this flag set will make runtime switching of language much more tricky
707          * because label will be stored translated */
708         prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
709         RNA_def_property_string_sdna(prop, NULL, "type->label");
710         RNA_def_property_flag(prop, PROP_REGISTER);
711         RNA_def_property_ui_text(prop, "Label",
712                                  "The panel label, shows up in the panel header at the right of the "
713                                  "triangle used to collapse the panel");
714         
715         prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE);
716         RNA_def_property_enum_sdna(prop, NULL, "type->space_type");
717         RNA_def_property_enum_items(prop, space_type_items);
718         RNA_def_property_flag(prop, PROP_REGISTER);
719         RNA_def_property_ui_text(prop, "Space type", "The space where the panel is going to be used in");
720         
721         prop = RNA_def_property(srna, "bl_region_type", PROP_ENUM, PROP_NONE);
722         RNA_def_property_enum_sdna(prop, NULL, "type->region_type");
723         RNA_def_property_enum_items(prop, region_type_items);
724         RNA_def_property_flag(prop, PROP_REGISTER);
725         RNA_def_property_ui_text(prop, "Region Type", "The region where the panel is going to be used in");
726
727         prop = RNA_def_property(srna, "bl_context", PROP_STRING, PROP_NONE);
728         RNA_def_property_string_sdna(prop, NULL, "type->context");
729         RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); /* Only used in Properties Editor and 3D View - Thomas */
730         RNA_def_property_ui_text(prop, "Context",
731                                  "The context in which the panel belongs to. (TODO: explain the "
732                                  "possible combinations bl_context/bl_region_type/bl_space_type)");
733         
734         prop = RNA_def_property(srna, "bl_options", PROP_ENUM, PROP_NONE);
735         RNA_def_property_enum_sdna(prop, NULL, "type->flag");
736         RNA_def_property_enum_items(prop, panel_flag_items);
737         RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL | PROP_ENUM_FLAG);
738         RNA_def_property_ui_text(prop, "Options",  "Options for this panel type");
739 }
740
741 static void rna_def_header(BlenderRNA *brna)
742 {
743         StructRNA *srna;
744         PropertyRNA *prop;
745         PropertyRNA *parm;
746         FunctionRNA *func;
747         
748         srna = RNA_def_struct(brna, "Header", NULL);
749         RNA_def_struct_ui_text(srna, "Header", "Editor header containing UI elements");
750         RNA_def_struct_sdna(srna, "Header");
751         RNA_def_struct_refine_func(srna, "rna_Header_refine");
752         RNA_def_struct_register_funcs(srna, "rna_Header_register", "rna_Header_unregister", NULL);
753
754         /* draw */
755         func = RNA_def_function(srna, "draw", NULL);
756         RNA_def_function_ui_description(func, "Draw UI elements into the header UI layout");
757         RNA_def_function_flag(func, FUNC_REGISTER);
758         parm = RNA_def_pointer(func, "context", "Context", "", "");
759         RNA_def_property_flag(parm, PROP_REQUIRED);
760
761         RNA_define_verify_sdna(0); /* not in sdna */
762
763         prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
764         RNA_def_property_pointer_sdna(prop, NULL, "layout");
765         RNA_def_property_struct_type(prop, "UILayout");
766         RNA_def_property_ui_text(prop, "Layout", "Structure of the header in the UI");
767
768         /* registration */
769         prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
770         RNA_def_property_string_sdna(prop, NULL, "type->idname");
771         RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
772         RNA_def_property_ui_text(prop, "ID Name",
773                                  "If this is set, the header gets a custom ID, otherwise it takes the "
774                                  "name of the class used to define the panel; for example, if the "
775                                  "class name is \"OBJECT_HT_hello\", and bl_idname is not set by the "
776                                  "script, then bl_idname = \"OBJECT_HT_hello\"");
777
778         prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE);
779         RNA_def_property_enum_sdna(prop, NULL, "type->space_type");
780         RNA_def_property_enum_items(prop, space_type_items);
781         RNA_def_property_flag(prop, PROP_REGISTER);
782         RNA_def_property_ui_text(prop, "Space type", "The space where the header is going to be used in");
783
784         RNA_define_verify_sdna(1);
785 }
786
787 static void rna_def_menu(BlenderRNA *brna)
788 {
789         StructRNA *srna;
790         PropertyRNA *prop;
791         PropertyRNA *parm;
792         FunctionRNA *func;
793         
794         srna = RNA_def_struct(brna, "Menu", NULL);
795         RNA_def_struct_ui_text(srna, "Menu", "Editor menu containing buttons");
796         RNA_def_struct_sdna(srna, "Menu");
797         RNA_def_struct_refine_func(srna, "rna_Menu_refine");
798         RNA_def_struct_register_funcs(srna, "rna_Menu_register", "rna_Menu_unregister", NULL);
799
800         /* poll */
801         func = RNA_def_function(srna, "poll", NULL);
802         RNA_def_function_ui_description(func, "If this method returns a non-null output, then the menu can be drawn");
803         RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
804         RNA_def_function_return(func, RNA_def_boolean(func, "visible", 1, "", ""));
805         parm = RNA_def_pointer(func, "context", "Context", "", "");
806         RNA_def_property_flag(parm, PROP_REQUIRED);
807
808         /* draw */
809         func = RNA_def_function(srna, "draw", NULL);
810         RNA_def_function_ui_description(func, "Draw UI elements into the menu UI layout");
811         RNA_def_function_flag(func, FUNC_REGISTER);
812         parm = RNA_def_pointer(func, "context", "Context", "", "");
813         RNA_def_property_flag(parm, PROP_REQUIRED);
814
815         RNA_define_verify_sdna(0); /* not in sdna */
816
817         prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
818         RNA_def_property_pointer_sdna(prop, NULL, "layout");
819         RNA_def_property_struct_type(prop, "UILayout");
820         RNA_def_property_ui_text(prop, "Layout", "Defines the structure of the menu in the UI");
821
822         /* registration */
823         prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
824         RNA_def_property_string_sdna(prop, NULL, "type->idname");
825         RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
826         RNA_def_property_ui_text(prop, "ID Name",
827                                  "If this is set, the menu gets a custom ID, otherwise it takes the "
828                                  "name of the class used to define the menu (for example, if the "
829                                  "class name is \"OBJECT_MT_hello\", and bl_idname is not set by the "
830                                  "script, then bl_idname = \"OBJECT_MT_hello\")");
831
832         /* menu's label indeed doesn't need PROP_TRANSLATE flag: translation of label happens in runtime
833          * when drawing panel and having this flag set will make runtime switching of language much more tricky
834          * because label will be stored translated */
835         prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
836         RNA_def_property_string_sdna(prop, NULL, "type->label");
837         RNA_def_property_flag(prop, PROP_REGISTER);
838         RNA_def_property_ui_text(prop, "Label", "The menu label");
839
840         prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_TRANSLATE);
841         RNA_def_property_string_sdna(prop, NULL, "type->description");
842         RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */
843         RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Menu_bl_description_set");
844         /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
845         RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
846         RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */
847
848         RNA_define_verify_sdna(1);
849 }
850
851 void RNA_def_ui(BlenderRNA *brna)
852 {
853         rna_def_ui_layout(brna);
854         rna_def_panel(brna);
855         rna_def_header(brna);
856         rna_def_menu(brna);
857 }
858
859 #endif /* RNA_RUNTIME */
860