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