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