2.5: Physics Buttons
[blender.git] / source / blender / editors / interface / interface_layout.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * Contributor(s): Blender Foundation 2009.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 #include <limits.h>
26 #include <math.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "MEM_guardedalloc.h"
31
32 #include "DNA_ID.h"
33 #include "DNA_scene_types.h"
34 #include "DNA_screen_types.h"
35 #include "DNA_userdef_types.h"
36 #include "DNA_windowmanager_types.h"
37
38 #include "BLI_listbase.h"
39 #include "BLI_string.h"
40
41 #include "BKE_context.h"
42 #include "BKE_global.h"
43 #include "BKE_idprop.h"
44 #include "BKE_library.h"
45 #include "BKE_screen.h"
46 #include "BKE_utildefines.h"
47
48 #include "RNA_access.h"
49
50 #include "UI_interface.h"
51 #include "UI_resources.h"
52 #include "UI_view2d.h"
53
54 #include "ED_util.h"
55 #include "ED_types.h"
56 #include "ED_screen.h"
57
58 #include "WM_api.h"
59 #include "WM_types.h"
60
61 #include "interface_intern.h"
62
63 /************************ Structs and Defines *************************/
64
65 #define RNA_NO_INDEX    -1
66 #define RNA_ENUM_VALUE  -2
67
68 #define EM_SEPR_X               6
69 #define EM_SEPR_Y               6
70
71 /* uiLayoutRoot */
72
73 typedef struct uiLayoutRoot {
74         struct uiLayoutRoot *next, *prev;
75
76         int type;
77         int opcontext;
78
79         int emw, emh;
80
81         uiMenuHandleFunc handlefunc;
82         void *argv;
83
84         uiStyle *style;
85         uiBlock *block;
86         uiLayout *layout;
87 } uiLayoutRoot;
88
89 /* Item */
90
91 typedef enum uiItemType {
92         ITEM_BUTTON,
93
94         ITEM_LAYOUT_ROW,
95         ITEM_LAYOUT_COLUMN,
96         ITEM_LAYOUT_COLUMN_FLOW,
97         ITEM_LAYOUT_ROW_FLOW,
98         ITEM_LAYOUT_BOX,
99         ITEM_LAYOUT_FREE,
100         ITEM_LAYOUT_SPLIT,
101
102         ITEM_LAYOUT_ROOT
103 #if 0
104         TEMPLATE_COLUMN_FLOW,
105         TEMPLATE_SPLIT,
106         TEMPLATE_BOX,
107
108         TEMPLATE_HEADER,
109         TEMPLATE_HEADER_ID
110 #endif
111 } uiItemType;
112
113 typedef struct uiItem {
114         void *next, *prev;
115         uiItemType type;
116         int flag;
117 } uiItem;
118
119 typedef struct uiButtonItem {
120         uiItem item;
121         uiBut *but;
122 } uiButtonItem;
123
124 struct uiLayout {
125         uiItem item;
126
127         uiLayoutRoot *root;
128         bContextStore *context;
129         ListBase items;
130
131         int x, y, w, h;
132         float scale[2];
133         short space;
134         char align;
135         char active;
136         char enabled;
137         char redalert;
138         char keepaspect;
139         char alignment;
140 };
141
142 typedef struct uiLayoutItemFlow {
143         uiLayout litem;
144         int number;
145         int totcol;
146 } uiLayoutItemFlow;
147
148 typedef struct uiLayoutItemBx {
149         uiLayout litem;
150         uiBut *roundbox;
151 } uiLayoutItemBx;
152
153 typedef struct uiLayoutItemSplt {
154         uiLayout litem;
155         float percentage;
156 } uiLayoutItemSplt;
157
158 typedef struct uiLayoutItemRoot {
159         uiLayout litem;
160 } uiLayoutItemRoot;
161
162 /************************** Item ***************************/
163
164 static char *ui_item_name_add_colon(char *name, char namestr[UI_MAX_NAME_STR])
165 {
166         int len= strlen(name);
167
168         if(len != 0 && len+1 < UI_MAX_NAME_STR) {
169                 BLI_strncpy(namestr, name, UI_MAX_NAME_STR);
170                 namestr[len]= ':';
171                 namestr[len+1]= '\0';
172                 return namestr;
173         }
174
175         return name;
176 }
177
178 static int ui_item_fit(int item, int pos, int all, int available, int last, int alignment, int *offset)
179 {
180         /* available == 0 is unlimited */
181         if(available == 0)
182                 return item;
183         
184         if(offset)
185                 *offset= 0;
186         
187         if(all > available) {
188                 /* contents is bigger than available space */
189                 if(last)
190                         return available-pos;
191                 else
192                         return (item*available)/all;
193         }
194         else {
195                 /* contents is smaller or equal to available space */
196                 if(alignment == UI_LAYOUT_ALIGN_EXPAND) {
197                         if(last)
198                                 return available-pos;
199                         else
200                                 return (item*available)/all;
201                 }
202                 else
203                         return item;
204         }
205 }
206
207 /* variable button size in which direction? */
208 #define UI_ITEM_VARY_X  1
209 #define UI_ITEM_VARY_Y  2
210
211 static int ui_layout_vary_direction(uiLayout *layout)
212 {
213         return (layout->root->type == UI_LAYOUT_HEADER || layout->alignment != UI_LAYOUT_ALIGN_EXPAND)? UI_ITEM_VARY_X: UI_ITEM_VARY_Y;
214 }
215
216 /* estimated size of text + icon */
217 static int ui_text_icon_width(uiLayout *layout, char *name, int icon)
218 {
219         int variable = ui_layout_vary_direction(layout) == UI_ITEM_VARY_X;
220
221         if(icon && strcmp(name, "") == 0)
222                 return UI_UNIT_X; /* icon only */
223         else if(icon)
224                 return (variable)? UI_GetStringWidth(name) + 4 + UI_UNIT_X: 10*UI_UNIT_X; /* icon + text */
225         else
226                 return (variable)? UI_GetStringWidth(name) + 4 + UI_UNIT_X: 10*UI_UNIT_X; /* text only */
227 }
228
229 static void ui_item_size(uiItem *item, int *r_w, int *r_h)
230 {
231         if(item->type == ITEM_BUTTON) {
232                 uiButtonItem *bitem= (uiButtonItem*)item;
233
234                 if(r_w) *r_w= bitem->but->x2 - bitem->but->x1;
235                 if(r_h) *r_h= bitem->but->y2 - bitem->but->y1;
236         }
237         else {
238                 uiLayout *litem= (uiLayout*)item;
239
240                 if(r_w) *r_w= litem->w;
241                 if(r_h) *r_h= litem->h;
242         }
243 }
244
245 static void ui_item_offset(uiItem *item, int *r_x, int *r_y)
246 {
247         if(item->type == ITEM_BUTTON) {
248                 uiButtonItem *bitem= (uiButtonItem*)item;
249
250                 if(r_x) *r_x= bitem->but->x1;
251                 if(r_y) *r_y= bitem->but->y1;
252         }
253         else {
254                 if(r_x) *r_x= 0;
255                 if(r_y) *r_y= 0;
256         }
257 }
258
259 static void ui_item_position(uiItem *item, int x, int y, int w, int h)
260 {
261         if(item->type == ITEM_BUTTON) {
262                 uiButtonItem *bitem= (uiButtonItem*)item;
263
264                 bitem->but->x1= x;
265                 bitem->but->y1= y;
266                 bitem->but->x2= x+w;
267                 bitem->but->y2= y+h;
268                 
269                 ui_check_but(bitem->but); /* for strlen */
270         }
271         else {
272                 uiLayout *litem= (uiLayout*)item;
273
274                 litem->x= x;
275                 litem->y= y+h;
276                 litem->w= w;
277                 litem->h= h;
278         }
279 }
280
281 /******************** Special RNA Items *********************/
282
283 static int ui_layout_local_dir(uiLayout *layout)
284 {
285         switch(layout->item.type) {
286                 case ITEM_LAYOUT_ROW:
287                 case ITEM_LAYOUT_ROOT:
288                         return UI_LAYOUT_HORIZONTAL;
289                 case ITEM_LAYOUT_COLUMN:
290                 case ITEM_LAYOUT_COLUMN_FLOW:
291                 case ITEM_LAYOUT_SPLIT:
292                 case ITEM_LAYOUT_FREE:
293                 case ITEM_LAYOUT_BOX:
294                 default:
295                         return UI_LAYOUT_VERTICAL;
296         }
297 }
298
299 static uiLayout *ui_item_local_sublayout(uiLayout *test, uiLayout *layout, int align)
300 {
301         uiLayout *sub;
302
303         if(ui_layout_local_dir(test) == UI_LAYOUT_HORIZONTAL)
304                 sub= uiLayoutRow(layout, align);
305         else
306                 sub= uiLayoutColumn(layout, align);
307         
308         sub->space= 0;
309         return sub;
310 }
311
312 /* create buttons for an item with an RNA array */
313 static void ui_item_array(uiLayout *layout, uiBlock *block, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int len, int x, int y, int w, int h, int expand, int slider)
314 {
315         uiStyle *style= layout->root->style;
316         uiBut *but;
317         PropertyType type;
318         PropertySubType subtype;
319         uiLayout *sub;
320         int a;
321
322         /* retrieve type and subtype */
323         type= RNA_property_type(prop);
324         subtype= RNA_property_subtype(prop);
325
326         sub= ui_item_local_sublayout(layout, layout, 1);
327         uiBlockSetCurLayout(block, sub);
328
329         /* create label */
330         if(strcmp(name, "") != 0)
331                 uiDefBut(block, LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
332
333         /* create buttons */
334         if(type == PROP_BOOLEAN && len == 20) {
335                 /* special check for layer layout */
336                 int butw, buth, unit;
337
338                 uiBlockSetCurLayout(block, uiLayoutFree(layout, 0));
339
340                 unit= UI_UNIT_X*0.75;
341                 butw= unit;
342                 buth= unit;
343
344                 uiBlockBeginAlign(block);
345                 for(a=0; a<5; a++)
346                         uiDefAutoButR(block, ptr, prop, a, "", ICON_BLANK1, x + butw*a, y+buth, butw, buth);
347                 for(a=0; a<5; a++)
348                         uiDefAutoButR(block, ptr, prop, a+10, "", ICON_BLANK1, x + butw*a, y, butw, buth);
349                 uiBlockEndAlign(block);
350
351                 x += 5*butw + style->buttonspacex;
352
353                 uiBlockBeginAlign(block);
354                 for(a=0; a<5; a++)
355                         uiDefAutoButR(block, ptr, prop, a+5, "", ICON_BLANK1, x + butw*a, y+buth, butw, buth);
356                 for(a=0; a<5; a++)
357                         uiDefAutoButR(block, ptr, prop, a+15, "", ICON_BLANK1, x + butw*a, y, butw, buth);
358                 uiBlockEndAlign(block);
359         }
360         else if(subtype == PROP_MATRIX) {
361                 /* matrix layout */
362                 int row, col;
363
364                 uiBlockSetCurLayout(block, uiLayoutFree(layout, 1));
365
366                 len= ceil(sqrt(len));
367
368                 h /= len;
369                 w /= len;
370
371                 // XXX test
372                 for(a=0; a<len; a++) {
373                         col= a%len;
374                         row= a/len;
375
376                         but= uiDefAutoButR(block, ptr, prop, a, "", 0, x + w*col, y+(row-a-1)*UI_UNIT_Y, w, UI_UNIT_Y);
377                         if(slider && but->type==NUM)
378                                 but->type= NUMSLI;
379                 }
380         }
381         else if(len <= 4 && ELEM3(subtype, PROP_ROTATION, PROP_VECTOR, PROP_COLOR)) {
382                 if(subtype == PROP_COLOR)
383                         uiDefAutoButR(block, ptr, prop, -1, "", 0, 0, 0, w, UI_UNIT_Y);
384
385                 if(subtype != PROP_COLOR || expand) {
386                         /* layout for known array subtypes */
387                         static char vectoritem[4]= {'X', 'Y', 'Z', 'W'};
388                         static char quatitem[4]= {'W', 'X', 'Y', 'Z'};
389                         static char coloritem[4]= {'R', 'G', 'B', 'A'};
390                         char str[3];
391
392                         for(a=0; a<len; a++) {
393                                 if(len == 4 && subtype == PROP_ROTATION)
394                                         str[0]= quatitem[a];
395                                 else if(subtype == PROP_VECTOR || subtype == PROP_ROTATION)
396                                         str[0]= vectoritem[a];
397                                 else
398                                         str[0]= coloritem[a];
399
400                                 if(type == PROP_BOOLEAN) {
401                                         str[1]= '\0';
402                                 }
403                                 else {
404                                         str[1]= ':';
405                                         str[2]= '\0';
406                                 }
407
408                                 but= uiDefAutoButR(block, ptr, prop, a, str, 0, 0, 0, w, UI_UNIT_Y);
409                                 if(slider && but->type==NUM)
410                                         but->type= NUMSLI;
411                         }
412                 }
413                 else if(subtype == PROP_COLOR && len == 4) {
414                         but= uiDefAutoButR(block, ptr, prop, 3, "A:", 0, 0, 0, w, UI_UNIT_Y);
415                         if(slider && but->type==NUM)
416                                 but->type= NUMSLI;
417                 }
418         }
419         else {
420                 for(a=0; a<len; a++) {
421                         but= uiDefAutoButR(block, ptr, prop, a, "", 0, 0, 0, w, UI_UNIT_Y);
422                         if(slider && but->type==NUM)
423                                 but->type= NUMSLI;
424                 }
425         }
426
427         uiBlockSetCurLayout(block, layout);
428 }
429
430 static void ui_item_enum_row(uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, char *uiname, int x, int y, int w, int h)
431 {
432         const EnumPropertyItem *item;
433         const char *identifier;
434         char *name;
435         int a, totitem, itemw, icon, value;
436
437         identifier= RNA_property_identifier(prop);
438         RNA_property_enum_items(ptr, prop, &item, &totitem);
439
440         uiBlockSetCurLayout(block, ui_item_local_sublayout(layout, layout, 1));
441         for(a=0; a<totitem; a++) {
442                 name= (!uiname || uiname[0])? (char*)item[a].name: "";
443                 icon= item[a].icon;
444                 value= item[a].value;
445                 itemw= ui_text_icon_width(block->curlayout, name, icon);
446
447                 if(icon && strcmp(name, "") != 0)
448                         uiDefIconTextButR(block, ROW, 0, icon, name, 0, 0, itemw, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
449                 else if(icon)
450                         uiDefIconButR(block, ROW, 0, icon, 0, 0, itemw, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
451                 else
452                         uiDefButR(block, ROW, 0, name, 0, 0, itemw, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
453         }
454         uiBlockSetCurLayout(block, layout);
455 }
456
457 /* create label + button for RNA property */
458 static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int x, int y, int w, int h)
459 {
460         uiLayout *sub;
461         uiBut *but;
462         PropertySubType subtype;
463
464         sub= uiLayoutRow(layout, 0);
465         uiBlockSetCurLayout(block, sub);
466
467         if(strcmp(name, "") != 0) {
468                 w= w/2;
469                 uiDefBut(block, LABEL, 0, name, x, y, w, h, NULL, 0.0, 0.0, 0, 0, "");
470         }
471
472         subtype= RNA_property_subtype(prop);
473
474         if(subtype == PROP_FILEPATH || subtype == PROP_DIRPATH) {
475                 uiBlockSetCurLayout(block, uiLayoutRow(sub, 1));
476                 uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w-UI_UNIT_X, h);
477                 but= uiDefIconBut(block, BUT, 0, ICON_FILESEL, x, y, UI_UNIT_X, h, NULL, 0.0f, 0.0f, 0.0f, 0.0f, "DUMMY file select button"); /* XXX */
478         }
479         else
480                 but= uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w, h);
481
482         uiBlockSetCurLayout(block, layout);
483         return but;
484 }
485
486 /********************* Button Items *************************/
487
488 /* disabled item */
489 static void ui_item_disabled(uiLayout *layout, char *name)
490 {
491         uiBlock *block= layout->root->block;
492         uiBut *but;
493         int w;
494
495         uiBlockSetCurLayout(block, layout);
496
497         if(!name)
498                 name= "";
499
500         w= ui_text_icon_width(layout, name, 0);
501
502         but= uiDefBut(block, LABEL, 0, (char*)name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
503         but->flag |= UI_BUT_DISABLED;
504         but->lock = 1;
505         but->lockstr = "";
506 }
507
508 /* operator items */
509 void uiItemFullO(uiLayout *layout, char *name, int icon, char *idname, IDProperty *properties, int context)
510 {
511         uiBlock *block= layout->root->block;
512         wmOperatorType *ot= WM_operatortype_find(idname);
513         uiBut *but;
514         int w;
515
516         if(!ot) {
517                 ui_item_disabled(layout, idname);
518                 return;
519         }
520
521         if(!name)
522                 name= ot->name;
523         if(layout->root->type == UI_LAYOUT_MENU && !icon)
524                 icon= ICON_BLANK1;
525
526         /* create button */
527         uiBlockSetCurLayout(block, layout);
528
529         w= ui_text_icon_width(layout, name, icon);
530
531         if(icon && strcmp(name, "") != 0)
532                 but= uiDefIconTextButO(block, BUT, ot->idname, context, icon, (char*)name, 0, 0, w, UI_UNIT_Y, NULL);
533         else if(icon)
534                 but= uiDefIconButO(block, BUT, ot->idname, context, icon, 0, 0, w, UI_UNIT_Y, NULL);
535         else
536                 but= uiDefButO(block, BUT, ot->idname, context, (char*)name, 0, 0, w, UI_UNIT_Y, NULL);
537
538         /* assign properties */
539         if(properties) {
540                 PointerRNA *opptr= uiButGetOperatorPtrRNA(but);
541                 opptr->data= properties;
542         }
543 }
544
545 static char *ui_menu_enumpropname(char *opname, char *propname, int retval)
546 {
547         wmOperatorType *ot= WM_operatortype_find(opname);
548         PointerRNA ptr;
549         PropertyRNA *prop;
550
551         if(!ot || !ot->srna)
552                 return "";
553
554         RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
555         prop= RNA_struct_find_property(&ptr, propname);
556
557         if(prop) {
558                 const EnumPropertyItem *item;
559                 int totitem, i;
560
561                 RNA_property_enum_items(&ptr, prop, &item, &totitem);
562
563                 for (i=0; i<totitem; i++) {
564                         if(item[i].value==retval)
565                                 return (char*)item[i].name;
566                 }
567         }
568
569         return "";
570 }
571
572 void uiItemEnumO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
573 {
574         PointerRNA ptr;
575
576         WM_operator_properties_create(&ptr, opname);
577         RNA_enum_set(&ptr, propname, value);
578
579         if(!name)
580                 name= ui_menu_enumpropname(opname, propname, value);
581
582         uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
583 }
584
585 void uiItemsEnumO(uiLayout *layout, char *opname, char *propname)
586 {
587         wmOperatorType *ot= WM_operatortype_find(opname);
588         PointerRNA ptr;
589         PropertyRNA *prop;
590
591         if(!ot || !ot->srna) {
592                 ui_item_disabled(layout, opname);
593                 return;
594         }
595
596         RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
597         prop= RNA_struct_find_property(&ptr, propname);
598
599         if(prop && RNA_property_type(prop) == PROP_ENUM) {
600                 const EnumPropertyItem *item;
601                 int totitem, i;
602
603                 RNA_property_enum_items(&ptr, prop, &item, &totitem);
604
605                 for(i=0; i<totitem; i++)
606                         uiItemEnumO(layout, (char*)item[i].name, item[i].icon, opname, propname, item[i].value);
607         }
608 }
609
610 /* for use in cases where we have */
611 void uiItemEnumO_string(uiLayout *layout, char *name, int icon, char *opname, char *propname, char *value_str)
612 {
613         PointerRNA ptr;
614         
615         /* for getting the enum */
616         PropertyRNA *prop;
617         const EnumPropertyItem *item;
618         int value;
619
620         WM_operator_properties_create(&ptr, opname);
621         
622         /* enum lookup */
623         if((prop= RNA_struct_find_property(&ptr, propname))) {
624                 RNA_property_enum_items(&ptr, prop, &item, NULL);
625                 if(RNA_enum_value_from_id(item, value_str, &value)==0) {
626                         printf("uiItemEnumO_string: %s.%s, enum %s not found.\n", RNA_struct_identifier(ptr.type), propname, value_str);
627                         return;
628                 }
629         }
630         else {
631                 printf("uiItemEnumO_string: %s.%s not found.\n", RNA_struct_identifier(ptr.type), propname);
632                 return;
633         }
634         
635         RNA_property_enum_set(&ptr, prop, value);
636         
637         /* same as uiItemEnumO */
638         if(!name)
639                 name= ui_menu_enumpropname(opname, propname, value);
640
641         uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
642 }
643
644 void uiItemBooleanO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
645 {
646         PointerRNA ptr;
647
648         WM_operator_properties_create(&ptr, opname);
649         RNA_boolean_set(&ptr, propname, value);
650
651         uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
652 }
653
654 void uiItemIntO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
655 {
656         PointerRNA ptr;
657
658         WM_operator_properties_create(&ptr, opname);
659         RNA_int_set(&ptr, propname, value);
660
661         uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
662 }
663
664 void uiItemFloatO(uiLayout *layout, char *name, int icon, char *opname, char *propname, float value)
665 {
666         PointerRNA ptr;
667
668         WM_operator_properties_create(&ptr, opname);
669         RNA_float_set(&ptr, propname, value);
670
671         uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
672 }
673
674 void uiItemStringO(uiLayout *layout, char *name, int icon, char *opname, char *propname, char *value)
675 {
676         PointerRNA ptr;
677
678         WM_operator_properties_create(&ptr, opname);
679         RNA_string_set(&ptr, propname, value);
680
681         uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
682 }
683
684 void uiItemO(uiLayout *layout, char *name, int icon, char *opname)
685 {
686         uiItemFullO(layout, name, icon, opname, NULL, layout->root->opcontext);
687 }
688
689 /* RNA property items */
690
691 static void ui_item_rna_size(uiLayout *layout, char *name, int icon, PropertyRNA *prop, int index, int *r_w, int *r_h)
692 {
693         PropertyType type;
694         PropertySubType subtype;
695         int len, w, h;
696
697         /* arbitrary extended width by type */
698         type= RNA_property_type(prop);
699         subtype= RNA_property_subtype(prop);
700         len= RNA_property_array_length(prop);
701
702         if(type == PROP_STRING && strcmp(name, "") == 0)
703                 name= "non-empty";
704
705         w= ui_text_icon_width(layout, name, icon);
706         h= UI_UNIT_Y;
707
708         /* increase height for arrays */
709         if(index == RNA_NO_INDEX && len > 0) {
710                 if(strcmp(name, "") == 0 && icon == 0)
711                         h= 0;
712
713                 if(type == PROP_BOOLEAN && len == 20)
714                         h += 2*UI_UNIT_Y;
715                 else if(subtype == PROP_MATRIX)
716                         h += ceil(sqrt(len))*UI_UNIT_Y;
717                 else
718                         h += len*UI_UNIT_Y;
719         }
720         else if(ui_layout_vary_direction(layout) == UI_ITEM_VARY_X) {
721                 if(type == PROP_BOOLEAN && strcmp(name, "") != 0)
722                         w += UI_UNIT_X;
723                 else if(type == PROP_ENUM)
724                         w += UI_UNIT_X/2;
725         }
726
727         *r_w= w;
728         *r_h= h;
729 }
730
731 void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int value, int expand, int slider, int toggle)
732 {
733         uiBlock *block= layout->root->block;
734         uiBut *but;
735         PropertyType type;
736         char namestr[UI_MAX_NAME_STR];
737         int len, w, h;
738
739         if(!ptr->data || !prop)
740                 return;
741
742         uiBlockSetCurLayout(block, layout);
743
744         /* retrieve info */
745         type= RNA_property_type(prop);
746         len= RNA_property_array_length(prop);
747
748         /* set name and icon */
749         if(!name)
750                 name= (char*)RNA_property_ui_name(prop);
751         if(!icon)
752                 icon= RNA_property_ui_icon(prop);
753
754         if(ELEM4(type, PROP_INT, PROP_FLOAT, PROP_STRING, PROP_POINTER))
755                 name= ui_item_name_add_colon(name, namestr);
756         else if(type == PROP_BOOLEAN && len)
757                 name= ui_item_name_add_colon(name, namestr);
758         else if(type == PROP_ENUM && index != RNA_ENUM_VALUE)
759                 name= ui_item_name_add_colon(name, namestr);
760
761         if(layout->root->type == UI_LAYOUT_MENU) {
762                 if(type == PROP_BOOLEAN)
763                         icon= (RNA_property_boolean_get(ptr, prop))? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT;
764                 else if(type == PROP_ENUM && index == RNA_ENUM_VALUE)
765                         icon= (RNA_property_enum_get(ptr, prop) == value)? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT; 
766         }
767
768         /* get size */
769         ui_item_rna_size(layout, name, icon, prop, index, &w, &h);
770
771         /* array property */
772         if(index == RNA_NO_INDEX && len > 0)
773                 ui_item_array(layout, block, name, icon, ptr, prop, len, 0, 0, w, h, expand, slider);
774         /* enum item */
775         else if(type == PROP_ENUM && index == RNA_ENUM_VALUE) {
776                 char *identifier= (char*)RNA_property_identifier(prop);
777
778                 if(icon && strcmp(name, "") != 0)
779                         uiDefIconTextButR(block, ROW, 0, icon, name, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
780                 else if(icon)
781                         uiDefIconButR(block, ROW, 0, icon, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
782                 else
783                         uiDefButR(block, ROW, 0, name, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
784         }
785         /* expanded enum */
786         else if(type == PROP_ENUM && expand)
787                 ui_item_enum_row(layout, block, ptr, prop, name, 0, 0, w, h);
788         /* property with separate label */
789         else if(type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER) {
790                 but= ui_item_with_label(layout, block, name, icon, ptr, prop, index, 0, 0, w, h);
791                 ui_but_add_search(but, ptr, prop, NULL, NULL);
792         }
793         /* single button */
794         else {
795                 but= uiDefAutoButR(block, ptr, prop, index, (char*)name, icon, 0, 0, w, h);
796
797                 if(slider && but->type==NUM)
798                         but->type= NUMSLI;
799
800                 if(toggle && but->type==OPTION)
801                         but->type= TOG;
802         }
803 }
804
805 void uiItemR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, char *propname, int expand, int slider, int toggle)
806 {
807         PropertyRNA *prop;
808
809         if(!ptr->data || !propname)
810                 return;
811
812         prop= RNA_struct_find_property(ptr, propname);
813
814         if(!prop) {
815                 ui_item_disabled(layout, propname);
816                 printf("uiItemR: property not found: %s\n", propname);
817                 return;
818         }
819
820         uiItemFullR(layout, name, icon, ptr, prop, RNA_NO_INDEX, 0, expand, slider, toggle);
821 }
822
823 void uiItemEnumR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, int value)
824 {
825         PropertyRNA *prop;
826
827         if(!ptr->data || !propname)
828                 return;
829
830         prop= RNA_struct_find_property(ptr, propname);
831
832         if(!prop || RNA_property_type(prop) != PROP_ENUM) {
833                 ui_item_disabled(layout, propname);
834                 printf("uiItemEnumR: enum property not found: %s\n", propname);
835                 return;
836         }
837
838         uiItemFullR(layout, name, icon, ptr, prop, RNA_ENUM_VALUE, value, 0, 0, 0);
839 }
840
841 void uiItemEnumR_string(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, char *value)
842 {
843         PropertyRNA *prop;
844         const EnumPropertyItem *item;
845         int ivalue, a;
846
847         if(!ptr->data || !propname)
848                 return;
849
850         prop= RNA_struct_find_property(ptr, propname);
851
852         if(!prop || RNA_property_type(prop) != PROP_ENUM) {
853                 ui_item_disabled(layout, propname);
854                 printf("uiItemEnumR: enum property not found: %s\n", propname);
855                 return;
856         }
857
858         RNA_property_enum_items(ptr, prop, &item, NULL);
859
860         if(!RNA_enum_value_from_id(item, value, &ivalue)) {
861                 ui_item_disabled(layout, propname);
862                 printf("uiItemEnumR: enum property value not found: %s\n", value);
863                 return;
864         }
865
866         for(a=0; item[a].identifier; a++) {
867                 if(item[a].value == ivalue) {
868                         uiItemFullR(layout, (char*)item[a].name, item[a].icon, ptr, prop, RNA_ENUM_VALUE, ivalue, 0, 0, 0);
869                         break;
870                 }
871         }
872 }
873
874 void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, char *propname)
875 {
876         PropertyRNA *prop;
877
878         prop= RNA_struct_find_property(ptr, propname);
879
880         if(!prop) {
881                 ui_item_disabled(layout, propname);
882                 return;
883         }
884
885         if(RNA_property_type(prop) == PROP_ENUM) {
886                 const EnumPropertyItem *item;
887                 int totitem, i;
888
889                 RNA_property_enum_items(ptr, prop, &item, &totitem);
890
891                 for(i=0; i<totitem; i++)
892                         uiItemEnumR(layout, (char*)item[i].name, 0, ptr, propname, item[i].value);
893         }
894 }
895
896 /* Pointer RNA button with search */
897
898 static void rna_search_cb(const struct bContext *C, void *arg_but, char *str, uiSearchItems *items)
899 {
900         Scene *scene= CTX_data_scene(C);
901         uiBut *but= arg_but;
902         char *name;
903         int i, iconid;
904
905         i = 0;
906         RNA_PROP_BEGIN(&but->rnasearchpoin, itemptr, but->rnasearchprop) {
907                 iconid= 0;
908                 if(RNA_struct_is_ID(itemptr.type))
909                         iconid= ui_id_icon_get(scene, itemptr.data);
910
911                 name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
912
913                 if(name) {
914                         if(BLI_strcasestr(name, str)) {
915                                 if(!uiSearchItemAdd(items, name, SET_INT_IN_POINTER(i), iconid)) {
916                                         MEM_freeN(name);
917                                         break;
918                                 }
919                         }
920
921                         MEM_freeN(name);
922                 }
923
924                 i++;
925         }
926         RNA_PROP_END;
927 }
928
929 static void search_id_collection(StructRNA *ptype, PointerRNA *ptr, PropertyRNA **prop)
930 {
931         StructRNA *srna;
932
933         /* look for collection property in Main */
934         RNA_main_pointer_create(G.main, ptr);
935
936         *prop= NULL;
937
938         RNA_STRUCT_BEGIN(ptr, iprop) {
939                 /* if it's a collection and has same pointer type, we've got it */
940                 if(RNA_property_type(iprop) == PROP_COLLECTION) {
941                         srna= RNA_property_pointer_type(ptr, iprop);
942
943                         if(ptype == srna) {
944                                 *prop= iprop;
945                                 break;
946                         }
947                 }
948         }
949         RNA_STRUCT_END;
950 }
951
952 void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop)
953 {
954         StructRNA *ptype;
955         PointerRNA sptr;
956
957         /* for ID's we do automatic lookup */
958         if(!searchprop) {
959                 if(RNA_property_type(prop) == PROP_POINTER) {
960                         ptype= RNA_property_pointer_type(ptr, prop);
961                         search_id_collection(ptype, &sptr, &searchprop);
962                         searchptr= &sptr;
963                 }
964         }
965
966         /* turn button into search button */
967         if(searchprop) {
968                 but->type= SEARCH_MENU;
969                 but->hardmax= MAX2(but->hardmax, 256);
970                 but->rnasearchpoin= *searchptr;
971                 but->rnasearchprop= searchprop;
972                 but->flag |= UI_ICON_LEFT|UI_TEXT_LEFT;
973
974                 uiButSetSearchFunc(but, rna_search_cb, but, NULL, NULL);
975         }
976 }
977
978 void uiItemPointerR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, struct PointerRNA *searchptr, char *searchpropname)
979 {
980         PropertyRNA *prop, *searchprop;
981         PropertyType type;
982         uiBut *but;
983         uiBlock *block;
984         StructRNA *icontype;
985         int w, h;
986         
987         /* validate arguments */
988         if(!ptr->data || !searchptr->data)
989                 return;
990
991         prop= RNA_struct_find_property(ptr, propname);
992
993         if(!prop) {
994                 printf("uiItemPointerR: property not found: %s\n", propname);
995                 return;
996         }
997         
998         type= RNA_property_type(prop);
999         if(!ELEM(type, PROP_POINTER, PROP_STRING)) {
1000                 printf("uiItemPointerR: property %s must be a pointer or string.\n", propname);
1001                 return;
1002         }
1003
1004         searchprop= RNA_struct_find_property(searchptr, searchpropname);
1005
1006         if(!searchprop || RNA_property_type(searchprop) != PROP_COLLECTION) {
1007                 printf("uiItemPointerR: search collection property not found: %s\n", searchpropname);
1008                 return;
1009         }
1010
1011         /* get icon & name */
1012         if(!icon) {
1013                 if(type == PROP_POINTER)
1014                         icontype= RNA_property_pointer_type(ptr, prop);
1015                 else
1016                         icontype= RNA_property_pointer_type(searchptr, searchprop);
1017
1018                 icon= RNA_struct_ui_icon(icontype);
1019         }
1020         if(!name)
1021                 name= (char*)RNA_property_ui_name(prop);
1022
1023         /* create button */
1024         block= uiLayoutGetBlock(layout);
1025
1026         ui_item_rna_size(layout, name, icon, prop, 0, &w, &h);
1027         but= ui_item_with_label(layout, block, name, icon, ptr, prop, 0, 0, 0, w, h);
1028
1029         ui_but_add_search(but, ptr, prop, searchptr, searchprop);
1030 }
1031
1032 /* menu item */
1033 static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt)
1034 {
1035         MenuType *mt= (MenuType*)arg_mt;
1036         Menu menu = {0};
1037
1038         menu.type= mt;
1039         menu.layout= layout;
1040         mt->draw(C, &menu);
1041 }
1042
1043 static void ui_item_menu(uiLayout *layout, char *name, int icon, uiMenuCreateFunc func, void *arg, void *argN)
1044 {
1045         uiBlock *block= layout->root->block;
1046         uiBut *but;
1047         int w, h;
1048
1049         uiBlockSetCurLayout(block, layout);
1050
1051         if(layout->root->type == UI_LAYOUT_HEADER)
1052                 uiBlockSetEmboss(block, UI_EMBOSS);
1053
1054         if(!name)
1055                 name= "";
1056         if(layout->root->type == UI_LAYOUT_MENU && !icon)
1057                 icon= ICON_BLANK1;
1058
1059         w= ui_text_icon_width(layout, name, icon);
1060         h= UI_UNIT_Y;
1061
1062         if(layout->root->type == UI_LAYOUT_HEADER) /* ugly .. */
1063                 w -= 10;
1064
1065         if(icon)
1066                 but= uiDefIconTextMenuBut(block, func, arg, icon, (char*)name, 0, 0, w, h, "");
1067         else
1068                 but= uiDefMenuBut(block, func, arg, (char*)name, 0, 0, w, h, "");
1069
1070         if(argN) { /* ugly .. */
1071                 but->poin= (char*)but;
1072                 but->func_argN= argN;
1073         }
1074
1075         if(layout->root->type == UI_LAYOUT_HEADER)
1076                 uiBlockSetEmboss(block, UI_EMBOSS);
1077         else if(layout->root->type == UI_LAYOUT_PANEL)
1078                 but->type= MENU;
1079 }
1080
1081 void uiItemM(uiLayout *layout, bContext *C, char *name, int icon, char *menuname)
1082 {
1083         ARegion *ar= CTX_wm_region(C);
1084         MenuType *mt;
1085
1086         if(!menuname)
1087                 return;
1088
1089         for(mt=ar->type->menutypes.first; mt; mt=mt->next) {
1090                 if(strcmp(menuname, mt->idname) == 0) {
1091                         if(!name)
1092                                 name= mt->label;
1093                         if(layout->root->type == UI_LAYOUT_MENU && !icon)
1094                                 icon= ICON_BLANK1;
1095                         ui_item_menu(layout, name, icon, ui_item_menutype_func, mt, NULL);
1096                         break;
1097                 }
1098         }
1099 }
1100
1101 /* label item */
1102 void uiItemL(uiLayout *layout, char *name, int icon)
1103 {
1104         uiBlock *block= layout->root->block;
1105         uiBut *but;
1106         int w;
1107
1108         uiBlockSetCurLayout(block, layout);
1109
1110         if(!name)
1111                 name= "";
1112         if(layout->root->type == UI_LAYOUT_MENU && !icon)
1113                 icon= ICON_BLANK1;
1114
1115         w= ui_text_icon_width(layout, name, icon);
1116
1117         if(icon && strcmp(name, "") != 0)
1118                 but= uiDefIconTextBut(block, LABEL, 0, icon, (char*)name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
1119         else if(icon)
1120                 but= uiDefIconBut(block, LABEL, 0, icon, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
1121         else
1122                 but= uiDefBut(block, LABEL, 0, (char*)name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
1123 }
1124
1125 /* value item */
1126 void uiItemV(uiLayout *layout, char *name, int icon, int argval)
1127 {
1128         /* label */
1129         uiBlock *block= layout->root->block;
1130         float *retvalue= (block->handle)? &block->handle->retvalue: NULL;
1131         int w;
1132
1133         uiBlockSetCurLayout(block, layout);
1134
1135         if(!name)
1136                 name= "";
1137         if(layout->root->type == UI_LAYOUT_MENU && !icon)
1138                 icon= ICON_BLANK1;
1139
1140         w= ui_text_icon_width(layout, name, icon);
1141
1142         if(icon && strcmp(name, "") != 0)
1143                 uiDefIconTextButF(block, BUTM, 0, icon, (char*)name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, argval, "");
1144         else if(icon)
1145                 uiDefIconButF(block, BUTM, 0, icon, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, argval, "");
1146         else
1147                 uiDefButF(block, BUTM, 0, (char*)name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, argval, "");
1148 }
1149
1150 /* separator item */
1151 void uiItemS(uiLayout *layout)
1152 {
1153         uiBlock *block= layout->root->block;
1154
1155         uiBlockSetCurLayout(block, layout);
1156         uiDefBut(block, SEPR, 0, "", 0, 0, EM_SEPR_X, EM_SEPR_Y, NULL, 0.0, 0.0, 0, 0, "");
1157 }
1158
1159 /* level items */
1160 void uiItemMenuF(uiLayout *layout, char *name, int icon, uiMenuCreateFunc func)
1161 {
1162         if(!func)
1163                 return;
1164
1165         ui_item_menu(layout, name, icon, func, NULL, NULL);
1166 }
1167
1168 typedef struct MenuItemLevel {
1169         int opcontext;
1170         char *opname;
1171         char *propname;
1172         PointerRNA rnapoin;
1173 } MenuItemLevel;
1174
1175 static void menu_item_enum_opname_menu(bContext *C, uiLayout *layout, void *arg)
1176 {
1177         MenuItemLevel *lvl= (MenuItemLevel*)(((uiBut*)arg)->func_argN);
1178
1179         uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
1180         uiItemsEnumO(layout, lvl->opname, lvl->propname);
1181 }
1182
1183 void uiItemMenuEnumO(uiLayout *layout, char *name, int icon, char *opname, char *propname)
1184 {
1185         wmOperatorType *ot= WM_operatortype_find(opname);
1186         MenuItemLevel *lvl;
1187
1188         if(!ot || !ot->srna) {
1189                 ui_item_disabled(layout, opname);
1190                 return;
1191         }
1192
1193         if(!name)
1194                 name= ot->name;
1195         if(layout->root->type == UI_LAYOUT_MENU && !icon)
1196                 icon= ICON_BLANK1;
1197
1198         lvl= MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
1199         lvl->opname= opname;
1200         lvl->propname= propname;
1201         lvl->opcontext= layout->root->opcontext;
1202
1203         ui_item_menu(layout, name, icon, menu_item_enum_opname_menu, NULL, lvl);
1204 }
1205
1206 static void menu_item_enum_rna_menu(bContext *C, uiLayout *layout, void *arg)
1207 {
1208         MenuItemLevel *lvl= (MenuItemLevel*)(((uiBut*)arg)->func_argN);
1209
1210         uiLayoutSetOperatorContext(layout, lvl->opcontext);
1211         uiItemsEnumR(layout, &lvl->rnapoin, lvl->propname);
1212 }
1213
1214 void uiItemMenuEnumR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname)
1215 {
1216         MenuItemLevel *lvl;
1217         PropertyRNA *prop;
1218
1219         prop= RNA_struct_find_property(ptr, propname);
1220         if(!prop) {
1221                 ui_item_disabled(layout, propname);
1222                 return;
1223         }
1224
1225         if(!name)
1226                 name= (char*)RNA_property_ui_name(prop);
1227         if(layout->root->type == UI_LAYOUT_MENU && !icon)
1228                 icon= ICON_BLANK1;
1229
1230         lvl= MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
1231         lvl->rnapoin= *ptr;
1232         lvl->propname= propname;
1233         lvl->opcontext= layout->root->opcontext;
1234
1235         ui_item_menu(layout, name, icon, menu_item_enum_rna_menu, NULL, lvl);
1236 }
1237
1238 /**************************** Layout Items ***************************/
1239
1240 /* single-row layout */
1241 static void ui_litem_estimate_row(uiLayout *litem)
1242 {
1243         uiItem *item;
1244         int itemw, itemh;
1245
1246         litem->w= 0;
1247         litem->h= 0;
1248
1249         for(item=litem->items.first; item; item=item->next) {
1250                 ui_item_size(item, &itemw, &itemh);
1251
1252                 litem->w += itemw;
1253                 litem->h= MAX2(itemh, litem->h);
1254
1255                 if(item->next)
1256                         litem->w += litem->space;
1257         }
1258 }
1259
1260 static int ui_litem_min_width(int itemw)
1261 {
1262         return MIN2(UI_UNIT_X, itemw);
1263 }
1264
1265 static void ui_litem_layout_row(uiLayout *litem)
1266 {
1267         uiItem *item;
1268         int x, y, w, tot, totw, neww, itemw, minw, itemh, offset;
1269         int fixedw, freew, fixedx, freex, flag= 0, lastw= 0;
1270
1271         x= litem->x;
1272         y= litem->y;
1273         w= litem->w;
1274         totw= 0;
1275         tot= 0;
1276
1277         for(item=litem->items.first; item; item=item->next) {
1278                 ui_item_size(item, &itemw, &itemh);
1279                 totw += itemw;
1280                 tot++;
1281         }
1282
1283         if(totw == 0)
1284                 return;
1285         
1286         if(w != 0)
1287                 w -= (tot-1)*litem->space;
1288         fixedw= 0;
1289
1290         /* keep clamping items to fixed minimum size until all are done */
1291         do {
1292                 freew= 0;
1293                 x= 0;
1294                 flag= 0;
1295
1296                 for(item=litem->items.first; item; item=item->next) {
1297                         if(item->flag)
1298                                 continue;
1299
1300                         ui_item_size(item, &itemw, &itemh);
1301                         minw= ui_litem_min_width(itemw);
1302
1303                         if(w - lastw > 0)
1304                                 neww= ui_item_fit(itemw, x, totw, w-lastw, !item->next, litem->alignment, NULL);
1305                         else
1306                                 neww= 0; /* no space left, all will need clamping to minimum size */
1307
1308                         x += neww;
1309
1310                         if((neww < minw || itemw == minw) && w != 0) {
1311                                 /* fixed size */
1312                                 item->flag= 1;
1313                                 fixedw += minw;
1314                                 flag= 1;
1315                                 totw -= itemw;
1316                         }
1317                         else {
1318                                 /* keep free size */
1319                                 item->flag= 0;
1320                                 freew += itemw;
1321                         }
1322                 }
1323
1324                 lastw= fixedw;
1325         } while(flag);
1326
1327         freex= 0;
1328         fixedx= 0;
1329         x= litem->x;
1330
1331         for(item=litem->items.first; item; item=item->next) {
1332                 ui_item_size(item, &itemw, &itemh);
1333                 minw= ui_litem_min_width(itemw);
1334
1335                 if(item->flag) {
1336                         /* fixed minimum size items */
1337                         itemw= ui_item_fit(minw, fixedx, fixedw, MIN2(w, fixedw), !item->next, litem->alignment, NULL);
1338                         fixedx += itemw;
1339                 }
1340                 else {
1341                         /* free size item */
1342                         itemw= ui_item_fit(itemw, freex, freew, w-fixedw, !item->next, litem->alignment, NULL);
1343                         freex += itemw;
1344                 }
1345
1346                 /* align right/center */
1347                 offset= 0;
1348                 if(litem->alignment == UI_LAYOUT_ALIGN_RIGHT) {
1349                         if(fixedw == 0 && freew < w-fixedw)
1350                                 offset= (w - fixedw) - freew;
1351                 }
1352                 else if(litem->alignment == UI_LAYOUT_ALIGN_CENTER) {
1353                         if(fixedw == 0 && freew < w-fixedw)
1354                                 offset= ((w - fixedw) - freew)/2;
1355                 }
1356
1357                 /* position item */
1358                 ui_item_position(item, x+offset, y-itemh, itemw, itemh);
1359
1360                 x += itemw;
1361                 if(item->next)
1362                         x += litem->space;
1363         }
1364
1365         litem->w= x - litem->x;
1366         litem->h= litem->y - y;
1367         litem->x= x;
1368         litem->y= y;
1369 }
1370
1371 /* single-column layout */
1372 static void ui_litem_estimate_column(uiLayout *litem)
1373 {
1374         uiItem *item;
1375         int itemw, itemh;
1376
1377         litem->w= 0;
1378         litem->h= 0;
1379
1380         for(item=litem->items.first; item; item=item->next) {
1381                 ui_item_size(item, &itemw, &itemh);
1382
1383                 litem->w= MAX2(litem->w, itemw);
1384                 litem->h += itemh;
1385
1386                 if(item->next)
1387                         litem->h += litem->space;
1388         }
1389 }
1390
1391 static void ui_litem_layout_column(uiLayout *litem)
1392 {
1393         uiItem *item;
1394         int itemh, x, y;
1395
1396         x= litem->x;
1397         y= litem->y;
1398
1399         for(item=litem->items.first; item; item=item->next) {
1400                 ui_item_size(item, NULL, &itemh);
1401
1402                 y -= itemh;
1403                 ui_item_position(item, x, y, litem->w, itemh);
1404
1405                 if(item->next)
1406                         y -= litem->space;
1407         }
1408
1409         litem->h= litem->y - y;
1410         litem->x= x;
1411         litem->y= y;
1412 }
1413
1414 /* root layout */
1415 static void ui_litem_estimate_root(uiLayout *litem)
1416 {
1417         /* nothing to do */
1418 }
1419
1420 static void ui_litem_layout_root(uiLayout *litem)
1421 {
1422         if(litem->root->type == UI_LAYOUT_HEADER)
1423                 ui_litem_layout_row(litem);
1424         else
1425                 ui_litem_layout_column(litem);
1426 }
1427
1428 /* box layout */
1429 static void ui_litem_estimate_box(uiLayout *litem)
1430 {
1431         uiStyle *style= litem->root->style;
1432
1433         ui_litem_estimate_column(litem);
1434         litem->w += 2*style->boxspace;
1435         litem->h += style->boxspace;
1436 }
1437
1438 static void ui_litem_layout_box(uiLayout *litem)
1439 {
1440         uiLayoutItemBx *box= (uiLayoutItemBx*)litem;
1441         uiStyle *style= litem->root->style;
1442         uiBut *but;
1443         int w, h;
1444
1445         w= litem->w;
1446         h= litem->h;
1447
1448         litem->x += style->boxspace;
1449
1450         if(w != 0) litem->w -= 2*style->boxspace;
1451         if(h != 0) litem->h -= 2*style->boxspace;
1452
1453         ui_litem_layout_column(litem);
1454
1455         litem->x -= style->boxspace;
1456         litem->y -= style->boxspace;
1457
1458         if(w != 0) litem->w += 2*style->boxspace;
1459         if(h != 0) litem->h += style->boxspace;
1460
1461         /* roundbox around the sublayout */
1462         but= box->roundbox;
1463         but->x1= litem->x;
1464         but->y1= litem->y;
1465         but->x2= litem->x+litem->w;
1466         but->y2= litem->y+litem->h;
1467 }
1468
1469 /* multi-column layout, automatically flowing to the next */
1470 static void ui_litem_estimate_column_flow(uiLayout *litem)
1471 {
1472         uiStyle *style= litem->root->style;
1473         uiLayoutItemFlow *flow= (uiLayoutItemFlow*)litem;
1474         uiItem *item;
1475         int col, x, y, emh, emy, miny, itemw, itemh, maxw=0;
1476         int toth, totitem;
1477
1478         /* compute max needed width and total height */
1479         toth= 0;
1480         totitem= 0;
1481         for(item=litem->items.first; item; item=item->next) {
1482                 ui_item_size(item, &itemw, &itemh);
1483                 maxw= MAX2(maxw, itemw);
1484                 toth += itemh;
1485                 totitem++;
1486         }
1487
1488         if(flow->number <= 0) {
1489                 /* auto compute number of columns, not very good */
1490                 if(maxw == 0) {
1491                         flow->totcol= 1;
1492                         return;
1493                 }
1494
1495                 flow->totcol= MAX2(litem->root->emw/maxw, 1);
1496                 flow->totcol= MIN2(flow->totcol, totitem);
1497         }
1498         else
1499                 flow->totcol= flow->number;
1500
1501         /* compute sizes */
1502         x= 0;
1503         y= 0;
1504         emy= 0;
1505         miny= 0;
1506
1507         maxw= 0;
1508         emh= toth/flow->totcol;
1509
1510         /* create column per column */
1511         col= 0;
1512         for(item=litem->items.first; item; item=item->next) {
1513                 ui_item_size(item, &itemw, &itemh);
1514
1515                 y -= itemh + style->buttonspacey;
1516                 miny= MIN2(miny, y);
1517                 emy -= itemh;
1518                 maxw= MAX2(itemw, maxw);
1519
1520                 /* decide to go to next one */
1521                 if(col < flow->totcol-1 && emy <= -emh) {
1522                         x += maxw + litem->space;
1523                         maxw= 0;
1524                         y= 0;
1525                         col++;
1526                 }
1527         }
1528
1529         litem->w= x;
1530         litem->h= litem->y - miny;
1531 }
1532
1533 static void ui_litem_layout_column_flow(uiLayout *litem)
1534 {
1535         uiStyle *style= litem->root->style;
1536         uiLayoutItemFlow *flow= (uiLayoutItemFlow*)litem;
1537         uiItem *item;
1538         int col, x, y, w, emh, emy, miny, itemw, itemh;
1539         int toth, totitem, offset;
1540
1541         /* compute max needed width and total height */
1542         toth= 0;
1543         totitem= 0;
1544         for(item=litem->items.first; item; item=item->next) {
1545                 ui_item_size(item, &itemw, &itemh);
1546                 toth += itemh;
1547                 totitem++;
1548         }
1549
1550         /* compute sizes */
1551         x= litem->x;
1552         y= litem->y;
1553         emy= 0;
1554         miny= 0;
1555
1556         w= litem->w - (flow->totcol-1)*style->columnspace;
1557         emh= toth/flow->totcol;
1558
1559         /* create column per column */
1560         col= 0;
1561         for(item=litem->items.first; item; item=item->next) {
1562                 ui_item_size(item, NULL, &itemh);
1563                 itemw= ui_item_fit(1, x-litem->x, flow->totcol, w, col == flow->totcol-1, litem->alignment, &offset);
1564         
1565                 y -= itemh;
1566                 emy -= itemh;
1567                 ui_item_position(item, x+offset, y, itemw, itemh);
1568                 y -= style->buttonspacey;
1569                 miny= MIN2(miny, y);
1570
1571                 /* decide to go to next one */
1572                 if(col < flow->totcol-1 && emy <= -emh) {
1573                         x += itemw + style->columnspace;
1574                         y= litem->y;
1575                         col++;
1576                 }
1577         }
1578
1579         litem->h= litem->y - miny;
1580         litem->x= x;
1581         litem->y= miny;
1582 }
1583
1584 /* free layout */
1585 static void ui_litem_estimate_free(uiLayout *litem)
1586 {
1587         uiItem *item;
1588         int itemx, itemy, itemw, itemh, minx, miny;
1589
1590         minx= 1e6;
1591         miny= 1e6;
1592         litem->w= 0;
1593         litem->h= 0;
1594
1595         for(item=litem->items.first; item; item=item->next) {
1596                 ui_item_offset(item, &itemx, &itemy);
1597                 ui_item_size(item, &itemw, &itemh);
1598
1599                 minx= MIN2(minx, itemx);
1600                 miny= MIN2(miny, itemy);
1601
1602                 litem->w= MAX2(litem->w, itemx+itemw);
1603                 litem->h= MAX2(litem->h, itemy+itemh);
1604         }
1605
1606         litem->w -= minx;
1607         litem->h -= miny;
1608 }
1609
1610 static void ui_litem_layout_free(uiLayout *litem)
1611 {
1612         uiItem *item;
1613         float scalex=1.0f, scaley=1.0f;
1614         int x, y, newx, newy, itemx, itemy, itemh, itemw, minx, miny, totw, toth;
1615
1616         minx= 1e6;
1617         miny= 1e6;
1618         totw= 0;
1619         toth= 0;
1620
1621         for(item=litem->items.first; item; item=item->next) {
1622                 ui_item_offset(item, &itemx, &itemy);
1623                 ui_item_size(item, &itemw, &itemh);
1624
1625                 minx= MIN2(minx, itemx);
1626                 miny= MIN2(miny, itemy);
1627
1628                 totw= MAX2(totw, itemx+itemw);
1629                 toth= MAX2(toth, itemy+itemh);
1630         }
1631
1632         totw -= minx;
1633         toth -= miny;
1634
1635         if(litem->w && totw > 0)
1636                 scalex= (float)litem->w/(float)totw;
1637         if(litem->h && toth > 0)
1638                 scaley= (float)litem->h/(float)toth;
1639         
1640         x= litem->x;
1641         y= litem->y - scaley*toth;
1642
1643         for(item=litem->items.first; item; item=item->next) {
1644                 ui_item_offset(item, &itemx, &itemy);
1645                 ui_item_size(item, &itemw, &itemh);
1646
1647                 if(scalex != 1.0f) {
1648                         newx= (itemx - minx)*scalex;
1649                         itemw= (itemx - minx + itemw)*scalex - newx;
1650                         itemx= minx + newx;
1651                 }
1652
1653                 if(scaley != 1.0f) {
1654                         newy= (itemy - miny)*scaley;
1655                         itemh= (itemy - miny + itemh)*scaley - newy;
1656                         itemy= miny + newy;
1657                 }
1658
1659                 ui_item_position(item, x+itemx-minx, y+itemy-miny, itemw, itemh);
1660         }
1661
1662         litem->w= scalex*totw;
1663         litem->h= litem->y - y;
1664         litem->x= x + litem->w;
1665         litem->y= y;
1666 }
1667
1668 /* split layout */
1669 static void ui_litem_estimate_split(uiLayout *litem)
1670 {
1671         ui_litem_estimate_row(litem);
1672 }
1673
1674 static void ui_litem_layout_split(uiLayout *litem)
1675 {
1676         uiLayoutItemSplt *split= (uiLayoutItemSplt*)litem;
1677         uiItem *item;
1678         float percentage;
1679         int itemh, x, y, w, tot=0, colw=0;
1680
1681         x= litem->x;
1682         y= litem->y;
1683
1684         for(item=litem->items.first; item; item=item->next)
1685                 tot++;
1686         
1687         if(tot == 0)
1688                 return;
1689         
1690         percentage= (split->percentage == 0.0f)? 1.0f/(float)tot: split->percentage;
1691         
1692         w= (litem->w - (tot-1)*litem->space);
1693         colw= w*percentage;
1694         colw= MAX2(colw, 0);
1695
1696         for(item=litem->items.first; item; item=item->next) {
1697                 ui_item_size(item, NULL, &itemh);
1698
1699                 ui_item_position(item, x, y-itemh, colw, itemh);
1700                 x += colw;
1701
1702                 if(item->next) {
1703                         colw= (w - (int)(w*percentage))/(tot-1);
1704                         colw= MAX2(colw, 0);
1705
1706                         x += litem->space;
1707                 }
1708         }
1709
1710         litem->w= x - litem->x;
1711         litem->h= litem->y - y;
1712         litem->x= x;
1713         litem->y= y;
1714 }
1715
1716 /* layout create functions */
1717 uiLayout *uiLayoutRow(uiLayout *layout, int align)
1718 {
1719         uiLayout *litem;
1720
1721         litem= MEM_callocN(sizeof(uiLayout), "uiLayoutRow");
1722         litem->item.type= ITEM_LAYOUT_ROW;
1723         litem->root= layout->root;
1724         litem->align= align;
1725         litem->active= 1;
1726         litem->enabled= 1;
1727         litem->context= layout->context;
1728         litem->space= (align)? 0: layout->root->style->buttonspacex;
1729         BLI_addtail(&layout->items, litem);
1730
1731         uiBlockSetCurLayout(layout->root->block, litem);
1732
1733         return litem;
1734 }
1735
1736 uiLayout *uiLayoutColumn(uiLayout *layout, int align)
1737 {
1738         uiLayout *litem;
1739
1740         litem= MEM_callocN(sizeof(uiLayout), "uiLayoutColumn");
1741         litem->item.type= ITEM_LAYOUT_COLUMN;
1742         litem->root= layout->root;
1743         litem->align= align;
1744         litem->active= 1;
1745         litem->enabled= 1;
1746         litem->context= layout->context;
1747         litem->space= (litem->align)? 0: layout->root->style->buttonspacey;
1748         BLI_addtail(&layout->items, litem);
1749
1750         uiBlockSetCurLayout(layout->root->block, litem);
1751
1752         return litem;
1753 }
1754
1755 uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align)
1756 {
1757         uiLayoutItemFlow *flow;
1758
1759         flow= MEM_callocN(sizeof(uiLayoutItemFlow), "uiLayoutItemFlow");
1760         flow->litem.item.type= ITEM_LAYOUT_COLUMN_FLOW;
1761         flow->litem.root= layout->root;
1762         flow->litem.align= align;
1763         flow->litem.active= 1;
1764         flow->litem.enabled= 1;
1765         flow->litem.context= layout->context;
1766         flow->litem.space= (flow->litem.align)? 0: layout->root->style->columnspace;
1767         flow->number= number;
1768         BLI_addtail(&layout->items, flow);
1769
1770         uiBlockSetCurLayout(layout->root->block, &flow->litem);
1771
1772         return &flow->litem;
1773 }
1774
1775 uiLayout *uiLayoutBox(uiLayout *layout)
1776 {
1777         uiLayoutItemBx *box;
1778
1779         box= MEM_callocN(sizeof(uiLayoutItemBx), "uiLayoutItemBx");
1780         box->litem.item.type= ITEM_LAYOUT_BOX;
1781         box->litem.root= layout->root;
1782         box->litem.active= 1;
1783         box->litem.enabled= 1;
1784         box->litem.context= layout->context;
1785         box->litem.space= layout->root->style->columnspace;
1786         BLI_addtail(&layout->items, box);
1787
1788         uiBlockSetCurLayout(layout->root->block, &box->litem);
1789
1790         box->roundbox= uiDefBut(layout->root->block, ROUNDBOX, 0, "", 0, 0, 0, 0, NULL, 0.0, 0.0, 0, 0, "");
1791
1792         return &box->litem;
1793 }
1794
1795 uiLayout *uiLayoutFree(uiLayout *layout, int align)
1796 {
1797         uiLayout *litem;
1798
1799         litem= MEM_callocN(sizeof(uiLayout), "uiLayoutFree");
1800         litem->item.type= ITEM_LAYOUT_FREE;
1801         litem->root= layout->root;
1802         litem->align= align;
1803         litem->active= 1;
1804         litem->enabled= 1;
1805         litem->context= layout->context;
1806         BLI_addtail(&layout->items, litem);
1807
1808         uiBlockSetCurLayout(layout->root->block, litem);
1809
1810         return litem;
1811 }
1812
1813 uiBlock *uiLayoutFreeBlock(uiLayout *layout)
1814 {
1815         uiBlock *block;
1816
1817         block= uiLayoutGetBlock(layout);
1818         uiLayoutFree(layout, 0);
1819
1820         return block;
1821 }
1822
1823 uiLayout *uiLayoutSplit(uiLayout *layout, float percentage)
1824 {
1825         uiLayoutItemSplt *split;
1826
1827         split= MEM_callocN(sizeof(uiLayoutItemSplt), "uiLayoutItemSplt");
1828         split->litem.item.type= ITEM_LAYOUT_SPLIT;
1829         split->litem.root= layout->root;
1830         split->litem.active= 1;
1831         split->litem.enabled= 1;
1832         split->litem.context= layout->context;
1833         split->litem.space= layout->root->style->columnspace;
1834         split->percentage= percentage;
1835         BLI_addtail(&layout->items, split);
1836
1837         uiBlockSetCurLayout(layout->root->block, &split->litem);
1838
1839         return &split->litem;
1840 }
1841
1842 void uiLayoutSetActive(uiLayout *layout, int active)
1843 {
1844         layout->active= active;
1845 }
1846
1847 void uiLayoutSetEnabled(uiLayout *layout, int enabled)
1848 {
1849         layout->enabled= enabled;
1850 }
1851
1852 void uiLayoutSetRedAlert(uiLayout *layout, int redalert)
1853 {
1854         layout->redalert= redalert;
1855 }
1856
1857 void uiLayoutSetKeepAspect(uiLayout *layout, int keepaspect)
1858 {
1859         layout->keepaspect= keepaspect;
1860 }
1861
1862 void uiLayoutSetAlignment(uiLayout *layout, int alignment)
1863 {
1864         layout->alignment= alignment;
1865 }
1866
1867 void uiLayoutSetScaleX(uiLayout *layout, float scale)
1868 {
1869         layout->scale[0]= scale;
1870 }
1871
1872 void uiLayoutSetScaleY(uiLayout *layout, float scale)
1873 {
1874         layout->scale[1]= scale;
1875 }
1876
1877 int uiLayoutGetActive(uiLayout *layout)
1878 {
1879         return layout->active;
1880 }
1881
1882 int uiLayoutGetEnabled(uiLayout *layout)
1883 {
1884         return layout->enabled;
1885 }
1886
1887 int uiLayoutGetRedAlert(uiLayout *layout)
1888 {
1889         return layout->redalert;
1890 }
1891
1892 int uiLayoutGetKeepAspect(uiLayout *layout)
1893 {
1894         return layout->keepaspect;
1895 }
1896
1897 int uiLayoutGetAlignment(uiLayout *layout)
1898 {
1899         return layout->alignment;
1900 }
1901
1902 float uiLayoutGetScaleX(uiLayout *layout)
1903 {
1904         return layout->scale[0];
1905 }
1906
1907 float uiLayoutGetScaleY(uiLayout *layout)
1908 {
1909         return layout->scale[0];
1910 }
1911
1912 /********************** Layout *******************/
1913
1914 static void ui_item_scale(uiLayout *litem, float scale[2])
1915 {
1916         uiItem *item;
1917         int x, y, w, h;
1918
1919         for(item=litem->items.last; item; item=item->prev) {
1920                 ui_item_size(item, &w, &h);
1921                 ui_item_offset(item, &x, &y);
1922
1923                 if(scale[0] != 0.0f) {
1924                         x *= scale[0];
1925                         w *= scale[0];
1926                 }
1927
1928                 if(scale[1] != 0.0f) {
1929                         y *= scale[1];
1930                         h *= scale[1];
1931                 }
1932
1933                 ui_item_position(item, x, y, w, h);
1934         }
1935 }
1936
1937 static void ui_item_estimate(uiItem *item)
1938 {
1939         uiItem *subitem;
1940
1941         if(item->type != ITEM_BUTTON) {
1942                 uiLayout *litem= (uiLayout*)item;
1943
1944                 for(subitem=litem->items.first; subitem; subitem=subitem->next)
1945                         ui_item_estimate(subitem);
1946
1947                 if(litem->items.first == NULL)
1948                         return;
1949
1950                 if(litem->scale[0] != 0.0f || litem->scale[1] != 0.0f)
1951                         ui_item_scale(litem, litem->scale);
1952
1953                 switch(litem->item.type) {
1954                         case ITEM_LAYOUT_COLUMN:
1955                                 ui_litem_estimate_column(litem);
1956                                 break;
1957                         case ITEM_LAYOUT_COLUMN_FLOW:
1958                                 ui_litem_estimate_column_flow(litem);
1959                                 break;
1960                         case ITEM_LAYOUT_ROW:
1961                                 ui_litem_estimate_row(litem);
1962                                 break;
1963                         case ITEM_LAYOUT_BOX:
1964                                 ui_litem_estimate_box(litem);
1965                                 break;
1966                         case ITEM_LAYOUT_ROOT:
1967                                 ui_litem_estimate_root(litem);
1968                                 break;
1969                         case ITEM_LAYOUT_FREE:
1970                                 ui_litem_estimate_free(litem);
1971                                 break;
1972                         case ITEM_LAYOUT_SPLIT:
1973                                 ui_litem_estimate_split(litem);
1974                                 break;
1975                         default:
1976                                 break;
1977                 }
1978         }
1979 }
1980
1981 static void ui_item_align(uiLayout *litem, int nr)
1982 {
1983         uiItem *item;
1984         uiButtonItem *bitem;
1985         uiLayoutItemBx *box;
1986
1987         for(item=litem->items.last; item; item=item->prev) {
1988                 if(item->type == ITEM_BUTTON) {
1989                         bitem= (uiButtonItem*)item;
1990                         if(ui_but_can_align(bitem->but))
1991                                 if(!bitem->but->alignnr)
1992                                         bitem->but->alignnr= nr;
1993                 }
1994                 else if(item->type == ITEM_LAYOUT_FREE);
1995                 else if(item->type == ITEM_LAYOUT_BOX) {
1996                         box= (uiLayoutItemBx*)item;
1997                         box->roundbox->alignnr= nr;
1998                         BLI_remlink(&litem->root->block->buttons, box->roundbox);
1999                         BLI_addhead(&litem->root->block->buttons, box->roundbox);
2000                 }
2001                 else
2002                         ui_item_align((uiLayout*)item, nr);
2003         }
2004 }
2005
2006 static void ui_item_flag(uiLayout *litem, int flag)
2007 {
2008         uiItem *item;
2009         uiButtonItem *bitem;
2010
2011         for(item=litem->items.last; item; item=item->prev) {
2012                 if(item->type == ITEM_BUTTON) {
2013                         bitem= (uiButtonItem*)item;
2014                         bitem->but->flag |= flag;
2015                 }
2016                 else
2017                         ui_item_flag((uiLayout*)item, flag);
2018         }
2019 }
2020
2021 static void ui_item_layout(uiItem *item)
2022 {
2023         uiItem *subitem;
2024
2025         if(item->type != ITEM_BUTTON) {
2026                 uiLayout *litem= (uiLayout*)item;
2027
2028                 if(litem->items.first == NULL)
2029                         return;
2030
2031                 if(litem->align)
2032                         ui_item_align(litem, ++litem->root->block->alignnr);
2033                 if(!litem->active)
2034                         ui_item_flag(litem, UI_BUT_INACTIVE);
2035                 if(!litem->enabled)
2036                         ui_item_flag(litem, UI_BUT_DISABLED);
2037
2038                 switch(litem->item.type) {
2039                         case ITEM_LAYOUT_COLUMN:
2040                                 ui_litem_layout_column(litem);
2041                                 break;
2042                         case ITEM_LAYOUT_COLUMN_FLOW:
2043                                 ui_litem_layout_column_flow(litem);
2044                                 break;
2045                         case ITEM_LAYOUT_ROW:
2046                                 ui_litem_layout_row(litem);
2047                                 break;
2048                         case ITEM_LAYOUT_BOX:
2049                                 ui_litem_layout_box(litem);
2050                                 break;
2051                         case ITEM_LAYOUT_ROOT:
2052                                 ui_litem_layout_root(litem);
2053                                 break;
2054                         case ITEM_LAYOUT_FREE:
2055                                 ui_litem_layout_free(litem);
2056                                 break;
2057                         case ITEM_LAYOUT_SPLIT:
2058                                 ui_litem_layout_split(litem);
2059                                 break;
2060                         default:
2061                                 break;
2062                 }
2063
2064                 for(subitem=litem->items.first; subitem; subitem=subitem->next)
2065                         ui_item_layout(subitem);
2066         }
2067 }
2068
2069 static void ui_layout_items(const bContext *C, uiBlock *block, uiLayout *layout)
2070 {
2071         ui_item_estimate(&layout->item);
2072         ui_item_layout(&layout->item);
2073 }
2074
2075 static void ui_layout_end(const bContext *C, uiBlock *block, uiLayout *layout, int *x, int *y)
2076 {
2077         if(layout->root->handlefunc)
2078                 uiBlockSetButmFunc(block, layout->root->handlefunc, layout->root->argv);
2079
2080         ui_layout_items(C, block, layout);
2081
2082         if(x) *x= layout->x;
2083         if(y) *y= layout->y;
2084 }
2085
2086 static void ui_layout_free(uiLayout *layout)
2087 {
2088         uiItem *item, *next;
2089
2090         for(item=layout->items.first; item; item=next) {
2091                 next= item->next;
2092
2093                 if(item->type == ITEM_BUTTON)
2094                         MEM_freeN(item);
2095                 else
2096                         ui_layout_free((uiLayout*)item);
2097         }
2098
2099         MEM_freeN(layout);
2100 }
2101
2102 uiLayout *uiBlockLayout(uiBlock *block, int dir, int type, int x, int y, int size, int em, uiStyle *style)
2103 {
2104         uiLayout *layout;
2105         uiLayoutRoot *root;
2106
2107         root= MEM_callocN(sizeof(uiLayoutRoot), "uiLayoutRoot");
2108         root->type= type;
2109         root->style= style;
2110         root->block= block;
2111         root->opcontext= WM_OP_INVOKE_REGION_WIN;
2112
2113         layout= MEM_callocN(sizeof(uiLayout), "uiLayout");
2114         layout->item.type= ITEM_LAYOUT_ROOT;
2115
2116         layout->x= x;
2117         layout->y= y;
2118         layout->root= root;
2119         layout->space= style->templatespace;
2120         layout->active= 1;
2121         layout->enabled= 1;
2122         layout->context= NULL;
2123
2124         if(type == UI_LAYOUT_MENU)
2125                 layout->space= 0;
2126
2127         if(dir == UI_LAYOUT_HORIZONTAL) {
2128                 layout->h= size;
2129                 layout->root->emh= em*UI_UNIT_Y;
2130         }
2131         else {
2132                 layout->w= size;
2133                 layout->root->emw= em*UI_UNIT_X;
2134         }
2135
2136         block->curlayout= layout;
2137         root->layout= layout;
2138         BLI_addtail(&block->layouts, root);
2139         
2140         return layout;
2141 }
2142
2143 uiBlock *uiLayoutGetBlock(uiLayout *layout)
2144 {
2145         return layout->root->block;
2146 }
2147
2148 int uiLayoutGetOperatorContext(uiLayout *layout)
2149 {
2150         return layout->root->opcontext;
2151 }
2152
2153
2154 void uiBlockSetCurLayout(uiBlock *block, uiLayout *layout)
2155 {
2156         block->curlayout= layout;
2157 }
2158
2159 void ui_layout_add_but(uiLayout *layout, uiBut *but)
2160 {
2161         uiButtonItem *bitem;
2162         
2163         bitem= MEM_callocN(sizeof(uiButtonItem), "uiButtonItem");
2164         bitem->item.type= ITEM_BUTTON;
2165         bitem->but= but;
2166         BLI_addtail(&layout->items, bitem);
2167
2168         if(layout->context) {
2169                 but->context= layout->context;
2170                 but->context->used= 1;
2171         }
2172 }
2173
2174 void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext)
2175 {
2176         layout->root->opcontext= opcontext;
2177 }
2178
2179 void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv)
2180 {
2181         layout->root->handlefunc= handlefunc;
2182         layout->root->argv= argv;
2183 }
2184
2185 void uiBlockLayoutResolve(const bContext *C, uiBlock *block, int *x, int *y)
2186 {
2187         uiLayoutRoot *root;
2188
2189         if(x) *x= 0;
2190         if(y) *y= 0;
2191
2192         block->curlayout= NULL;
2193
2194         for(root=block->layouts.first; root; root=root->next) {
2195                 /* NULL in advance so we don't interfere when adding button */
2196                 ui_layout_end(C, block, root->layout, x, y);
2197                 ui_layout_free(root->layout);
2198         }
2199
2200         BLI_freelistN(&block->layouts);
2201
2202         /* XXX silly trick, interface_templates.c doesn't get linked
2203          * because it's not used by other files in this module? */
2204         {
2205                 void ui_template_fix_linking();
2206                 ui_template_fix_linking();
2207         }
2208 }
2209
2210 void uiLayoutSetContextPointer(uiLayout *layout, char *name, PointerRNA *ptr)
2211 {
2212         uiBlock *block= layout->root->block;
2213         layout->context= CTX_store_add(&block->contexts, name, ptr);
2214 }
2215