Merge with 2.5 -r 21515:21619.
[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         EnumPropertyItem *item;
433         const char *identifier;
434         char *name;
435         int a, totitem, itemw, icon, value, free;
436
437         identifier= RNA_property_identifier(prop);
438         RNA_property_enum_items(block->evil_C, ptr, prop, &item, &totitem, &free);
439
440         uiBlockSetCurLayout(block, ui_item_local_sublayout(layout, layout, 1));
441         for(a=0; a<totitem; a++) {
442                 if(!item[a].identifier[0])
443                         continue;
444
445                 name= (!uiname || uiname[0])? (char*)item[a].name: "";
446                 icon= item[a].icon;
447                 value= item[a].value;
448                 itemw= ui_text_icon_width(block->curlayout, name, icon);
449
450                 if(icon && strcmp(name, "") != 0)
451                         uiDefIconTextButR(block, ROW, 0, icon, name, 0, 0, itemw, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
452                 else if(icon)
453                         uiDefIconButR(block, ROW, 0, icon, 0, 0, itemw, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
454                 else
455                         uiDefButR(block, ROW, 0, name, 0, 0, itemw, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
456         }
457         uiBlockSetCurLayout(block, layout);
458
459         if(free)
460                 MEM_freeN(item);
461 }
462
463 /* create label + button for RNA property */
464 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)
465 {
466         uiLayout *sub;
467         uiBut *but;
468         PropertySubType subtype;
469         int labelw;
470
471         sub= uiLayoutRow(layout, 0);
472         uiBlockSetCurLayout(block, sub);
473
474         if(strcmp(name, "") != 0) {
475                 /* XXX UI_GetStringWidth is not accurate
476                 labelw= UI_GetStringWidth(name);
477                 CLAMP(labelw, w/4, 3*w/4);*/
478                 labelw= w/2;
479                 uiDefBut(block, LABEL, 0, name, x, y, labelw, h, NULL, 0.0, 0.0, 0, 0, "");
480                 w= w-labelw;
481         }
482
483         subtype= RNA_property_subtype(prop);
484
485         if(subtype == PROP_FILEPATH || subtype == PROP_DIRPATH) {
486                 uiBlockSetCurLayout(block, uiLayoutRow(sub, 1));
487                 uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w-UI_UNIT_X, h);
488                 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 */
489         }
490         else
491                 but= uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w, h);
492
493         uiBlockSetCurLayout(block, layout);
494         return but;
495 }
496
497 /********************* Button Items *************************/
498
499 /* disabled item */
500 static void ui_item_disabled(uiLayout *layout, char *name)
501 {
502         uiBlock *block= layout->root->block;
503         uiBut *but;
504         int w;
505
506         uiBlockSetCurLayout(block, layout);
507
508         if(!name)
509                 name= "";
510
511         w= ui_text_icon_width(layout, name, 0);
512
513         but= uiDefBut(block, LABEL, 0, (char*)name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
514         but->flag |= UI_BUT_DISABLED;
515         but->lock = 1;
516         but->lockstr = "";
517 }
518
519 /* operator items */
520 void uiItemFullO(uiLayout *layout, char *name, int icon, char *idname, IDProperty *properties, int context)
521 {
522         uiBlock *block= layout->root->block;
523         wmOperatorType *ot= WM_operatortype_find(idname, 0);
524         uiBut *but;
525         int w;
526
527         if(!ot) {
528                 ui_item_disabled(layout, idname);
529                 return;
530         }
531
532         if(!name)
533                 name= ot->name;
534         if(layout->root->type == UI_LAYOUT_MENU && !icon)
535                 icon= ICON_BLANK1;
536
537         /* create button */
538         uiBlockSetCurLayout(block, layout);
539
540         w= ui_text_icon_width(layout, name, icon);
541
542         if(icon && strcmp(name, "") != 0)
543                 but= uiDefIconTextButO(block, BUT, ot->idname, context, icon, (char*)name, 0, 0, w, UI_UNIT_Y, NULL);
544         else if(icon)
545                 but= uiDefIconButO(block, BUT, ot->idname, context, icon, 0, 0, w, UI_UNIT_Y, NULL);
546         else
547                 but= uiDefButO(block, BUT, ot->idname, context, (char*)name, 0, 0, w, UI_UNIT_Y, NULL);
548
549         /* assign properties */
550         if(properties) {
551                 PointerRNA *opptr= uiButGetOperatorPtrRNA(but);
552                 opptr->data= properties;
553         }
554 }
555
556 static char *ui_menu_enumpropname(uiLayout *layout, char *opname, char *propname, int retval)
557 {
558         wmOperatorType *ot= WM_operatortype_find(opname, 0);
559         PointerRNA ptr;
560         PropertyRNA *prop;
561
562         if(!ot || !ot->srna)
563                 return "";
564
565         RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
566         prop= RNA_struct_find_property(&ptr, propname);
567
568         if(prop) {
569                 EnumPropertyItem *item;
570                 int totitem, free;
571                 const char *name;
572
573                 RNA_property_enum_items(layout->root->block->evil_C, &ptr, prop, &item, &totitem, &free);
574                 if(RNA_enum_name(item, retval, &name)) {
575                         if(free) MEM_freeN(item);
576                         return (char*)name;
577                 }
578                 
579                 if(free)
580                         MEM_freeN(item);
581         }
582
583         return "";
584 }
585
586 void uiItemEnumO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
587 {
588         PointerRNA ptr;
589
590         WM_operator_properties_create(&ptr, opname);
591         RNA_enum_set(&ptr, propname, value);
592
593         if(!name)
594                 name= ui_menu_enumpropname(layout, opname, propname, value);
595
596         uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
597 }
598
599 void uiItemsEnumO(uiLayout *layout, char *opname, char *propname)
600 {
601         wmOperatorType *ot= WM_operatortype_find(opname, 0);
602         PointerRNA ptr;
603         PropertyRNA *prop;
604
605         if(!ot || !ot->srna) {
606                 ui_item_disabled(layout, opname);
607                 return;
608         }
609
610         RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
611         prop= RNA_struct_find_property(&ptr, propname);
612
613         if(prop && RNA_property_type(prop) == PROP_ENUM) {
614                 EnumPropertyItem *item;
615                 int totitem, i, free;
616
617                 RNA_property_enum_items(layout->root->block->evil_C, &ptr, prop, &item, &totitem, &free);
618
619                 for(i=0; i<totitem; i++)
620                         if(item[i].identifier[0])
621                                 uiItemEnumO(layout, (char*)item[i].name, item[i].icon, opname, propname, item[i].value);
622                         else
623                                 uiItemS(layout);
624
625                 if(free)
626                         MEM_freeN(item);
627         }
628 }
629
630 /* for use in cases where we have */
631 void uiItemEnumO_string(uiLayout *layout, char *name, int icon, char *opname, char *propname, char *value_str)
632 {
633         PointerRNA ptr;
634         
635         /* for getting the enum */
636         PropertyRNA *prop;
637         EnumPropertyItem *item;
638         int value, free;
639
640         WM_operator_properties_create(&ptr, opname);
641         
642         /* enum lookup */
643         if((prop= RNA_struct_find_property(&ptr, propname))) {
644                 RNA_property_enum_items(layout->root->block->evil_C, &ptr, prop, &item, NULL, &free);
645                 if(RNA_enum_value_from_id(item, value_str, &value)==0) {
646                         if(free) MEM_freeN(item);
647                         printf("uiItemEnumO_string: %s.%s, enum %s not found.\n", RNA_struct_identifier(ptr.type), propname, value_str);
648                         return;
649                 }
650
651                 if(free)
652                         MEM_freeN(item);
653         }
654         else {
655                 printf("uiItemEnumO_string: %s.%s not found.\n", RNA_struct_identifier(ptr.type), propname);
656                 return;
657         }
658         
659         RNA_property_enum_set(&ptr, prop, value);
660         
661         /* same as uiItemEnumO */
662         if(!name)
663                 name= ui_menu_enumpropname(layout, opname, propname, value);
664
665         uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
666 }
667
668 void uiItemBooleanO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
669 {
670         PointerRNA ptr;
671
672         WM_operator_properties_create(&ptr, opname);
673         RNA_boolean_set(&ptr, propname, value);
674
675         uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
676 }
677
678 void uiItemIntO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
679 {
680         PointerRNA ptr;
681
682         WM_operator_properties_create(&ptr, opname);
683         RNA_int_set(&ptr, propname, value);
684
685         uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
686 }
687
688 void uiItemFloatO(uiLayout *layout, char *name, int icon, char *opname, char *propname, float value)
689 {
690         PointerRNA ptr;
691
692         WM_operator_properties_create(&ptr, opname);
693         RNA_float_set(&ptr, propname, value);
694
695         uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
696 }
697
698 void uiItemStringO(uiLayout *layout, char *name, int icon, char *opname, char *propname, char *value)
699 {
700         PointerRNA ptr;
701
702         WM_operator_properties_create(&ptr, opname);
703         RNA_string_set(&ptr, propname, value);
704
705         uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
706 }
707
708 void uiItemO(uiLayout *layout, char *name, int icon, char *opname)
709 {
710         uiItemFullO(layout, name, icon, opname, NULL, layout->root->opcontext);
711 }
712
713 /* RNA property items */
714
715 static void ui_item_rna_size(uiLayout *layout, char *name, int icon, PropertyRNA *prop, int index, int *r_w, int *r_h)
716 {
717         PropertyType type;
718         PropertySubType subtype;
719         int len, w, h;
720
721         /* arbitrary extended width by type */
722         type= RNA_property_type(prop);
723         subtype= RNA_property_subtype(prop);
724         len= RNA_property_array_length(prop);
725
726         if(ELEM(type, PROP_STRING, PROP_POINTER) && strcmp(name, "") == 0)
727                 name= "non-empty";
728
729         w= ui_text_icon_width(layout, name, icon);
730         h= UI_UNIT_Y;
731
732         /* increase height for arrays */
733         if(index == RNA_NO_INDEX && len > 0) {
734                 if(strcmp(name, "") == 0 && icon == 0)
735                         h= 0;
736
737                 if(type == PROP_BOOLEAN && len == 20)
738                         h += 2*UI_UNIT_Y;
739                 else if(subtype == PROP_MATRIX)
740                         h += ceil(sqrt(len))*UI_UNIT_Y;
741                 else
742                         h += len*UI_UNIT_Y;
743         }
744         else if(ui_layout_vary_direction(layout) == UI_ITEM_VARY_X) {
745                 if(type == PROP_BOOLEAN && strcmp(name, "") != 0)
746                         w += UI_UNIT_X;
747                 else if(type == PROP_ENUM)
748                         w += UI_UNIT_X/2;
749         }
750
751         *r_w= w;
752         *r_h= h;
753 }
754
755 void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int value, int expand, int slider, int toggle)
756 {
757         uiBlock *block= layout->root->block;
758         uiBut *but;
759         PropertyType type;
760         char namestr[UI_MAX_NAME_STR];
761         int len, w, h;
762
763         if(!ptr->data || !prop)
764                 return;
765
766         uiBlockSetCurLayout(block, layout);
767
768         /* retrieve info */
769         type= RNA_property_type(prop);
770         len= RNA_property_array_length(prop);
771
772         /* set name and icon */
773         if(!name)
774                 name= (char*)RNA_property_ui_name(prop);
775         if(!icon)
776                 icon= RNA_property_ui_icon(prop);
777
778         if(ELEM4(type, PROP_INT, PROP_FLOAT, PROP_STRING, PROP_POINTER))
779                 name= ui_item_name_add_colon(name, namestr);
780         else if(type == PROP_BOOLEAN && len)
781                 name= ui_item_name_add_colon(name, namestr);
782         else if(type == PROP_ENUM && index != RNA_ENUM_VALUE)
783                 name= ui_item_name_add_colon(name, namestr);
784
785         if(layout->root->type == UI_LAYOUT_MENU) {
786                 if(type == PROP_BOOLEAN)
787                         icon= (RNA_property_boolean_get(ptr, prop))? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT;
788                 else if(type == PROP_ENUM && index == RNA_ENUM_VALUE)
789                         icon= (RNA_property_enum_get(ptr, prop) == value)? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT; 
790         }
791
792         /* get size */
793         ui_item_rna_size(layout, name, icon, prop, index, &w, &h);
794
795         /* array property */
796         if(index == RNA_NO_INDEX && len > 0)
797                 ui_item_array(layout, block, name, icon, ptr, prop, len, 0, 0, w, h, expand, slider);
798         /* enum item */
799         else if(type == PROP_ENUM && index == RNA_ENUM_VALUE) {
800                 char *identifier= (char*)RNA_property_identifier(prop);
801
802                 if(icon && strcmp(name, "") != 0)
803                         uiDefIconTextButR(block, ROW, 0, icon, name, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
804                 else if(icon)
805                         uiDefIconButR(block, ROW, 0, icon, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
806                 else
807                         uiDefButR(block, ROW, 0, name, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
808         }
809         /* expanded enum */
810         else if(type == PROP_ENUM && expand)
811                 ui_item_enum_row(layout, block, ptr, prop, name, 0, 0, w, h);
812         /* property with separate label */
813         else if(type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER) {
814                 but= ui_item_with_label(layout, block, name, icon, ptr, prop, index, 0, 0, w, h);
815                 ui_but_add_search(but, ptr, prop, NULL, NULL);
816         }
817         /* single button */
818         else {
819                 but= uiDefAutoButR(block, ptr, prop, index, (char*)name, icon, 0, 0, w, h);
820
821                 if(slider && but->type==NUM)
822                         but->type= NUMSLI;
823
824                 if(toggle && but->type==OPTION)
825                         but->type= TOG;
826         }
827 }
828
829 void uiItemR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, char *propname, int expand, int slider, int toggle)
830 {
831         PropertyRNA *prop;
832
833         if(!ptr->data || !propname)
834                 return;
835
836         prop= RNA_struct_find_property(ptr, propname);
837
838         if(!prop) {
839                 ui_item_disabled(layout, propname);
840                 printf("uiItemR: property not found: %s\n", propname);
841                 return;
842         }
843
844         uiItemFullR(layout, name, icon, ptr, prop, RNA_NO_INDEX, 0, expand, slider, toggle);
845 }
846
847 void uiItemEnumR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, int value)
848 {
849         PropertyRNA *prop;
850
851         if(!ptr->data || !propname)
852                 return;
853
854         prop= RNA_struct_find_property(ptr, propname);
855
856         if(!prop || RNA_property_type(prop) != PROP_ENUM) {
857                 ui_item_disabled(layout, propname);
858                 printf("uiItemEnumR: enum property not found: %s\n", propname);
859                 return;
860         }
861
862         uiItemFullR(layout, name, icon, ptr, prop, RNA_ENUM_VALUE, value, 0, 0, 0);
863 }
864
865 void uiItemEnumR_string(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, char *value)
866 {
867         PropertyRNA *prop;
868         EnumPropertyItem *item;
869         int ivalue, a, free;
870
871         if(!ptr->data || !propname)
872                 return;
873
874         prop= RNA_struct_find_property(ptr, propname);
875
876         if(!prop || RNA_property_type(prop) != PROP_ENUM) {
877                 ui_item_disabled(layout, propname);
878                 printf("uiItemEnumR: enum property not found: %s\n", propname);
879                 return;
880         }
881
882         RNA_property_enum_items(layout->root->block->evil_C, ptr, prop, &item, NULL, &free);
883
884         if(!RNA_enum_value_from_id(item, value, &ivalue)) {
885                 if(free) MEM_freeN(item);
886                 ui_item_disabled(layout, propname);
887                 printf("uiItemEnumR: enum property value not found: %s\n", value);
888                 return;
889         }
890
891         for(a=0; item[a].identifier; a++) {
892                 if(item[a].value == ivalue) {
893                         uiItemFullR(layout, (char*)item[a].name, item[a].icon, ptr, prop, RNA_ENUM_VALUE, ivalue, 0, 0, 0);
894                         break;
895                 }
896         }
897
898         if(free)
899                 MEM_freeN(item);
900 }
901
902 void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, char *propname)
903 {
904         PropertyRNA *prop;
905
906         prop= RNA_struct_find_property(ptr, propname);
907
908         if(!prop) {
909                 ui_item_disabled(layout, propname);
910                 return;
911         }
912
913         if(RNA_property_type(prop) == PROP_ENUM) {
914                 EnumPropertyItem *item;
915                 int totitem, i, free;
916
917                 RNA_property_enum_items(layout->root->block->evil_C, ptr, prop, &item, &totitem, &free);
918
919                 for(i=0; i<totitem; i++)
920                         if(item[i].identifier[0])
921                                 uiItemEnumR(layout, (char*)item[i].name, 0, ptr, propname, item[i].value);
922                         else
923                                 uiItemS(layout);
924
925                 if(free)
926                         MEM_freeN(item);
927         }
928 }
929
930 /* Pointer RNA button with search */
931
932 static void rna_search_cb(const struct bContext *C, void *arg_but, char *str, uiSearchItems *items)
933 {
934         Scene *scene= CTX_data_scene(C);
935         uiBut *but= arg_but;
936         char *name;
937         int i, iconid;
938
939         i = 0;
940         RNA_PROP_BEGIN(&but->rnasearchpoin, itemptr, but->rnasearchprop) {
941                 iconid= 0;
942                 if(RNA_struct_is_ID(itemptr.type))
943                         iconid= ui_id_icon_get(scene, itemptr.data);
944
945                 name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
946
947                 if(name) {
948                         if(BLI_strcasestr(name, str)) {
949                                 if(!uiSearchItemAdd(items, name, SET_INT_IN_POINTER(i), iconid)) {
950                                         MEM_freeN(name);
951                                         break;
952                                 }
953                         }
954
955                         MEM_freeN(name);
956                 }
957
958                 i++;
959         }
960         RNA_PROP_END;
961 }
962
963 static void search_id_collection(StructRNA *ptype, PointerRNA *ptr, PropertyRNA **prop)
964 {
965         StructRNA *srna;
966
967         /* look for collection property in Main */
968         RNA_main_pointer_create(G.main, ptr);
969
970         *prop= NULL;
971
972         RNA_STRUCT_BEGIN(ptr, iprop) {
973                 /* if it's a collection and has same pointer type, we've got it */
974                 if(RNA_property_type(iprop) == PROP_COLLECTION) {
975                         srna= RNA_property_pointer_type(ptr, iprop);
976
977                         if(ptype == srna) {
978                                 *prop= iprop;
979                                 break;
980                         }
981                 }
982         }
983         RNA_STRUCT_END;
984 }
985
986 void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop)
987 {
988         StructRNA *ptype;
989         PointerRNA sptr;
990
991         /* for ID's we do automatic lookup */
992         if(!searchprop) {
993                 if(RNA_property_type(prop) == PROP_POINTER) {
994                         ptype= RNA_property_pointer_type(ptr, prop);
995                         search_id_collection(ptype, &sptr, &searchprop);
996                         searchptr= &sptr;
997                 }
998         }
999
1000         /* turn button into search button */
1001         if(searchprop) {
1002                 but->type= SEARCH_MENU;
1003                 but->hardmax= MAX2(but->hardmax, 256);
1004                 but->rnasearchpoin= *searchptr;
1005                 but->rnasearchprop= searchprop;
1006                 but->flag |= UI_ICON_LEFT|UI_TEXT_LEFT;
1007
1008                 uiButSetSearchFunc(but, rna_search_cb, but, NULL, NULL);
1009         }
1010 }
1011
1012 void uiItemPointerR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, struct PointerRNA *searchptr, char *searchpropname)
1013 {
1014         PropertyRNA *prop, *searchprop;
1015         PropertyType type;
1016         uiBut *but;
1017         uiBlock *block;
1018         StructRNA *icontype;
1019         int w, h;
1020         
1021         /* validate arguments */
1022         if(!ptr->data || !searchptr->data)
1023                 return;
1024
1025         prop= RNA_struct_find_property(ptr, propname);
1026
1027         if(!prop) {
1028                 printf("uiItemPointerR: property not found: %s\n", propname);
1029                 return;
1030         }
1031         
1032         type= RNA_property_type(prop);
1033         if(!ELEM(type, PROP_POINTER, PROP_STRING)) {
1034                 printf("uiItemPointerR: property %s must be a pointer or string.\n", propname);
1035                 return;
1036         }
1037
1038         searchprop= RNA_struct_find_property(searchptr, searchpropname);
1039
1040         if(!searchprop || RNA_property_type(searchprop) != PROP_COLLECTION) {
1041                 printf("uiItemPointerR: search collection property not found: %s\n", searchpropname);
1042                 return;
1043         }
1044
1045         /* get icon & name */
1046         if(!icon) {
1047                 if(type == PROP_POINTER)
1048                         icontype= RNA_property_pointer_type(ptr, prop);
1049                 else
1050                         icontype= RNA_property_pointer_type(searchptr, searchprop);
1051
1052                 icon= RNA_struct_ui_icon(icontype);
1053         }
1054         if(!name)
1055                 name= (char*)RNA_property_ui_name(prop);
1056
1057         /* create button */
1058         block= uiLayoutGetBlock(layout);
1059
1060         ui_item_rna_size(layout, name, icon, prop, 0, &w, &h);
1061         but= ui_item_with_label(layout, block, name, icon, ptr, prop, 0, 0, 0, w, h);
1062
1063         ui_but_add_search(but, ptr, prop, searchptr, searchprop);
1064 }
1065
1066 /* menu item */
1067 static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt)
1068 {
1069         MenuType *mt= (MenuType*)arg_mt;
1070         Menu menu = {0};
1071
1072         menu.type= mt;
1073         menu.layout= layout;
1074         mt->draw(C, &menu);
1075 }
1076
1077 static void ui_item_menu(uiLayout *layout, char *name, int icon, uiMenuCreateFunc func, void *arg, void *argN)
1078 {
1079         uiBlock *block= layout->root->block;
1080         uiBut *but;
1081         int w, h;
1082
1083         uiBlockSetCurLayout(block, layout);
1084
1085         if(layout->root->type == UI_LAYOUT_HEADER)
1086                 uiBlockSetEmboss(block, UI_EMBOSS);
1087
1088         if(!name)
1089                 name= "";
1090         if(layout->root->type == UI_LAYOUT_MENU && !icon)
1091                 icon= ICON_BLANK1;
1092
1093         w= ui_text_icon_width(layout, name, icon);
1094         h= UI_UNIT_Y;
1095
1096         if(layout->root->type == UI_LAYOUT_HEADER) /* ugly .. */
1097                 w -= 10;
1098
1099         if(icon)
1100                 but= uiDefIconTextMenuBut(block, func, arg, icon, (char*)name, 0, 0, w, h, "");
1101         else
1102                 but= uiDefMenuBut(block, func, arg, (char*)name, 0, 0, w, h, "");
1103
1104         if(argN) { /* ugly .. */
1105                 but->poin= (char*)but;
1106                 but->func_argN= argN;
1107         }
1108
1109         if(layout->root->type == UI_LAYOUT_HEADER)
1110                 uiBlockSetEmboss(block, UI_EMBOSS);
1111         else if(layout->root->type == UI_LAYOUT_PANEL)
1112                 but->type= MENU;
1113 }
1114
1115 void uiItemM(uiLayout *layout, bContext *C, char *name, int icon, char *menuname)
1116 {
1117         ARegion *ar= CTX_wm_region(C);
1118         MenuType *mt;
1119
1120         if(!menuname)
1121                 return;
1122
1123         for(mt=ar->type->menutypes.first; mt; mt=mt->next) {
1124                 if(strcmp(menuname, mt->idname) == 0) {
1125                         if(!name)
1126                                 name= mt->label;
1127                         if(layout->root->type == UI_LAYOUT_MENU && !icon)
1128                                 icon= ICON_BLANK1;
1129                         ui_item_menu(layout, name, icon, ui_item_menutype_func, mt, NULL);
1130                         return;
1131                 }
1132         }
1133
1134         printf("uiItemM: not found %s\n", menuname);
1135 }
1136
1137 /* label item */
1138 void uiItemL(uiLayout *layout, char *name, int icon)
1139 {
1140         uiBlock *block= layout->root->block;
1141         uiBut *but;
1142         int w;
1143
1144         uiBlockSetCurLayout(block, layout);
1145
1146         if(!name)
1147                 name= "";
1148         if(layout->root->type == UI_LAYOUT_MENU && !icon)
1149                 icon= ICON_BLANK1;
1150
1151         w= ui_text_icon_width(layout, name, icon);
1152
1153         if(icon && strcmp(name, "") != 0)
1154                 but= uiDefIconTextBut(block, LABEL, 0, icon, (char*)name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
1155         else if(icon)
1156                 but= uiDefIconBut(block, LABEL, 0, icon, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
1157         else
1158                 but= uiDefBut(block, LABEL, 0, (char*)name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
1159 }
1160
1161 /* value item */
1162 void uiItemV(uiLayout *layout, char *name, int icon, int argval)
1163 {
1164         /* label */
1165         uiBlock *block= layout->root->block;
1166         float *retvalue= (block->handle)? &block->handle->retvalue: NULL;
1167         int w;
1168
1169         uiBlockSetCurLayout(block, layout);
1170
1171         if(!name)
1172                 name= "";
1173         if(layout->root->type == UI_LAYOUT_MENU && !icon)
1174                 icon= ICON_BLANK1;
1175
1176         w= ui_text_icon_width(layout, name, icon);
1177
1178         if(icon && strcmp(name, "") != 0)
1179                 uiDefIconTextButF(block, BUTM, 0, icon, (char*)name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, argval, "");
1180         else if(icon)
1181                 uiDefIconButF(block, BUTM, 0, icon, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, argval, "");
1182         else
1183                 uiDefButF(block, BUTM, 0, (char*)name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, argval, "");
1184 }
1185
1186 /* separator item */
1187 void uiItemS(uiLayout *layout)
1188 {
1189         uiBlock *block= layout->root->block;
1190
1191         uiBlockSetCurLayout(block, layout);
1192         uiDefBut(block, SEPR, 0, "", 0, 0, EM_SEPR_X, EM_SEPR_Y, NULL, 0.0, 0.0, 0, 0, "");
1193 }
1194
1195 /* level items */
1196 void uiItemMenuF(uiLayout *layout, char *name, int icon, uiMenuCreateFunc func)
1197 {
1198         if(!func)
1199                 return;
1200
1201         ui_item_menu(layout, name, icon, func, NULL, NULL);
1202 }
1203
1204 typedef struct MenuItemLevel {
1205         int opcontext;
1206         char *opname;
1207         char *propname;
1208         PointerRNA rnapoin;
1209 } MenuItemLevel;
1210
1211 static void menu_item_enum_opname_menu(bContext *C, uiLayout *layout, void *arg)
1212 {
1213         MenuItemLevel *lvl= (MenuItemLevel*)(((uiBut*)arg)->func_argN);
1214
1215         uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
1216         uiItemsEnumO(layout, lvl->opname, lvl->propname);
1217 }
1218
1219 void uiItemMenuEnumO(uiLayout *layout, char *name, int icon, char *opname, char *propname)
1220 {
1221         wmOperatorType *ot= WM_operatortype_find(opname, 0);
1222         MenuItemLevel *lvl;
1223
1224         if(!ot || !ot->srna) {
1225                 ui_item_disabled(layout, opname);
1226                 return;
1227         }
1228
1229         if(!name)
1230                 name= ot->name;
1231         if(layout->root->type == UI_LAYOUT_MENU && !icon)
1232                 icon= ICON_BLANK1;
1233
1234         lvl= MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
1235         lvl->opname= opname;
1236         lvl->propname= propname;
1237         lvl->opcontext= layout->root->opcontext;
1238
1239         ui_item_menu(layout, name, icon, menu_item_enum_opname_menu, NULL, lvl);
1240 }
1241
1242 static void menu_item_enum_rna_menu(bContext *C, uiLayout *layout, void *arg)
1243 {
1244         MenuItemLevel *lvl= (MenuItemLevel*)(((uiBut*)arg)->func_argN);
1245
1246         uiLayoutSetOperatorContext(layout, lvl->opcontext);
1247         uiItemsEnumR(layout, &lvl->rnapoin, lvl->propname);
1248 }
1249
1250 void uiItemMenuEnumR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname)
1251 {
1252         MenuItemLevel *lvl;
1253         PropertyRNA *prop;
1254
1255         prop= RNA_struct_find_property(ptr, propname);
1256         if(!prop) {
1257                 ui_item_disabled(layout, propname);
1258                 return;
1259         }
1260
1261         if(!name)
1262                 name= (char*)RNA_property_ui_name(prop);
1263         if(layout->root->type == UI_LAYOUT_MENU && !icon)
1264                 icon= ICON_BLANK1;
1265
1266         lvl= MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
1267         lvl->rnapoin= *ptr;
1268         lvl->propname= propname;
1269         lvl->opcontext= layout->root->opcontext;
1270
1271         ui_item_menu(layout, name, icon, menu_item_enum_rna_menu, NULL, lvl);
1272 }
1273
1274 /**************************** Layout Items ***************************/
1275
1276 /* single-row layout */
1277 static void ui_litem_estimate_row(uiLayout *litem)
1278 {
1279         uiItem *item;
1280         int itemw, itemh;
1281
1282         litem->w= 0;
1283         litem->h= 0;
1284
1285         for(item=litem->items.first; item; item=item->next) {
1286                 ui_item_size(item, &itemw, &itemh);
1287
1288                 litem->w += itemw;
1289                 litem->h= MAX2(itemh, litem->h);
1290
1291                 if(item->next)
1292                         litem->w += litem->space;
1293         }
1294 }
1295
1296 static int ui_litem_min_width(int itemw)
1297 {
1298         return MIN2(2*UI_UNIT_X, itemw);
1299 }
1300
1301 static void ui_litem_layout_row(uiLayout *litem)
1302 {
1303         uiItem *item;
1304         int x, y, w, tot, totw, neww, itemw, minw, itemh, offset;
1305         int fixedw, freew, fixedx, freex, flag= 0, lastw= 0;
1306
1307         x= litem->x;
1308         y= litem->y;
1309         w= litem->w;
1310         totw= 0;
1311         tot= 0;
1312
1313         for(item=litem->items.first; item; item=item->next) {
1314                 ui_item_size(item, &itemw, &itemh);
1315                 totw += itemw;
1316                 tot++;
1317         }
1318
1319         if(totw == 0)
1320                 return;
1321         
1322         if(w != 0)
1323                 w -= (tot-1)*litem->space;
1324         fixedw= 0;
1325
1326         /* keep clamping items to fixed minimum size until all are done */
1327         do {
1328                 freew= 0;
1329                 x= 0;
1330                 flag= 0;
1331
1332                 for(item=litem->items.first; item; item=item->next) {
1333                         if(item->flag)
1334                                 continue;
1335
1336                         ui_item_size(item, &itemw, &itemh);
1337                         minw= ui_litem_min_width(itemw);
1338
1339                         if(w - lastw > 0)
1340                                 neww= ui_item_fit(itemw, x, totw, w-lastw, !item->next, litem->alignment, NULL);
1341                         else
1342                                 neww= 0; /* no space left, all will need clamping to minimum size */
1343
1344                         x += neww;
1345
1346                         if((neww < minw || itemw == minw) && w != 0) {
1347                                 /* fixed size */
1348                                 item->flag= 1;
1349                                 fixedw += minw;
1350                                 flag= 1;
1351                                 totw -= itemw;
1352                         }
1353                         else {
1354                                 /* keep free size */
1355                                 item->flag= 0;
1356                                 freew += itemw;
1357                         }
1358                 }
1359
1360                 lastw= fixedw;
1361         } while(flag);
1362
1363         freex= 0;
1364         fixedx= 0;
1365         x= litem->x;
1366
1367         for(item=litem->items.first; item; item=item->next) {
1368                 ui_item_size(item, &itemw, &itemh);
1369                 minw= ui_litem_min_width(itemw);
1370
1371                 if(item->flag) {
1372                         /* fixed minimum size items */
1373                         itemw= ui_item_fit(minw, fixedx, fixedw, MIN2(w, fixedw), !item->next, litem->alignment, NULL);
1374                         fixedx += itemw;
1375                 }
1376                 else {
1377                         /* free size item */
1378                         itemw= ui_item_fit(itemw, freex, freew, w-fixedw, !item->next, litem->alignment, NULL);
1379                         freex += itemw;
1380                 }
1381
1382                 /* align right/center */
1383                 offset= 0;
1384                 if(litem->alignment == UI_LAYOUT_ALIGN_RIGHT) {
1385                         if(fixedw == 0 && freew < w-fixedw)
1386                                 offset= (w - fixedw) - freew;
1387                 }
1388                 else if(litem->alignment == UI_LAYOUT_ALIGN_CENTER) {
1389                         if(fixedw == 0 && freew < w-fixedw)
1390                                 offset= ((w - fixedw) - freew)/2;
1391                 }
1392
1393                 /* position item */
1394                 ui_item_position(item, x+offset, y-itemh, itemw, itemh);
1395
1396                 x += itemw;
1397                 if(item->next)
1398                         x += litem->space;
1399         }
1400
1401         litem->w= x - litem->x;
1402         litem->h= litem->y - y;
1403         litem->x= x;
1404         litem->y= y;
1405 }
1406
1407 /* single-column layout */
1408 static void ui_litem_estimate_column(uiLayout *litem)
1409 {
1410         uiItem *item;
1411         int itemw, itemh;
1412
1413         litem->w= 0;
1414         litem->h= 0;
1415
1416         for(item=litem->items.first; item; item=item->next) {
1417                 ui_item_size(item, &itemw, &itemh);
1418
1419                 litem->w= MAX2(litem->w, itemw);
1420                 litem->h += itemh;
1421
1422                 if(item->next)
1423                         litem->h += litem->space;
1424         }
1425 }
1426
1427 static void ui_litem_layout_column(uiLayout *litem)
1428 {
1429         uiItem *item;
1430         int itemh, x, y;
1431
1432         x= litem->x;
1433         y= litem->y;
1434
1435         for(item=litem->items.first; item; item=item->next) {
1436                 ui_item_size(item, NULL, &itemh);
1437
1438                 y -= itemh;
1439                 ui_item_position(item, x, y, litem->w, itemh);
1440
1441                 if(item->next)
1442                         y -= litem->space;
1443         }
1444
1445         litem->h= litem->y - y;
1446         litem->x= x;
1447         litem->y= y;
1448 }
1449
1450 /* root layout */
1451 static void ui_litem_estimate_root(uiLayout *litem)
1452 {
1453         /* nothing to do */
1454 }
1455
1456 static void ui_litem_layout_root(uiLayout *litem)
1457 {
1458         if(litem->root->type == UI_LAYOUT_HEADER)
1459                 ui_litem_layout_row(litem);
1460         else
1461                 ui_litem_layout_column(litem);
1462 }
1463
1464 /* box layout */
1465 static void ui_litem_estimate_box(uiLayout *litem)
1466 {
1467         uiStyle *style= litem->root->style;
1468
1469         ui_litem_estimate_column(litem);
1470         litem->w += 2*style->boxspace;
1471         litem->h += style->boxspace;
1472 }
1473
1474 static void ui_litem_layout_box(uiLayout *litem)
1475 {
1476         uiLayoutItemBx *box= (uiLayoutItemBx*)litem;
1477         uiStyle *style= litem->root->style;
1478         uiBut *but;
1479         int w, h;
1480
1481         w= litem->w;
1482         h= litem->h;
1483
1484         litem->x += style->boxspace;
1485
1486         if(w != 0) litem->w -= 2*style->boxspace;
1487         if(h != 0) litem->h -= 2*style->boxspace;
1488
1489         ui_litem_layout_column(litem);
1490
1491         litem->x -= style->boxspace;
1492         litem->y -= style->boxspace;
1493
1494         if(w != 0) litem->w += 2*style->boxspace;
1495         if(h != 0) litem->h += style->boxspace;
1496
1497         /* roundbox around the sublayout */
1498         but= box->roundbox;
1499         but->x1= litem->x;
1500         but->y1= litem->y;
1501         but->x2= litem->x+litem->w;
1502         but->y2= litem->y+litem->h;
1503 }
1504
1505 /* multi-column layout, automatically flowing to the next */
1506 static void ui_litem_estimate_column_flow(uiLayout *litem)
1507 {
1508         uiStyle *style= litem->root->style;
1509         uiLayoutItemFlow *flow= (uiLayoutItemFlow*)litem;
1510         uiItem *item;
1511         int col, x, y, emh, emy, miny, itemw, itemh, maxw=0;
1512         int toth, totitem;
1513
1514         /* compute max needed width and total height */
1515         toth= 0;
1516         totitem= 0;
1517         for(item=litem->items.first; item; item=item->next) {
1518                 ui_item_size(item, &itemw, &itemh);
1519                 maxw= MAX2(maxw, itemw);
1520                 toth += itemh;
1521                 totitem++;
1522         }
1523
1524         if(flow->number <= 0) {
1525                 /* auto compute number of columns, not very good */
1526                 if(maxw == 0) {
1527                         flow->totcol= 1;
1528                         return;
1529                 }
1530
1531                 flow->totcol= MAX2(litem->root->emw/maxw, 1);
1532                 flow->totcol= MIN2(flow->totcol, totitem);
1533         }
1534         else
1535                 flow->totcol= flow->number;
1536
1537         /* compute sizes */
1538         x= 0;
1539         y= 0;
1540         emy= 0;
1541         miny= 0;
1542
1543         maxw= 0;
1544         emh= toth/flow->totcol;
1545
1546         /* create column per column */
1547         col= 0;
1548         for(item=litem->items.first; item; item=item->next) {
1549                 ui_item_size(item, &itemw, &itemh);
1550
1551                 y -= itemh + style->buttonspacey;
1552                 miny= MIN2(miny, y);
1553                 emy -= itemh;
1554                 maxw= MAX2(itemw, maxw);
1555
1556                 /* decide to go to next one */
1557                 if(col < flow->totcol-1 && emy <= -emh) {
1558                         x += maxw + litem->space;
1559                         maxw= 0;
1560                         y= 0;
1561                         col++;
1562                 }
1563         }
1564
1565         litem->w= x;
1566         litem->h= litem->y - miny;
1567 }
1568
1569 static void ui_litem_layout_column_flow(uiLayout *litem)
1570 {
1571         uiStyle *style= litem->root->style;
1572         uiLayoutItemFlow *flow= (uiLayoutItemFlow*)litem;
1573         uiItem *item;
1574         int col, x, y, w, emh, emy, miny, itemw, itemh;
1575         int toth, totitem, offset;
1576
1577         /* compute max needed width and total height */
1578         toth= 0;
1579         totitem= 0;
1580         for(item=litem->items.first; item; item=item->next) {
1581                 ui_item_size(item, &itemw, &itemh);
1582                 toth += itemh;
1583                 totitem++;
1584         }
1585
1586         /* compute sizes */
1587         x= litem->x;
1588         y= litem->y;
1589         emy= 0;
1590         miny= 0;
1591
1592         w= litem->w - (flow->totcol-1)*style->columnspace;
1593         emh= toth/flow->totcol;
1594
1595         /* create column per column */
1596         col= 0;
1597         for(item=litem->items.first; item; item=item->next) {
1598                 ui_item_size(item, NULL, &itemh);
1599                 itemw= ui_item_fit(1, x-litem->x, flow->totcol, w, col == flow->totcol-1, litem->alignment, &offset);
1600         
1601                 y -= itemh;
1602                 emy -= itemh;
1603                 ui_item_position(item, x+offset, y, itemw, itemh);
1604                 y -= style->buttonspacey;
1605                 miny= MIN2(miny, y);
1606
1607                 /* decide to go to next one */
1608                 if(col < flow->totcol-1 && emy <= -emh) {
1609                         x += itemw + style->columnspace;
1610                         y= litem->y;
1611                         col++;
1612                 }
1613         }
1614
1615         litem->h= litem->y - miny;
1616         litem->x= x;
1617         litem->y= miny;
1618 }
1619
1620 /* free layout */
1621 static void ui_litem_estimate_free(uiLayout *litem)
1622 {
1623         uiItem *item;
1624         int itemx, itemy, itemw, itemh, minx, miny;
1625
1626         minx= 1e6;
1627         miny= 1e6;
1628         litem->w= 0;
1629         litem->h= 0;
1630
1631         for(item=litem->items.first; item; item=item->next) {
1632                 ui_item_offset(item, &itemx, &itemy);
1633                 ui_item_size(item, &itemw, &itemh);
1634
1635                 minx= MIN2(minx, itemx);
1636                 miny= MIN2(miny, itemy);
1637
1638                 litem->w= MAX2(litem->w, itemx+itemw);
1639                 litem->h= MAX2(litem->h, itemy+itemh);
1640         }
1641
1642         litem->w -= minx;
1643         litem->h -= miny;
1644 }
1645
1646 static void ui_litem_layout_free(uiLayout *litem)
1647 {
1648         uiItem *item;
1649         float scalex=1.0f, scaley=1.0f;
1650         int x, y, newx, newy, itemx, itemy, itemh, itemw, minx, miny, totw, toth;
1651
1652         minx= 1e6;
1653         miny= 1e6;
1654         totw= 0;
1655         toth= 0;
1656
1657         for(item=litem->items.first; item; item=item->next) {
1658                 ui_item_offset(item, &itemx, &itemy);
1659                 ui_item_size(item, &itemw, &itemh);
1660
1661                 minx= MIN2(minx, itemx);
1662                 miny= MIN2(miny, itemy);
1663
1664                 totw= MAX2(totw, itemx+itemw);
1665                 toth= MAX2(toth, itemy+itemh);
1666         }
1667
1668         totw -= minx;
1669         toth -= miny;
1670
1671         if(litem->w && totw > 0)
1672                 scalex= (float)litem->w/(float)totw;
1673         if(litem->h && toth > 0)
1674                 scaley= (float)litem->h/(float)toth;
1675         
1676         x= litem->x;
1677         y= litem->y - scaley*toth;
1678
1679         for(item=litem->items.first; item; item=item->next) {
1680                 ui_item_offset(item, &itemx, &itemy);
1681                 ui_item_size(item, &itemw, &itemh);
1682
1683                 if(scalex != 1.0f) {
1684                         newx= (itemx - minx)*scalex;
1685                         itemw= (itemx - minx + itemw)*scalex - newx;
1686                         itemx= minx + newx;
1687                 }
1688
1689                 if(scaley != 1.0f) {
1690                         newy= (itemy - miny)*scaley;
1691                         itemh= (itemy - miny + itemh)*scaley - newy;
1692                         itemy= miny + newy;
1693                 }
1694
1695                 ui_item_position(item, x+itemx-minx, y+itemy-miny, itemw, itemh);
1696         }
1697
1698         litem->w= scalex*totw;
1699         litem->h= litem->y - y;
1700         litem->x= x + litem->w;
1701         litem->y= y;
1702 }
1703
1704 /* split layout */
1705 static void ui_litem_estimate_split(uiLayout *litem)
1706 {
1707         ui_litem_estimate_row(litem);
1708 }
1709
1710 static void ui_litem_layout_split(uiLayout *litem)
1711 {
1712         uiLayoutItemSplt *split= (uiLayoutItemSplt*)litem;
1713         uiItem *item;
1714         float percentage;
1715         int itemh, x, y, w, tot=0, colw=0;
1716
1717         x= litem->x;
1718         y= litem->y;
1719
1720         for(item=litem->items.first; item; item=item->next)
1721                 tot++;
1722         
1723         if(tot == 0)
1724                 return;
1725         
1726         percentage= (split->percentage == 0.0f)? 1.0f/(float)tot: split->percentage;
1727         
1728         w= (litem->w - (tot-1)*litem->space);
1729         colw= w*percentage;
1730         colw= MAX2(colw, 0);
1731
1732         for(item=litem->items.first; item; item=item->next) {
1733                 ui_item_size(item, NULL, &itemh);
1734
1735                 ui_item_position(item, x, y-itemh, colw, itemh);
1736                 x += colw;
1737
1738                 if(item->next) {
1739                         colw= (w - (int)(w*percentage))/(tot-1);
1740                         colw= MAX2(colw, 0);
1741
1742                         x += litem->space;
1743                 }
1744         }
1745
1746         litem->w= x - litem->x;
1747         litem->h= litem->y - y;
1748         litem->x= x;
1749         litem->y= y;
1750 }
1751
1752 /* layout create functions */
1753 uiLayout *uiLayoutRow(uiLayout *layout, int align)
1754 {
1755         uiLayout *litem;
1756
1757         litem= MEM_callocN(sizeof(uiLayout), "uiLayoutRow");
1758         litem->item.type= ITEM_LAYOUT_ROW;
1759         litem->root= layout->root;
1760         litem->align= align;
1761         litem->active= 1;
1762         litem->enabled= 1;
1763         litem->context= layout->context;
1764         litem->space= (align)? 0: layout->root->style->buttonspacex;
1765         BLI_addtail(&layout->items, litem);
1766
1767         uiBlockSetCurLayout(layout->root->block, litem);
1768
1769         return litem;
1770 }
1771
1772 uiLayout *uiLayoutColumn(uiLayout *layout, int align)
1773 {
1774         uiLayout *litem;
1775
1776         litem= MEM_callocN(sizeof(uiLayout), "uiLayoutColumn");
1777         litem->item.type= ITEM_LAYOUT_COLUMN;
1778         litem->root= layout->root;
1779         litem->align= align;
1780         litem->active= 1;
1781         litem->enabled= 1;
1782         litem->context= layout->context;
1783         litem->space= (litem->align)? 0: layout->root->style->buttonspacey;
1784         BLI_addtail(&layout->items, litem);
1785
1786         uiBlockSetCurLayout(layout->root->block, litem);
1787
1788         return litem;
1789 }
1790
1791 uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align)
1792 {
1793         uiLayoutItemFlow *flow;
1794
1795         flow= MEM_callocN(sizeof(uiLayoutItemFlow), "uiLayoutItemFlow");
1796         flow->litem.item.type= ITEM_LAYOUT_COLUMN_FLOW;
1797         flow->litem.root= layout->root;
1798         flow->litem.align= align;
1799         flow->litem.active= 1;
1800         flow->litem.enabled= 1;
1801         flow->litem.context= layout->context;
1802         flow->litem.space= (flow->litem.align)? 0: layout->root->style->columnspace;
1803         flow->number= number;
1804         BLI_addtail(&layout->items, flow);
1805
1806         uiBlockSetCurLayout(layout->root->block, &flow->litem);
1807
1808         return &flow->litem;
1809 }
1810
1811 uiLayout *uiLayoutBox(uiLayout *layout)
1812 {
1813         uiLayoutItemBx *box;
1814
1815         box= MEM_callocN(sizeof(uiLayoutItemBx), "uiLayoutItemBx");
1816         box->litem.item.type= ITEM_LAYOUT_BOX;
1817         box->litem.root= layout->root;
1818         box->litem.active= 1;
1819         box->litem.enabled= 1;
1820         box->litem.context= layout->context;
1821         box->litem.space= layout->root->style->columnspace;
1822         BLI_addtail(&layout->items, box);
1823
1824         uiBlockSetCurLayout(layout->root->block, &box->litem);
1825
1826         box->roundbox= uiDefBut(layout->root->block, ROUNDBOX, 0, "", 0, 0, 0, 0, NULL, 0.0, 0.0, 0, 0, "");
1827
1828         return &box->litem;
1829 }
1830
1831 uiLayout *uiLayoutFree(uiLayout *layout, int align)
1832 {
1833         uiLayout *litem;
1834
1835         litem= MEM_callocN(sizeof(uiLayout), "uiLayoutFree");
1836         litem->item.type= ITEM_LAYOUT_FREE;
1837         litem->root= layout->root;
1838         litem->align= align;
1839         litem->active= 1;
1840         litem->enabled= 1;
1841         litem->context= layout->context;
1842         BLI_addtail(&layout->items, litem);
1843
1844         uiBlockSetCurLayout(layout->root->block, litem);
1845
1846         return litem;
1847 }
1848
1849 uiBlock *uiLayoutFreeBlock(uiLayout *layout)
1850 {
1851         uiBlock *block;
1852
1853         block= uiLayoutGetBlock(layout);
1854         uiLayoutFree(layout, 0);
1855
1856         return block;
1857 }
1858
1859 uiLayout *uiLayoutSplit(uiLayout *layout, float percentage)
1860 {
1861         uiLayoutItemSplt *split;
1862
1863         split= MEM_callocN(sizeof(uiLayoutItemSplt), "uiLayoutItemSplt");
1864         split->litem.item.type= ITEM_LAYOUT_SPLIT;
1865         split->litem.root= layout->root;
1866         split->litem.active= 1;
1867         split->litem.enabled= 1;
1868         split->litem.context= layout->context;
1869         split->litem.space= layout->root->style->columnspace;
1870         split->percentage= percentage;
1871         BLI_addtail(&layout->items, split);
1872
1873         uiBlockSetCurLayout(layout->root->block, &split->litem);
1874
1875         return &split->litem;
1876 }
1877
1878 void uiLayoutSetActive(uiLayout *layout, int active)
1879 {
1880         layout->active= active;
1881 }
1882
1883 void uiLayoutSetEnabled(uiLayout *layout, int enabled)
1884 {
1885         layout->enabled= enabled;
1886 }
1887
1888 void uiLayoutSetRedAlert(uiLayout *layout, int redalert)
1889 {
1890         layout->redalert= redalert;
1891 }
1892
1893 void uiLayoutSetKeepAspect(uiLayout *layout, int keepaspect)
1894 {
1895         layout->keepaspect= keepaspect;
1896 }
1897
1898 void uiLayoutSetAlignment(uiLayout *layout, int alignment)
1899 {
1900         layout->alignment= alignment;
1901 }
1902
1903 void uiLayoutSetScaleX(uiLayout *layout, float scale)
1904 {
1905         layout->scale[0]= scale;
1906 }
1907
1908 void uiLayoutSetScaleY(uiLayout *layout, float scale)
1909 {
1910         layout->scale[1]= scale;
1911 }
1912
1913 int uiLayoutGetActive(uiLayout *layout)
1914 {
1915         return layout->active;
1916 }
1917
1918 int uiLayoutGetEnabled(uiLayout *layout)
1919 {
1920         return layout->enabled;
1921 }
1922
1923 int uiLayoutGetRedAlert(uiLayout *layout)
1924 {
1925         return layout->redalert;
1926 }
1927
1928 int uiLayoutGetKeepAspect(uiLayout *layout)
1929 {
1930         return layout->keepaspect;
1931 }
1932
1933 int uiLayoutGetAlignment(uiLayout *layout)
1934 {
1935         return layout->alignment;
1936 }
1937
1938 float uiLayoutGetScaleX(uiLayout *layout)
1939 {
1940         return layout->scale[0];
1941 }
1942
1943 float uiLayoutGetScaleY(uiLayout *layout)
1944 {
1945         return layout->scale[0];
1946 }
1947
1948 /********************** Layout *******************/
1949
1950 static void ui_item_scale(uiLayout *litem, float scale[2])
1951 {
1952         uiItem *item;
1953         int x, y, w, h;
1954
1955         for(item=litem->items.last; item; item=item->prev) {
1956                 ui_item_size(item, &w, &h);
1957                 ui_item_offset(item, &x, &y);
1958
1959                 if(scale[0] != 0.0f) {
1960                         x *= scale[0];
1961                         w *= scale[0];
1962                 }
1963
1964                 if(scale[1] != 0.0f) {
1965                         y *= scale[1];
1966                         h *= scale[1];
1967                 }
1968
1969                 ui_item_position(item, x, y, w, h);
1970         }
1971 }
1972
1973 static void ui_item_estimate(uiItem *item)
1974 {
1975         uiItem *subitem;
1976
1977         if(item->type != ITEM_BUTTON) {
1978                 uiLayout *litem= (uiLayout*)item;
1979
1980                 for(subitem=litem->items.first; subitem; subitem=subitem->next)
1981                         ui_item_estimate(subitem);
1982
1983                 if(litem->items.first == NULL)
1984                         return;
1985
1986                 if(litem->scale[0] != 0.0f || litem->scale[1] != 0.0f)
1987                         ui_item_scale(litem, litem->scale);
1988
1989                 switch(litem->item.type) {
1990                         case ITEM_LAYOUT_COLUMN:
1991                                 ui_litem_estimate_column(litem);
1992                                 break;
1993                         case ITEM_LAYOUT_COLUMN_FLOW:
1994                                 ui_litem_estimate_column_flow(litem);
1995                                 break;
1996                         case ITEM_LAYOUT_ROW:
1997                                 ui_litem_estimate_row(litem);
1998                                 break;
1999                         case ITEM_LAYOUT_BOX:
2000                                 ui_litem_estimate_box(litem);
2001                                 break;
2002                         case ITEM_LAYOUT_ROOT:
2003                                 ui_litem_estimate_root(litem);
2004                                 break;
2005                         case ITEM_LAYOUT_FREE:
2006                                 ui_litem_estimate_free(litem);
2007                                 break;
2008                         case ITEM_LAYOUT_SPLIT:
2009                                 ui_litem_estimate_split(litem);
2010                                 break;
2011                         default:
2012                                 break;
2013                 }
2014         }
2015 }
2016
2017 static void ui_item_align(uiLayout *litem, int nr)
2018 {
2019         uiItem *item;
2020         uiButtonItem *bitem;
2021         uiLayoutItemBx *box;
2022
2023         for(item=litem->items.last; item; item=item->prev) {
2024                 if(item->type == ITEM_BUTTON) {
2025                         bitem= (uiButtonItem*)item;
2026                         if(ui_but_can_align(bitem->but))
2027                                 if(!bitem->but->alignnr)
2028                                         bitem->but->alignnr= nr;
2029                 }
2030                 else if(item->type == ITEM_LAYOUT_FREE);
2031                 else if(item->type == ITEM_LAYOUT_BOX) {
2032                         box= (uiLayoutItemBx*)item;
2033                         box->roundbox->alignnr= nr;
2034                         BLI_remlink(&litem->root->block->buttons, box->roundbox);
2035                         BLI_addhead(&litem->root->block->buttons, box->roundbox);
2036                 }
2037                 else
2038                         ui_item_align((uiLayout*)item, nr);
2039         }
2040 }
2041
2042 static void ui_item_flag(uiLayout *litem, int flag)
2043 {
2044         uiItem *item;
2045         uiButtonItem *bitem;
2046
2047         for(item=litem->items.last; item; item=item->prev) {
2048                 if(item->type == ITEM_BUTTON) {
2049                         bitem= (uiButtonItem*)item;
2050                         bitem->but->flag |= flag;
2051                 }
2052                 else
2053                         ui_item_flag((uiLayout*)item, flag);
2054         }
2055 }
2056
2057 static void ui_item_layout(uiItem *item)
2058 {
2059         uiItem *subitem;
2060
2061         if(item->type != ITEM_BUTTON) {
2062                 uiLayout *litem= (uiLayout*)item;
2063
2064                 if(litem->items.first == NULL)
2065                         return;
2066
2067                 if(litem->align)
2068                         ui_item_align(litem, ++litem->root->block->alignnr);
2069                 if(!litem->active)
2070                         ui_item_flag(litem, UI_BUT_INACTIVE);
2071                 if(!litem->enabled)
2072                         ui_item_flag(litem, UI_BUT_DISABLED);
2073
2074                 switch(litem->item.type) {
2075                         case ITEM_LAYOUT_COLUMN:
2076                                 ui_litem_layout_column(litem);
2077                                 break;
2078                         case ITEM_LAYOUT_COLUMN_FLOW:
2079                                 ui_litem_layout_column_flow(litem);
2080                                 break;
2081                         case ITEM_LAYOUT_ROW:
2082                                 ui_litem_layout_row(litem);
2083                                 break;
2084                         case ITEM_LAYOUT_BOX:
2085                                 ui_litem_layout_box(litem);
2086                                 break;
2087                         case ITEM_LAYOUT_ROOT:
2088                                 ui_litem_layout_root(litem);
2089                                 break;
2090                         case ITEM_LAYOUT_FREE:
2091                                 ui_litem_layout_free(litem);
2092                                 break;
2093                         case ITEM_LAYOUT_SPLIT:
2094                                 ui_litem_layout_split(litem);
2095                                 break;
2096                         default:
2097                                 break;
2098                 }
2099
2100                 for(subitem=litem->items.first; subitem; subitem=subitem->next)
2101                         ui_item_layout(subitem);
2102         }
2103 }
2104
2105 static void ui_layout_items(const bContext *C, uiBlock *block, uiLayout *layout)
2106 {
2107         ui_item_estimate(&layout->item);
2108         ui_item_layout(&layout->item);
2109 }
2110
2111 static void ui_layout_end(const bContext *C, uiBlock *block, uiLayout *layout, int *x, int *y)
2112 {
2113         if(layout->root->handlefunc)
2114                 uiBlockSetButmFunc(block, layout->root->handlefunc, layout->root->argv);
2115
2116         ui_layout_items(C, block, layout);
2117
2118         if(x) *x= layout->x;
2119         if(y) *y= layout->y;
2120 }
2121
2122 static void ui_layout_free(uiLayout *layout)
2123 {
2124         uiItem *item, *next;
2125
2126         for(item=layout->items.first; item; item=next) {
2127                 next= item->next;
2128
2129                 if(item->type == ITEM_BUTTON)
2130                         MEM_freeN(item);
2131                 else
2132                         ui_layout_free((uiLayout*)item);
2133         }
2134
2135         MEM_freeN(layout);
2136 }
2137
2138 uiLayout *uiBlockLayout(uiBlock *block, int dir, int type, int x, int y, int size, int em, uiStyle *style)
2139 {
2140         uiLayout *layout;
2141         uiLayoutRoot *root;
2142
2143         root= MEM_callocN(sizeof(uiLayoutRoot), "uiLayoutRoot");
2144         root->type= type;
2145         root->style= style;
2146         root->block= block;
2147         root->opcontext= WM_OP_INVOKE_REGION_WIN;
2148
2149         layout= MEM_callocN(sizeof(uiLayout), "uiLayout");
2150         layout->item.type= ITEM_LAYOUT_ROOT;
2151
2152         layout->x= x;
2153         layout->y= y;
2154         layout->root= root;
2155         layout->space= style->templatespace;
2156         layout->active= 1;
2157         layout->enabled= 1;
2158         layout->context= NULL;
2159
2160         if(type == UI_LAYOUT_MENU)
2161                 layout->space= 0;
2162
2163         if(dir == UI_LAYOUT_HORIZONTAL) {
2164                 layout->h= size;
2165                 layout->root->emh= em*UI_UNIT_Y;
2166         }
2167         else {
2168                 layout->w= size;
2169                 layout->root->emw= em*UI_UNIT_X;
2170         }
2171
2172         block->curlayout= layout;
2173         root->layout= layout;
2174         BLI_addtail(&block->layouts, root);
2175         
2176         return layout;
2177 }
2178
2179 uiBlock *uiLayoutGetBlock(uiLayout *layout)
2180 {
2181         return layout->root->block;
2182 }
2183
2184 int uiLayoutGetOperatorContext(uiLayout *layout)
2185 {
2186         return layout->root->opcontext;
2187 }
2188
2189
2190 void uiBlockSetCurLayout(uiBlock *block, uiLayout *layout)
2191 {
2192         block->curlayout= layout;
2193 }
2194
2195 void ui_layout_add_but(uiLayout *layout, uiBut *but)
2196 {
2197         uiButtonItem *bitem;
2198         
2199         bitem= MEM_callocN(sizeof(uiButtonItem), "uiButtonItem");
2200         bitem->item.type= ITEM_BUTTON;
2201         bitem->but= but;
2202         BLI_addtail(&layout->items, bitem);
2203
2204         if(layout->context) {
2205                 but->context= layout->context;
2206                 but->context->used= 1;
2207         }
2208 }
2209
2210 void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext)
2211 {
2212         layout->root->opcontext= opcontext;
2213 }
2214
2215 void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv)
2216 {
2217         layout->root->handlefunc= handlefunc;
2218         layout->root->argv= argv;
2219 }
2220
2221 void uiBlockLayoutResolve(const bContext *C, uiBlock *block, int *x, int *y)
2222 {
2223         uiLayoutRoot *root;
2224
2225         if(x) *x= 0;
2226         if(y) *y= 0;
2227
2228         block->curlayout= NULL;
2229
2230         for(root=block->layouts.first; root; root=root->next) {
2231                 /* NULL in advance so we don't interfere when adding button */
2232                 ui_layout_end(C, block, root->layout, x, y);
2233                 ui_layout_free(root->layout);
2234         }
2235
2236         BLI_freelistN(&block->layouts);
2237
2238         /* XXX silly trick, interface_templates.c doesn't get linked
2239          * because it's not used by other files in this module? */
2240         {
2241                 void ui_template_fix_linking();
2242                 ui_template_fix_linking();
2243         }
2244 }
2245
2246 void uiLayoutSetContextPointer(uiLayout *layout, char *name, PointerRNA *ptr)
2247 {
2248         uiBlock *block= layout->root->block;
2249         layout->context= CTX_store_add(&block->contexts, name, ptr);
2250 }
2251