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