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