Merge with 2.5 -r 21619:21756.
[blender.git] / source / blender / editors / interface / interface_layout.c
index b3216412b68439ae0ac606ec5d9febf9820a905e..07fe2686317d953f4a131739dab79d14fe4717b9 100644 (file)
@@ -1,3 +1,26 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * Contributor(s): Blender Foundation 2009.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
 
 #include <limits.h>
 #include <math.h>
 #include "DNA_ID.h"
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
 #include "DNA_windowmanager_types.h"
 
 #include "BLI_listbase.h"
+#include "BLI_string.h"
 
 #include "BKE_context.h"
 #include "BKE_global.h"
 #include "BKE_idprop.h"
+#include "BKE_library.h"
 #include "BKE_screen.h"
 #include "BKE_utildefines.h"
 
@@ -25,8 +51,6 @@
 #include "UI_resources.h"
 #include "UI_view2d.h"
 
-#include "BIF_gl.h"
-
 #include "ED_util.h"
 #include "ED_types.h"
 #include "ED_screen.h"
 
 /************************ Structs and Defines *************************/
 
-#define COLUMN_SPACE   5
-#define TEMPLATE_SPACE 5
-#define BOX_SPACE              5
-#define BUTTON_SPACE_X 5
-#define BUTTON_SPACE_Y 2
-
 #define RNA_NO_INDEX   -1
+#define RNA_ENUM_VALUE -2
 
-#define EM_UNIT_X              XIC
-#define EM_UNIT_Y              YIC
-
-/* Item */
-
-typedef enum uiItemType {
-       ITEM_OPERATOR,
-       ITEM_RNA_PROPERTY,
-       ITEM_MENU,
-       ITEM_LABEL
-} uiItemType;
-
-enum uiItemFlag {
-       ITEM_ICON,
-       ITEM_TEXT
-};
+#define EM_SEPR_X              6
+#define EM_SEPR_Y              6
 
-typedef struct uiItem {
-       struct uiItem *next, *prev;
-       uiItemType type;
-       int slot;
+/* uiLayoutRoot */
 
-       char *name;
-       int icon;
-} uiItem;
+typedef struct uiLayoutRoot {
+       struct uiLayoutRoot *next, *prev;
 
-typedef struct uiItemRNA {
-       uiItem item;
+       int type;
+       int opcontext;
 
-       PointerRNA ptr;
-       PropertyRNA *prop;
-       int index;
-       int expand;
-} uiItemRNA;
+       int emw, emh;
 
-typedef struct uiItemOp {
-       uiItem item;
+       uiMenuHandleFunc handlefunc;
+       void *argv;
 
-       wmOperatorType *ot;
-       IDProperty *properties;
-       int context;
-} uiItemOp;
+       uiStyle *style;
+       uiBlock *block;
+       uiLayout *layout;
+} uiLayoutRoot;
 
-typedef struct uiItemLMenu {
-       uiItem item;
+/* Item */
 
-       uiMenuCreateFunc func;
-} uiItemLMenu;
+typedef enum uiItemType {
+       ITEM_BUTTON,
 
-/* Template */
+       ITEM_LAYOUT_ROW,
+       ITEM_LAYOUT_COLUMN,
+       ITEM_LAYOUT_COLUMN_FLOW,
+       ITEM_LAYOUT_ROW_FLOW,
+       ITEM_LAYOUT_BOX,
+       ITEM_LAYOUT_FREE,
+       ITEM_LAYOUT_SPLIT,
 
-typedef enum uiTemplateType {
-       TEMPLATE_ROW,
-       TEMPLATE_COLUMN,
+       ITEM_LAYOUT_ROOT
+#if 0
        TEMPLATE_COLUMN_FLOW,
        TEMPLATE_SPLIT,
        TEMPLATE_BOX,
 
-       TEMPLATE_HEADER_MENUS,
-       TEMPLATE_HEADER_BUTTONS,
+       TEMPLATE_HEADER,
        TEMPLATE_HEADER_ID
-} uiTemplateType;
+#endif
+} uiItemType;
+
+typedef struct uiItem {
+       void *next, *prev;
+       uiItemType type;
+       int flag;
+} uiItem;
 
-typedef struct uiTemplate {
-       struct uiTemplate *next, *prev;
-       uiTemplateType type;
+typedef struct uiButtonItem {
+       uiItem item;
+       uiBut *but;
+} uiButtonItem;
+
+struct uiLayout {
+       uiItem item;
 
+       uiLayoutRoot *root;
+       bContextStore *context;
        ListBase items;
-       int color, slot;
-} uiTemplate;
 
-typedef struct uiTemplateFlow {
-       uiTemplate template;
-       int number;
-} uiTemplateFlow;
+       int x, y, w, h;
+       float scale[2];
+       short space;
+       char align;
+       char active;
+       char enabled;
+       char redalert;
+       char keepaspect;
+       char alignment;
+};
 
-typedef struct uiTemplateSplt {
-       uiTemplate template;
+typedef struct uiLayoutItemFlow {
+       uiLayout litem;
        int number;
-       int lr;
-       uiLayout **sublayout;
-} uiTemplateSplt;
-
-typedef struct uiTemplateBx {
-       uiTemplate template;
-       uiLayout *sublayout;
-} uiTemplateBx;
+       int totcol;
+} uiLayoutItemFlow;
 
-typedef struct uiTemplateHeadID {
-       uiTemplate template;
+typedef struct uiLayoutItemBx {
+       uiLayout litem;
+       uiBut *roundbox;
+       ListBase items;
+} uiLayoutItemBx;
 
-       PointerRNA ptr;
-       char *propname;
-       int flag;
-       uiIDPoinFunc func;
-} uiTemplateHeadID;
+typedef struct uiLayoutItemSplt {
+       uiLayout litem;
+       float percentage;
+} uiLayoutItemSplt;
 
-/* Layout */
+typedef struct uiLayoutItemRoot {
+       uiLayout litem;
+} uiLayoutItemRoot;
 
-struct uiLayout {
-       ListBase templates;
-       int opcontext;
-       int dir;
-       int x, y, w, h;
-       int emw, emh;
-};
+/************************** Item ***************************/
 
-void ui_layout_free(uiLayout *layout);
-void ui_layout_end(const bContext *C, uiBlock *block, uiLayout *layout, int *x, int *y);
+static char *ui_item_name_add_colon(char *name, char namestr[UI_MAX_NAME_STR])
+{
+       int len= strlen(name);
 
-/************************** Item ***************************/
+       if(len != 0 && len+1 < UI_MAX_NAME_STR) {
+               BLI_strncpy(namestr, name, UI_MAX_NAME_STR);
+               namestr[len]= ':';
+               namestr[len+1]= '\0';
+               return namestr;
+       }
 
-#define UI_FIT_EXPAND 1
+       return name;
+}
 
-static int ui_item_fit(int item, int pos, int all, int available, int last, int flag)
+static int ui_item_fit(int item, int pos, int all, int available, int last, int alignment, int *offset)
 {
+       /* available == 0 is unlimited */
+       if(available == 0)
+               return item;
+       
+       if(offset)
+               *offset= 0;
+       
        if(all > available) {
                /* contents is bigger than available space */
                if(last)
@@ -171,7 +194,7 @@ static int ui_item_fit(int item, int pos, int all, int available, int last, int
        }
        else {
                /* contents is smaller or equal to available space */
-               if(flag & UI_FIT_EXPAND) {
+               if(alignment == UI_LAYOUT_ALIGN_EXPAND) {
                        if(last)
                                return available-pos;
                        else
@@ -182,59 +205,165 @@ static int ui_item_fit(int item, int pos, int all, int available, int last, int
        }
 }
 
+/* variable button size in which direction? */
+#define UI_ITEM_VARY_X 1
+#define UI_ITEM_VARY_Y 2
+
+static int ui_layout_vary_direction(uiLayout *layout)
+{
+       return (layout->root->type == UI_LAYOUT_HEADER || layout->alignment != UI_LAYOUT_ALIGN_EXPAND)? UI_ITEM_VARY_X: UI_ITEM_VARY_Y;
+}
+
+/* estimated size of text + icon */
+static int ui_text_icon_width(uiLayout *layout, char *name, int icon)
+{
+       int variable = ui_layout_vary_direction(layout) == UI_ITEM_VARY_X;
+
+       if(icon && !name[0])
+               return UI_UNIT_X; /* icon only */
+       else if(icon)
+               return (variable)? UI_GetStringWidth(name) + 4 + UI_UNIT_X: 10*UI_UNIT_X; /* icon + text */
+       else
+               return (variable)? UI_GetStringWidth(name) + 4 + UI_UNIT_X: 10*UI_UNIT_X; /* text only */
+}
+
+static void ui_item_size(uiItem *item, int *r_w, int *r_h)
+{
+       if(item->type == ITEM_BUTTON) {
+               uiButtonItem *bitem= (uiButtonItem*)item;
+
+               if(r_w) *r_w= bitem->but->x2 - bitem->but->x1;
+               if(r_h) *r_h= bitem->but->y2 - bitem->but->y1;
+       }
+       else {
+               uiLayout *litem= (uiLayout*)item;
+
+               if(r_w) *r_w= litem->w;
+               if(r_h) *r_h= litem->h;
+       }
+}
+
+static void ui_item_offset(uiItem *item, int *r_x, int *r_y)
+{
+       if(item->type == ITEM_BUTTON) {
+               uiButtonItem *bitem= (uiButtonItem*)item;
+
+               if(r_x) *r_x= bitem->but->x1;
+               if(r_y) *r_y= bitem->but->y1;
+       }
+       else {
+               if(r_x) *r_x= 0;
+               if(r_y) *r_y= 0;
+       }
+}
+
+static void ui_item_position(uiItem *item, int x, int y, int w, int h)
+{
+       if(item->type == ITEM_BUTTON) {
+               uiButtonItem *bitem= (uiButtonItem*)item;
+
+               bitem->but->x1= x;
+               bitem->but->y1= y;
+               bitem->but->x2= x+w;
+               bitem->but->y2= y+h;
+               
+               ui_check_but(bitem->but); /* for strlen */
+       }
+       else {
+               uiLayout *litem= (uiLayout*)item;
+
+               litem->x= x;
+               litem->y= y+h;
+               litem->w= w;
+               litem->h= h;
+       }
+}
+
+/******************** Special RNA Items *********************/
+
+static int ui_layout_local_dir(uiLayout *layout)
+{
+       switch(layout->item.type) {
+               case ITEM_LAYOUT_ROW:
+               case ITEM_LAYOUT_ROOT:
+                       return UI_LAYOUT_HORIZONTAL;
+               case ITEM_LAYOUT_COLUMN:
+               case ITEM_LAYOUT_COLUMN_FLOW:
+               case ITEM_LAYOUT_SPLIT:
+               case ITEM_LAYOUT_FREE:
+               case ITEM_LAYOUT_BOX:
+               default:
+                       return UI_LAYOUT_VERTICAL;
+       }
+}
+
+static uiLayout *ui_item_local_sublayout(uiLayout *test, uiLayout *layout, int align)
+{
+       uiLayout *sub;
+
+       if(ui_layout_local_dir(test) == UI_LAYOUT_HORIZONTAL)
+               sub= uiLayoutRow(layout, align);
+       else
+               sub= uiLayoutColumn(layout, align);
+       
+       sub->space= 0;
+       return sub;
+}
+
 /* create buttons for an item with an RNA array */
-static void ui_item_array(uiBlock *block, uiItemRNA *rnaitem, int len, int x, int y, int w, int h)
+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)
 {
+       uiStyle *style= layout->root->style;
+       uiBut *but;
        PropertyType type;
        PropertySubType subtype;
-       char *name;
+       uiLayout *sub;
        int a;
 
        /* retrieve type and subtype */
-       type= RNA_property_type(&rnaitem->ptr, rnaitem->prop);
-       subtype= RNA_property_subtype(&rnaitem->ptr, rnaitem->prop);
+       type= RNA_property_type(prop);
+       subtype= RNA_property_subtype(prop);
 
-       /* create label */
-       if(rnaitem->item.name)
-               name= (char*)rnaitem->item.name;
-       else
-               name= (char*)RNA_property_ui_name(&rnaitem->ptr, rnaitem->prop);
+       sub= ui_item_local_sublayout(layout, layout, 1);
+       uiBlockSetCurLayout(block, sub);
 
+       /* create label */
        if(strcmp(name, "") != 0)
-               uiDefBut(block, LABEL, 0, name, x, y + h - EM_UNIT_Y, w, EM_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+               uiDefBut(block, LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
 
        /* create buttons */
-       uiBlockBeginAlign(block);
-
        if(type == PROP_BOOLEAN && len == 20) {
                /* special check for layer layout */
-               int butw, buth;
+               int butw, buth, unit;
 
-               butw= ui_item_fit(EM_UNIT_X, 0, EM_UNIT_X*10 + BUTTON_SPACE_X, w, 0, UI_FIT_EXPAND);
-               buth= MIN2(EM_UNIT_Y, butw);
+               uiBlockSetCurLayout(block, uiLayoutFree(layout, 0));
 
-               y += 2*(EM_UNIT_Y - buth);
+               unit= UI_UNIT_X*0.75;
+               butw= unit;
+               buth= unit;
 
                uiBlockBeginAlign(block);
                for(a=0; a<5; a++)
-                       uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a, "", ICON_BLANK1, x + butw*a, y+buth, butw, buth);
+                       uiDefAutoButR(block, ptr, prop, a, "", ICON_BLANK1, x + butw*a, y+buth, butw, buth);
                for(a=0; a<5; a++)
-                       uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a+10, "", ICON_BLANK1, x + butw*a, y, butw, buth);
+                       uiDefAutoButR(block, ptr, prop, a+10, "", ICON_BLANK1, x + butw*a, y, butw, buth);
                uiBlockEndAlign(block);
 
-               x += 5*butw + BUTTON_SPACE_X;
+               x += 5*butw + style->buttonspacex;
 
                uiBlockBeginAlign(block);
                for(a=0; a<5; a++)
-                       uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a+5, "", ICON_BLANK1, x + butw*a, y+buth, butw, buth);
+                       uiDefAutoButR(block, ptr, prop, a+5, "", ICON_BLANK1, x + butw*a, y+buth, butw, buth);
                for(a=0; a<5; a++)
-                       uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a+15, "", ICON_BLANK1, x + butw*a, y, butw, buth);
+                       uiDefAutoButR(block, ptr, prop, a+15, "", ICON_BLANK1, x + butw*a, y, butw, buth);
                uiBlockEndAlign(block);
        }
        else if(subtype == PROP_MATRIX) {
                /* matrix layout */
                int row, col;
 
+               uiBlockSetCurLayout(block, uiLayoutFree(layout, 1));
+
                len= ceil(sqrt(len));
 
                h /= len;
@@ -245,243 +374,214 @@ static void ui_item_array(uiBlock *block, uiItemRNA *rnaitem, int len, int x, in
                        col= a%len;
                        row= a/len;
 
-                       uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a, "", 0, x + w*col, y+(row-a-1)*EM_UNIT_Y, w, EM_UNIT_Y);
+                       but= uiDefAutoButR(block, ptr, prop, a, "", 0, x + w*col, y+(row-a-1)*UI_UNIT_Y, w, UI_UNIT_Y);
+                       if(slider && but->type==NUM)
+                               but->type= NUMSLI;
                }
        }
        else if(len <= 4 && ELEM3(subtype, PROP_ROTATION, PROP_VECTOR, PROP_COLOR)) {
-               /* layout for known array subtypes */
-               static char vectoritem[4]= {'X', 'Y', 'Z', 'W'};
-               static char quatitem[4]= {'W', 'X', 'Y', 'Z'};
-               static char coloritem[4]= {'R', 'G', 'B', 'A'};
-               char str[3];
-
-               for(a=0; a<len; a++) {
-                       if(len == 4 && subtype == PROP_ROTATION)
-                               str[0]= quatitem[a];
-                       else if(subtype == PROP_VECTOR || subtype == PROP_ROTATION)
-                               str[0]= vectoritem[a];
-                       else
-                               str[0]= coloritem[a];
-
-                       if(type == PROP_BOOLEAN) {
-                               str[1]= '\0';
-                       }
-                       else {
-                               str[1]= ':';
-                               str[2]= '\0';
+               if(subtype == PROP_COLOR)
+                       uiDefAutoButR(block, ptr, prop, -1, "", 0, 0, 0, w, UI_UNIT_Y);
+
+               if(subtype != PROP_COLOR || expand) {
+                       /* layout for known array subtypes */
+                       static char vectoritem[4]= {'X', 'Y', 'Z', 'W'};
+                       static char quatitem[4]= {'W', 'X', 'Y', 'Z'};
+                       static char coloritem[4]= {'R', 'G', 'B', 'A'};
+                       char str[3];
+
+                       for(a=0; a<len; a++) {
+                               if(len == 4 && subtype == PROP_ROTATION)
+                                       str[0]= quatitem[a];
+                               else if(subtype == PROP_VECTOR || subtype == PROP_ROTATION)
+                                       str[0]= vectoritem[a];
+                               else
+                                       str[0]= coloritem[a];
+
+                               if(type == PROP_BOOLEAN) {
+                                       str[1]= '\0';
+                               }
+                               else {
+                                       str[1]= ':';
+                                       str[2]= '\0';
+                               }
+
+                               but= uiDefAutoButR(block, ptr, prop, a, str, 0, 0, 0, w, UI_UNIT_Y);
+                               if(slider && but->type==NUM)
+                                       but->type= NUMSLI;
                        }
-
-                       uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a, str, 0, x, y+(len-a-1)*EM_UNIT_Y, w, EM_UNIT_Y);
+               }
+               else if(subtype == PROP_COLOR && len == 4) {
+                       but= uiDefAutoButR(block, ptr, prop, 3, "A:", 0, 0, 0, w, UI_UNIT_Y);
+                       if(slider && but->type==NUM)
+                               but->type= NUMSLI;
                }
        }
        else {
-               /* default array layout */
-               for(a=0; a<len; a++)
-                       uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a, "", 0, x, y+(len-a-1)*EM_UNIT_Y, w, EM_UNIT_Y);
+               for(a=0; a<len; a++) {
+                       but= uiDefAutoButR(block, ptr, prop, a, "", 0, 0, 0, w, UI_UNIT_Y);
+                       if(slider && but->type==NUM)
+                               but->type= NUMSLI;
+               }
        }
 
-       uiBlockEndAlign(block);
+       uiBlockSetCurLayout(block, layout);
 }
 
-static void ui_item_enum_row(uiBlock *block, uiItemRNA *rnaitem, int x, int y, int w, int h)
+static void ui_item_enum_row(uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, char *uiname, int x, int y, int w, int h)
 {
-       const EnumPropertyItem *item;
-       int a, totitem, pos, itemw;
-       const char *propname;
-       
-       propname= RNA_property_identifier(&rnaitem->ptr, rnaitem->prop);
-       RNA_property_enum_items(&rnaitem->ptr, rnaitem->prop, &item, &totitem);
+       EnumPropertyItem *item;
+       const char *identifier;
+       char *name;
+       int a, totitem, itemw, icon, value, free;
+
+       identifier= RNA_property_identifier(prop);
+       RNA_property_enum_items(block->evil_C, ptr, prop, &item, &totitem, &free);
 
-       uiBlockBeginAlign(block);
-       pos= 0;
+       uiBlockSetCurLayout(block, ui_item_local_sublayout(layout, layout, 1));
        for(a=0; a<totitem; a++) {
-               itemw= ui_item_fit(1, pos, totitem, w, a == totitem-1, UI_FIT_EXPAND);
-               uiDefButR(block, ROW, 0, NULL, x+pos, y, itemw, h, &rnaitem->ptr, propname, -1, 0, item[a].value, -1, -1, NULL);
-               pos += itemw;
+               if(!item[a].identifier[0])
+                       continue;
+
+               name= (!uiname || uiname[0])? (char*)item[a].name: "";
+               icon= item[a].icon;
+               value= item[a].value;
+               itemw= ui_text_icon_width(block->curlayout, name, icon);
+
+               if(icon && strcmp(name, "") != 0)
+                       uiDefIconTextButR(block, ROW, 0, icon, name, 0, 0, itemw, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
+               else if(icon)
+                       uiDefIconButR(block, ROW, 0, icon, 0, 0, itemw, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
+               else
+                       uiDefButR(block, ROW, 0, name, 0, 0, itemw, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
        }
-       uiBlockEndAlign(block);
+       uiBlockSetCurLayout(block, layout);
+
+       if(free)
+               MEM_freeN(item);
 }
 
 /* create label + button for RNA property */
-static void ui_item_with_label(uiBlock *block, uiItemRNA *rnaitem, int x, int y, int w, int h)
+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)
 {
-       char *name;
+       uiLayout *sub;
+       uiBut *but;
+       PropertySubType subtype;
+       int labelw;
+
+       sub= uiLayoutRow(layout, 0);
+       uiBlockSetCurLayout(block, sub);
 
-       if(rnaitem->item.name)
-               name= (char*)rnaitem->item.name;
-       else
-               name= (char*)RNA_property_ui_name(&rnaitem->ptr, rnaitem->prop);
-       
        if(strcmp(name, "") != 0) {
-               w= w/2;
-               uiDefBut(block, LABEL, 0, name, x, y, w, h, NULL, 0.0, 0.0, 0, 0, "");
-               x += w;
+               /* XXX UI_GetStringWidth is not accurate
+               labelw= UI_GetStringWidth(name);
+               CLAMP(labelw, w/4, 3*w/4);*/
+               labelw= w/2;
+               uiDefBut(block, LABEL, 0, name, x, y, labelw, h, NULL, 0.0, 0.0, 0, 0, "");
+               w= w-labelw;
+       }
+
+       subtype= RNA_property_subtype(prop);
+
+       if(subtype == PROP_FILEPATH || subtype == PROP_DIRPATH) {
+               uiBlockSetCurLayout(block, uiLayoutRow(sub, 1));
+               uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w-UI_UNIT_X, h);
+               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 */
        }
+       else
+               but= uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w, h);
 
-       uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, rnaitem->index, "", rnaitem->item.icon, x, y, w, h);
+       uiBlockSetCurLayout(block, layout);
+       return but;
 }
 
-/* create buttons for an arbitrary item */
-static void ui_item_buts(uiBlock *block, uiItem *item, int x, int y, int w, int h)
+/********************* Button Items *************************/
+
+/* disabled item */
+static void ui_item_disabled(uiLayout *layout, char *name)
 {
-       if(item->type == ITEM_RNA_PROPERTY) {
-               /* RNA property */
-               uiItemRNA *rnaitem= (uiItemRNA*)item;
-               PropertyType type;
-               int len;
-               
-               /* retrieve info */
-               type= RNA_property_type(&rnaitem->ptr, rnaitem->prop);
-               len= RNA_property_array_length(&rnaitem->ptr, rnaitem->prop);
-
-               /* array property */
-               if(rnaitem->index == RNA_NO_INDEX && len > 0)
-                       ui_item_array(block, rnaitem, len, x, y, w, h);
-               /* expanded enum */
-               else if(type == PROP_ENUM && rnaitem->expand)
-                       ui_item_enum_row(block, rnaitem, x, y, w, h);
-               /* property with separate label */
-               else if(type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER)
-                       ui_item_with_label(block, rnaitem, x, y, w, h);
-               /* single button */
-               else
-                       uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, rnaitem->index, (char*)item->name, item->icon, x, y, w, h);
-       }
-       else if(item->type == ITEM_OPERATOR) {
-               /* operator */
-               uiItemOp *opitem= (uiItemOp*)item;
-               uiBut *but;
-
-               if(item->icon && item->name)
-                       but= uiDefIconTextButO(block, BUT, opitem->ot->idname, opitem->context, item->icon, (char*)item->name, x, y, w, h, NULL);
-               else if(item->icon)
-                       but= uiDefIconButO(block, BUT, opitem->ot->idname, opitem->context, item->icon, x, y, w, h, NULL);
-               /* text only */
-               else
-                       but= uiDefButO(block, BUT, opitem->ot->idname, opitem->context, (char*)item->name, x, y, w, h, NULL);
+       uiBlock *block= layout->root->block;
+       uiBut *but;
+       int w;
 
-               if(but && opitem->properties) {
-                       /* assign properties */
-                       PointerRNA *opptr= uiButGetOperatorPtrRNA(but);
-                       opptr->data= opitem->properties;
-                       opitem->properties= NULL;
-               }
-       }
-       else if(item->type == ITEM_MENU) {
-               /* menu */
-               uiItemLMenu *menuitem= (uiItemLMenu*)item;
+       uiBlockSetCurLayout(block, layout);
 
-               uiDefMenuBut(block, menuitem->func, NULL, (char*)item->name, x, y-2, w-3, h+4, "");
-       }
-       else if(item->type == ITEM_LABEL) {
-               /* label */
+       if(!name)
+               name= "";
 
-               if(item->icon && item->name)
-                       uiDefIconTextBut(block, LABEL, 0, item->icon, (char*)item->name, x, y, w, h, NULL, 0.0, 0.0, 0, 0, "");
-               else if(item->icon)
-                       uiDefIconBut(block, LABEL, 0, item->icon, x, y, w, h, NULL, 0.0, 0.0, 0, 0, "");
-               else if((char*)item->name)
-                       uiDefBut(block, LABEL, 0, (char*)item->name, x, y, w, h, NULL, 0.0, 0.0, 0, 0, "");
-       }
-       else {
-               /* separator */
-               uiDefBut(block, SEPR, 0, "", x, y, w, h, NULL, 0.0, 0.0, 0, 0, "");
-       }
-}
+       w= ui_text_icon_width(layout, name, 0);
 
-/* estimated size of text + icon */
-static int ui_text_icon_width(char *name, int icon)
-{
-       if(icon && name && strcmp(name, "") == 0)
-               return EM_UNIT_X; /* icon only */
-       else if(icon)
-               return 10*EM_UNIT_X; /* icon + text */
-       else
-               return 10*EM_UNIT_X; /* text only */
+       but= uiDefBut(block, LABEL, 0, (char*)name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+       but->flag |= UI_BUT_DISABLED;
+       but->lock = 1;
+       but->lockstr = "";
 }
 
-/* estimated size of an item */
-static void ui_item_size(uiItem *item, int *r_w, int *r_h)
+/* operator items */
+void uiItemFullO(uiLayout *layout, char *name, int icon, char *idname, IDProperty *properties, int context)
 {
-       int w, h;
+       uiBlock *block= layout->root->block;
+       wmOperatorType *ot= WM_operatortype_find(idname, 0);
+       uiBut *but;
+       int w;
 
-       if(item->type == ITEM_RNA_PROPERTY) {
-               /* RNA property */
-               uiItemRNA *rnaitem= (uiItemRNA*)item;
-               PropertyType type;
-               PropertySubType subtype;
-               int len;
-
-               w= ui_text_icon_width(item->name, item->icon);
-               h= EM_UNIT_Y;
-
-               /* arbitrary extended width by type */
-               type= RNA_property_type(&rnaitem->ptr, rnaitem->prop);
-               subtype= RNA_property_subtype(&rnaitem->ptr, rnaitem->prop);
-               len= RNA_property_array_length(&rnaitem->ptr, rnaitem->prop);
-
-               if(type == PROP_STRING)
-                       w += 10*EM_UNIT_X;
-
-               /* increase height for arrays */
-               if(rnaitem->index == RNA_NO_INDEX && len > 0) {
-                       if(item->name && strcmp(item->name, "") == 0 && item->icon == 0)
-                               h= 0;
-
-                       if(type == PROP_BOOLEAN && len == 20)
-                               h += 2*EM_UNIT_Y;
-                       else if(subtype == PROP_MATRIX)
-                               h += ceil(sqrt(len))*EM_UNIT_Y;
-                       else
-                               h += len*EM_UNIT_Y;
-               }
-       }
-       else {
-               /* other */
-               w= ui_text_icon_width(item->name, item->icon);
-               h= EM_UNIT_Y;
+       if(!ot) {
+               ui_item_disabled(layout, idname);
+               return;
        }
 
-       if(r_w) *r_w= w;
-       if(r_h) *r_h= h;
-}
+       if(!name)
+               name= ot->name;
+       if(layout->root->type == UI_LAYOUT_MENU && !icon)
+               icon= ICON_BLANK1;
 
-static void ui_item_free(uiItem *item)
-{
-       if(item->type == ITEM_OPERATOR) {
-               uiItemOp *opitem= (uiItemOp*)item;
+       /* create button */
+       uiBlockSetCurLayout(block, layout);
 
-               if(opitem->properties) {
-                       IDP_FreeProperty(opitem->properties);
-                       MEM_freeN(opitem->properties);
-               }
+       w= ui_text_icon_width(layout, name, icon);
+
+       if(icon && strcmp(name, "") != 0)
+               but= uiDefIconTextButO(block, BUT, ot->idname, context, icon, (char*)name, 0, 0, w, UI_UNIT_Y, NULL);
+       else if(icon)
+               but= uiDefIconButO(block, BUT, ot->idname, context, icon, 0, 0, w, UI_UNIT_Y, NULL);
+       else
+               but= uiDefButO(block, BUT, ot->idname, context, (char*)name, 0, 0, w, UI_UNIT_Y, NULL);
+
+       /* assign properties */
+       if(properties) {
+               PointerRNA *opptr= uiButGetOperatorPtrRNA(but);
+               opptr->data= properties;
        }
 }
 
-/* operator items */
-void uiItemFullO(uiLayout *layout, char *name, int icon, char *idname, IDProperty *properties, int context)
+static char *ui_menu_enumpropname(uiLayout *layout, char *opname, char *propname, int retval)
 {
-       uiTemplate *template= layout->templates.last;
-       wmOperatorType *ot= WM_operatortype_find(idname);
-       uiItemOp *opitem;
+       wmOperatorType *ot= WM_operatortype_find(opname, 0);
+       PointerRNA ptr;
+       PropertyRNA *prop;
 
-       if(!template)
-               return;
-       if(!ot)
-               return;
+       if(!ot || !ot->srna)
+               return "";
 
-       opitem= MEM_callocN(sizeof(uiItemOp), "uiItemOp");
+       RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
+       prop= RNA_struct_find_property(&ptr, propname);
 
-       opitem->item.name= name;
-       opitem->item.icon= icon;
-       opitem->item.type= ITEM_OPERATOR;
-       opitem->item.slot= template->slot;
+       if(prop) {
+               EnumPropertyItem *item;
+               int totitem, free;
+               const char *name;
 
-       opitem->ot= ot;
-       opitem->properties= properties;
-       opitem->context= context;
+               RNA_property_enum_items(layout->root->block->evil_C, &ptr, prop, &item, &totitem, &free);
+               if(RNA_enum_name(item, retval, &name)) {
+                       if(free) MEM_freeN(item);
+                       return (char*)name;
+               }
+               
+               if(free)
+                       MEM_freeN(item);
+       }
 
-       BLI_addtail(&template->items, opitem);
+       return "";
 }
 
 void uiItemEnumO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
@@ -491,30 +591,79 @@ void uiItemEnumO(uiLayout *layout, char *name, int icon, char *opname, char *pro
        WM_operator_properties_create(&ptr, opname);
        RNA_enum_set(&ptr, propname, value);
 
-       uiItemFullO(layout, name, icon, opname, ptr.data, layout->opcontext);
+       if(!name)
+               name= ui_menu_enumpropname(layout, opname, propname, value);
+
+       uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
 }
 
 void uiItemsEnumO(uiLayout *layout, char *opname, char *propname)
 {
-       wmOperatorType *ot= WM_operatortype_find(opname);
+       wmOperatorType *ot= WM_operatortype_find(opname, 0);
        PointerRNA ptr;
        PropertyRNA *prop;
 
-       if(!ot || !ot->srna)
+       if(!ot || !ot->srna) {
+               ui_item_disabled(layout, opname);
                return;
+       }
 
        RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
        prop= RNA_struct_find_property(&ptr, propname);
 
-       if(prop && RNA_property_type(&ptr, prop) == PROP_ENUM) {
-               const EnumPropertyItem *item;
-               int totitem, i;
+       if(prop && RNA_property_type(prop) == PROP_ENUM) {
+               EnumPropertyItem *item;
+               int totitem, i, free;
 
-               RNA_property_enum_items(&ptr, prop, &item, &totitem);
+               RNA_property_enum_items(layout->root->block->evil_C, &ptr, prop, &item, &totitem, &free);
 
                for(i=0; i<totitem; i++)
-                       uiItemEnumO(layout, "", 0, opname, propname, item[i].value);
+                       if(item[i].identifier[0])
+                               uiItemEnumO(layout, (char*)item[i].name, item[i].icon, opname, propname, item[i].value);
+                       else
+                               uiItemS(layout);
+
+               if(free)
+                       MEM_freeN(item);
+       }
+}
+
+/* for use in cases where we have */
+void uiItemEnumO_string(uiLayout *layout, char *name, int icon, char *opname, char *propname, char *value_str)
+{
+       PointerRNA ptr;
+       
+       /* for getting the enum */
+       PropertyRNA *prop;
+       EnumPropertyItem *item;
+       int value, free;
+
+       WM_operator_properties_create(&ptr, opname);
+       
+       /* enum lookup */
+       if((prop= RNA_struct_find_property(&ptr, propname))) {
+               RNA_property_enum_items(layout->root->block->evil_C, &ptr, prop, &item, NULL, &free);
+               if(RNA_enum_value_from_id(item, value_str, &value)==0) {
+                       if(free) MEM_freeN(item);
+                       printf("uiItemEnumO_string: %s.%s, enum %s not found.\n", RNA_struct_identifier(ptr.type), propname, value_str);
+                       return;
+               }
+
+               if(free)
+                       MEM_freeN(item);
+       }
+       else {
+               printf("uiItemEnumO_string: %s.%s not found.\n", RNA_struct_identifier(ptr.type), propname);
+               return;
        }
+       
+       RNA_property_enum_set(&ptr, prop, value);
+       
+       /* same as uiItemEnumO */
+       if(!name)
+               name= ui_menu_enumpropname(layout, opname, propname, value);
+
+       uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
 }
 
 void uiItemBooleanO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
@@ -524,7 +673,7 @@ void uiItemBooleanO(uiLayout *layout, char *name, int icon, char *opname, char *
        WM_operator_properties_create(&ptr, opname);
        RNA_boolean_set(&ptr, propname, value);
 
-       uiItemFullO(layout, name, icon, opname, ptr.data, layout->opcontext);
+       uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
 }
 
 void uiItemIntO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
@@ -534,7 +683,7 @@ void uiItemIntO(uiLayout *layout, char *name, int icon, char *opname, char *prop
        WM_operator_properties_create(&ptr, opname);
        RNA_int_set(&ptr, propname, value);
 
-       uiItemFullO(layout, name, icon, opname, ptr.data, layout->opcontext);
+       uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
 }
 
 void uiItemFloatO(uiLayout *layout, char *name, int icon, char *opname, char *propname, float value)
@@ -544,7 +693,7 @@ void uiItemFloatO(uiLayout *layout, char *name, int icon, char *opname, char *pr
        WM_operator_properties_create(&ptr, opname);
        RNA_float_set(&ptr, propname, value);
 
-       uiItemFullO(layout, name, icon, opname, ptr.data, layout->opcontext);
+       uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
 }
 
 void uiItemStringO(uiLayout *layout, char *name, int icon, char *opname, char *propname, char *value)
@@ -554,183 +703,821 @@ void uiItemStringO(uiLayout *layout, char *name, int icon, char *opname, char *p
        WM_operator_properties_create(&ptr, opname);
        RNA_string_set(&ptr, propname, value);
 
-       uiItemFullO(layout, name, icon, opname, ptr.data, layout->opcontext);
+       uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
 }
 
 void uiItemO(uiLayout *layout, char *name, int icon, char *opname)
 {
-       uiItemFullO(layout, name, icon, opname, NULL, layout->opcontext);
+       uiItemFullO(layout, name, icon, opname, NULL, layout->root->opcontext);
 }
 
 /* RNA property items */
-void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int expand)
+
+static void ui_item_rna_size(uiLayout *layout, char *name, int icon, PropertyRNA *prop, int index, int *r_w, int *r_h)
+{
+       PropertyType type;
+       PropertySubType subtype;
+       int len, w, h;
+
+       /* arbitrary extended width by type */
+       type= RNA_property_type(prop);
+       subtype= RNA_property_subtype(prop);
+       len= RNA_property_array_length(prop);
+
+       if(ELEM(type, PROP_STRING, PROP_POINTER) && !name[0])
+               name= "non-empty";
+       else if(type == PROP_BOOLEAN && !name[0])
+               icon= ICON_DOT;
+
+       w= ui_text_icon_width(layout, name, icon);
+       h= UI_UNIT_Y;
+
+       /* increase height for arrays */
+       if(index == RNA_NO_INDEX && len > 0) {
+               if(!name[0] && icon == 0)
+                       h= 0;
+
+               if(type == PROP_BOOLEAN && len == 20)
+                       h += 2*UI_UNIT_Y;
+               else if(subtype == PROP_MATRIX)
+                       h += ceil(sqrt(len))*UI_UNIT_Y;
+               else
+                       h += len*UI_UNIT_Y;
+       }
+       else if(ui_layout_vary_direction(layout) == UI_ITEM_VARY_X) {
+               if(type == PROP_BOOLEAN && strcmp(name, "") != 0)
+                       w += UI_UNIT_X;
+               else if(type == PROP_ENUM)
+                       w += UI_UNIT_X/2;
+       }
+
+       *r_w= w;
+       *r_h= h;
+}
+
+void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int value, int expand, int slider, int toggle)
 {
-       uiTemplate *template= layout->templates.last;
-       uiItemRNA *rnaitem;
+       uiBlock *block= layout->root->block;
+       uiBut *but;
+       PropertyType type;
+       char namestr[UI_MAX_NAME_STR];
+       int len, w, h;
 
        if(!ptr->data || !prop)
                return;
-       if(!template)
-               return;
 
-       rnaitem= MEM_callocN(sizeof(uiItemRNA), "uiItemRNA");
+       uiBlockSetCurLayout(block, layout);
+
+       /* retrieve info */
+       type= RNA_property_type(prop);
+       len= RNA_property_array_length(prop);
+
+       /* set name and icon */
+       if(!name)
+               name= (char*)RNA_property_ui_name(prop);
+       if(!icon)
+               icon= RNA_property_ui_icon(prop);
+
+       if(ELEM4(type, PROP_INT, PROP_FLOAT, PROP_STRING, PROP_POINTER))
+               name= ui_item_name_add_colon(name, namestr);
+       else if(type == PROP_BOOLEAN && len)
+               name= ui_item_name_add_colon(name, namestr);
+       else if(type == PROP_ENUM && index != RNA_ENUM_VALUE)
+               name= ui_item_name_add_colon(name, namestr);
+
+       if(layout->root->type == UI_LAYOUT_MENU) {
+               if(type == PROP_BOOLEAN)
+                       icon= (RNA_property_boolean_get(ptr, prop))? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT;
+               else if(type == PROP_ENUM && index == RNA_ENUM_VALUE)
+                       icon= (RNA_property_enum_get(ptr, prop) == value)? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT; 
+       }
+
+       /* get size */
+       ui_item_rna_size(layout, name, icon, prop, index, &w, &h);
 
-       rnaitem->item.name= name;
-       rnaitem->item.icon= icon;
-       rnaitem->item.type= ITEM_RNA_PROPERTY;
-       rnaitem->item.slot= template->slot;
+       /* array property */
+       if(index == RNA_NO_INDEX && len > 0)
+               ui_item_array(layout, block, name, icon, ptr, prop, len, 0, 0, w, h, expand, slider);
+       /* enum item */
+       else if(type == PROP_ENUM && index == RNA_ENUM_VALUE) {
+               char *identifier= (char*)RNA_property_identifier(prop);
+
+               if(icon && strcmp(name, "") != 0)
+                       uiDefIconTextButR(block, ROW, 0, icon, name, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
+               else if(icon)
+                       uiDefIconButR(block, ROW, 0, icon, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
+               else
+                       uiDefButR(block, ROW, 0, name, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
+       }
+       /* expanded enum */
+       else if(type == PROP_ENUM && expand)
+               ui_item_enum_row(layout, block, ptr, prop, name, 0, 0, w, h);
+       /* property with separate label */
+       else if(type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER) {
+               but= ui_item_with_label(layout, block, name, icon, ptr, prop, index, 0, 0, w, h);
+               ui_but_add_search(but, ptr, prop, NULL, NULL);
+       }
+       /* single button */
+       else {
+               but= uiDefAutoButR(block, ptr, prop, index, (char*)name, icon, 0, 0, w, h);
 
-       rnaitem->ptr= *ptr;
-       rnaitem->prop= prop;
-       rnaitem->index= index;
-       rnaitem->expand= expand;
+               if(slider && but->type==NUM)
+                       but->type= NUMSLI;
 
-       BLI_addtail(&template->items, rnaitem);
+               if(toggle && but->type==OPTION)
+                       but->type= TOG;
+       }
 }
 
-void uiItemR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, char *propname, int expand)
+void uiItemR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, char *propname, int expand, int slider, int toggle)
 {
        PropertyRNA *prop;
 
+       if(!ptr->data || !propname)
+               return;
+
        prop= RNA_struct_find_property(ptr, propname);
 
-       if(!ptr->data)
-               return;
        if(!prop) {
-               printf("uiItemR: property not found: %s\n",propname);
+               ui_item_disabled(layout, propname);
+               printf("uiItemR: property not found: %s\n", propname);
                return;
        }
-       
-       uiItemFullR(layout, name, icon, ptr, prop, RNA_NO_INDEX, expand);
+
+       uiItemFullR(layout, name, icon, ptr, prop, RNA_NO_INDEX, 0, expand, slider, toggle);
 }
 
-/* menu item */
-void uiItemM(uiLayout *layout, char *name, int icon, uiMenuCreateFunc func)
+void uiItemEnumR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, int value)
 {
-       uiTemplate *template= layout->templates.last;
-       uiItemLMenu *menuitem;
-       
-       if(!template)
-               return;
+       PropertyRNA *prop;
 
-       menuitem= MEM_callocN(sizeof(uiItemLMenu), "uiItemLMenu");
+       if(!ptr->data || !propname)
+               return;
 
-       menuitem->item.name= name;
-       menuitem->item.icon= icon;
-       menuitem->item.type= ITEM_MENU;
-       menuitem->item.slot= template->slot;
+       prop= RNA_struct_find_property(ptr, propname);
 
-       menuitem->func= func;
+       if(!prop || RNA_property_type(prop) != PROP_ENUM) {
+               ui_item_disabled(layout, propname);
+               printf("uiItemEnumR: enum property not found: %s\n", propname);
+               return;
+       }
 
-       BLI_addtail(&template->items, menuitem);
+       uiItemFullR(layout, name, icon, ptr, prop, RNA_ENUM_VALUE, value, 0, 0, 0);
 }
 
-/* label item */
-void uiItemL(uiLayout *layout, char *name, int icon)
+void uiItemEnumR_string(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, char *value)
 {
-       uiTemplate *template= layout->templates.last;
-       uiItem *item;
-       
-       if(!template)
-               return;
+       PropertyRNA *prop;
+       EnumPropertyItem *item;
+       int ivalue, a, free;
 
-       item= MEM_callocN(sizeof(uiItem), "uiItem");
+       if(!ptr->data || !propname)
+               return;
 
-       item->name= name;
-       item->icon= icon;
-       item->type= ITEM_LABEL;
-       item->slot= template->slot;
+       prop= RNA_struct_find_property(ptr, propname);
 
-       BLI_addtail(&template->items, item);
-}
+       if(!prop || RNA_property_type(prop) != PROP_ENUM) {
+               ui_item_disabled(layout, propname);
+               printf("uiItemEnumR: enum property not found: %s\n", propname);
+               return;
+       }
 
-/**************************** Template ***************************/
+       RNA_property_enum_items(layout->root->block->evil_C, ptr, prop, &item, NULL, &free);
 
-/* single row layout */
-static void ui_layout_row(uiLayout *layout, uiBlock *block, uiTemplate *template)
-{
-       uiItem *item;
-       int tot=0, totw= 0, maxh= 0, itemw, itemh, x, w;
+       if(!RNA_enum_value_from_id(item, value, &ivalue)) {
+               if(free) MEM_freeN(item);
+               ui_item_disabled(layout, propname);
+               printf("uiItemEnumR: enum property value not found: %s\n", value);
+               return;
+       }
 
-       /* estimate total width of buttons */
-       for(item=template->items.first; item; item=item->next) {
-               ui_item_size(item, &itemw, &itemh);
-               totw += itemw;
-               maxh= MAX2(maxh, itemh);
-               tot++;
+       for(a=0; item[a].identifier; a++) {
+               if(item[a].value == ivalue) {
+                       uiItemFullR(layout, (char*)item[a].name, item[a].icon, ptr, prop, RNA_ENUM_VALUE, ivalue, 0, 0, 0);
+                       break;
+               }
        }
 
-       if(totw == 0)
-               return;
-       
-       /* create buttons starting from left */
-       x= 0;
-       w= layout->w - (tot-1)*BUTTON_SPACE_X;
+       if(free)
+               MEM_freeN(item);
+}
 
-       for(item=template->items.first; item; item=item->next) {
-               ui_item_size(item, &itemw, &itemh);
-               itemw= ui_item_fit(itemw, x, totw, w, !item->next, UI_FIT_EXPAND);
+void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, char *propname)
+{
+       PropertyRNA *prop;
 
-               ui_item_buts(block, item, layout->x+x, layout->y-itemh, itemw, itemh);
-               x += itemw+BUTTON_SPACE_X;
+       prop= RNA_struct_find_property(ptr, propname);
+
+       if(!prop) {
+               ui_item_disabled(layout, propname);
+               return;
        }
 
-       layout->y -= maxh;
+       if(RNA_property_type(prop) == PROP_ENUM) {
+               EnumPropertyItem *item;
+               int totitem, i, free;
+
+               RNA_property_enum_items(layout->root->block->evil_C, ptr, prop, &item, &totitem, &free);
+
+               for(i=0; i<totitem; i++)
+                       if(item[i].identifier[0])
+                               uiItemEnumR(layout, (char*)item[i].name, 0, ptr, propname, item[i].value);
+                       else
+                               uiItemS(layout);
+
+               if(free)
+                       MEM_freeN(item);
+       }
 }
 
-/* multi-column layout */
-static void ui_layout_column(uiLayout *layout, uiBlock *block, uiTemplate *template)
+/* Pointer RNA button with search */
+
+static void rna_search_cb(const struct bContext *C, void *arg_but, char *str, uiSearchItems *items)
 {
-       uiItem *item;
-       int col, totcol= 0, x, y, miny, itemw, itemh, w;
+       Scene *scene= CTX_data_scene(C);
+       uiBut *but= arg_but;
+       char *name;
+       int i, iconid;
+
+       i = 0;
+       RNA_PROP_BEGIN(&but->rnasearchpoin, itemptr, but->rnasearchprop) {
+               iconid= 0;
+               if(RNA_struct_is_ID(itemptr.type))
+                       iconid= ui_id_icon_get(scene, itemptr.data);
+
+               name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
+
+               if(name) {
+                       if(BLI_strcasestr(name, str)) {
+                               if(!uiSearchItemAdd(items, name, SET_INT_IN_POINTER(i), iconid)) {
+                                       MEM_freeN(name);
+                                       break;
+                               }
+                       }
+
+                       MEM_freeN(name);
+               }
+
+               i++;
+       }
+       RNA_PROP_END;
+}
+
+static void search_id_collection(StructRNA *ptype, PointerRNA *ptr, PropertyRNA **prop)
+{
+       StructRNA *srna;
+
+       /* look for collection property in Main */
+       RNA_main_pointer_create(G.main, ptr);
+
+       *prop= NULL;
 
-       /* compute number of columns */
-       for(item=template->items.first; item; item=item->next)
-               totcol= MAX2(item->slot+1, totcol);
+       RNA_STRUCT_BEGIN(ptr, iprop) {
+               /* if it's a collection and has same pointer type, we've got it */
+               if(RNA_property_type(iprop) == PROP_COLLECTION) {
+                       srna= RNA_property_pointer_type(ptr, iprop);
+
+                       if(ptype == srna) {
+                               *prop= iprop;
+                               break;
+                       }
+               }
+       }
+       RNA_STRUCT_END;
+}
+
+void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop)
+{
+       StructRNA *ptype;
+       PointerRNA sptr;
+
+       /* for ID's we do automatic lookup */
+       if(!searchprop) {
+               if(RNA_property_type(prop) == PROP_POINTER) {
+                       ptype= RNA_property_pointer_type(ptr, prop);
+                       search_id_collection(ptype, &sptr, &searchprop);
+                       searchptr= &sptr;
+               }
+       }
+
+       /* turn button into search button */
+       if(searchprop) {
+               but->type= SEARCH_MENU;
+               but->hardmax= MAX2(but->hardmax, 256);
+               but->rnasearchpoin= *searchptr;
+               but->rnasearchprop= searchprop;
+               but->flag |= UI_ICON_LEFT|UI_TEXT_LEFT;
+
+               uiButSetSearchFunc(but, rna_search_cb, but, NULL, NULL);
+       }
+}
+
+void uiItemPointerR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, struct PointerRNA *searchptr, char *searchpropname)
+{
+       PropertyRNA *prop, *searchprop;
+       PropertyType type;
+       uiBut *but;
+       uiBlock *block;
+       StructRNA *icontype;
+       int w, h;
        
-       if(totcol == 0)
+       /* validate arguments */
+       if(!ptr->data || !searchptr->data)
+               return;
+
+       prop= RNA_struct_find_property(ptr, propname);
+
+       if(!prop) {
+               printf("uiItemPointerR: property not found: %s\n", propname);
                return;
+       }
        
-       x= 0;
-       miny= 0;
-       w= layout->w - (totcol-1)*COLUMN_SPACE;
+       type= RNA_property_type(prop);
+       if(!ELEM(type, PROP_POINTER, PROP_STRING)) {
+               printf("uiItemPointerR: property %s must be a pointer or string.\n", propname);
+               return;
+       }
 
-       /* create column per column */
-       for(col=0; col<totcol; col++) {
-               y= 0;
+       searchprop= RNA_struct_find_property(searchptr, searchpropname);
 
-               itemw= ui_item_fit(1, x, totcol, w, col == totcol-1, UI_FIT_EXPAND);
+       if(!searchprop || RNA_property_type(searchprop) != PROP_COLLECTION) {
+               printf("uiItemPointerR: search collection property not found: %s\n", searchpropname);
+               return;
+       }
+
+       /* get icon & name */
+       if(!icon) {
+               if(type == PROP_POINTER)
+                       icontype= RNA_property_pointer_type(ptr, prop);
+               else
+                       icontype= RNA_property_pointer_type(searchptr, searchprop);
+
+               icon= RNA_struct_ui_icon(icontype);
+       }
+       if(!name)
+               name= (char*)RNA_property_ui_name(prop);
+
+       /* create button */
+       block= uiLayoutGetBlock(layout);
+
+       ui_item_rna_size(layout, name, icon, prop, 0, &w, &h);
+       but= ui_item_with_label(layout, block, name, icon, ptr, prop, 0, 0, 0, w, h);
+
+       ui_but_add_search(but, ptr, prop, searchptr, searchprop);
+}
+
+/* menu item */
+static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt)
+{
+       MenuType *mt= (MenuType*)arg_mt;
+       Menu menu = {0};
 
-               for(item=template->items.first; item; item=item->next) {
-                       if(item->slot != col)
+       menu.type= mt;
+       menu.layout= layout;
+       mt->draw(C, &menu);
+}
+
+static void ui_item_menu(uiLayout *layout, char *name, int icon, uiMenuCreateFunc func, void *arg, void *argN)
+{
+       uiBlock *block= layout->root->block;
+       uiBut *but;
+       int w, h;
+
+       uiBlockSetCurLayout(block, layout);
+
+       if(layout->root->type == UI_LAYOUT_HEADER)
+               uiBlockSetEmboss(block, UI_EMBOSS);
+
+       if(!name)
+               name= "";
+       if(layout->root->type == UI_LAYOUT_MENU && !icon)
+               icon= ICON_BLANK1;
+
+       w= ui_text_icon_width(layout, name, icon);
+       h= UI_UNIT_Y;
+
+       if(layout->root->type == UI_LAYOUT_HEADER) /* ugly .. */
+               w -= 10;
+
+       if(icon)
+               but= uiDefIconTextMenuBut(block, func, arg, icon, (char*)name, 0, 0, w, h, "");
+       else
+               but= uiDefMenuBut(block, func, arg, (char*)name, 0, 0, w, h, "");
+
+       if(argN) { /* ugly .. */
+               but->poin= (char*)but;
+               but->func_argN= argN;
+       }
+
+       if(layout->root->type == UI_LAYOUT_HEADER)
+               uiBlockSetEmboss(block, UI_EMBOSS);
+       else if(layout->root->type == UI_LAYOUT_PANEL)
+               but->type= MENU;
+}
+
+void uiItemM(uiLayout *layout, bContext *C, char *name, int icon, char *menuname)
+{
+       ARegion *ar= CTX_wm_region(C);
+       MenuType *mt;
+
+       if(!menuname)
+               return;
+
+       for(mt=ar->type->menutypes.first; mt; mt=mt->next) {
+               if(strcmp(menuname, mt->idname) == 0) {
+                       if(!name)
+                               name= mt->label;
+                       if(layout->root->type == UI_LAYOUT_MENU && !icon)
+                               icon= ICON_BLANK1;
+                       ui_item_menu(layout, name, icon, ui_item_menutype_func, mt, NULL);
+                       return;
+               }
+       }
+
+       printf("uiItemM: not found %s\n", menuname);
+}
+
+/* label item */
+void uiItemL(uiLayout *layout, char *name, int icon)
+{
+       uiBlock *block= layout->root->block;
+       uiBut *but;
+       int w;
+
+       uiBlockSetCurLayout(block, layout);
+
+       if(!name)
+               name= "";
+       if(layout->root->type == UI_LAYOUT_MENU && !icon)
+               icon= ICON_BLANK1;
+
+       w= ui_text_icon_width(layout, name, icon);
+
+       if(icon && strcmp(name, "") != 0)
+               but= uiDefIconTextBut(block, LABEL, 0, icon, (char*)name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+       else if(icon)
+               but= uiDefIconBut(block, LABEL, 0, icon, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+       else
+               but= uiDefBut(block, LABEL, 0, (char*)name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+}
+
+/* value item */
+void uiItemV(uiLayout *layout, char *name, int icon, int argval)
+{
+       /* label */
+       uiBlock *block= layout->root->block;
+       float *retvalue= (block->handle)? &block->handle->retvalue: NULL;
+       int w;
+
+       uiBlockSetCurLayout(block, layout);
+
+       if(!name)
+               name= "";
+       if(layout->root->type == UI_LAYOUT_MENU && !icon)
+               icon= ICON_BLANK1;
+
+       w= ui_text_icon_width(layout, name, icon);
+
+       if(icon && strcmp(name, "") != 0)
+               uiDefIconTextButF(block, BUTM, 0, icon, (char*)name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, argval, "");
+       else if(icon)
+               uiDefIconButF(block, BUTM, 0, icon, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, argval, "");
+       else
+               uiDefButF(block, BUTM, 0, (char*)name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, argval, "");
+}
+
+/* separator item */
+void uiItemS(uiLayout *layout)
+{
+       uiBlock *block= layout->root->block;
+
+       uiBlockSetCurLayout(block, layout);
+       uiDefBut(block, SEPR, 0, "", 0, 0, EM_SEPR_X, EM_SEPR_Y, NULL, 0.0, 0.0, 0, 0, "");
+}
+
+/* level items */
+void uiItemMenuF(uiLayout *layout, char *name, int icon, uiMenuCreateFunc func)
+{
+       if(!func)
+               return;
+
+       ui_item_menu(layout, name, icon, func, NULL, NULL);
+}
+
+typedef struct MenuItemLevel {
+       int opcontext;
+       char *opname;
+       char *propname;
+       PointerRNA rnapoin;
+} MenuItemLevel;
+
+static void menu_item_enum_opname_menu(bContext *C, uiLayout *layout, void *arg)
+{
+       MenuItemLevel *lvl= (MenuItemLevel*)(((uiBut*)arg)->func_argN);
+
+       uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
+       uiItemsEnumO(layout, lvl->opname, lvl->propname);
+}
+
+void uiItemMenuEnumO(uiLayout *layout, char *name, int icon, char *opname, char *propname)
+{
+       wmOperatorType *ot= WM_operatortype_find(opname, 0);
+       MenuItemLevel *lvl;
+
+       if(!ot || !ot->srna) {
+               ui_item_disabled(layout, opname);
+               return;
+       }
+
+       if(!name)
+               name= ot->name;
+       if(layout->root->type == UI_LAYOUT_MENU && !icon)
+               icon= ICON_BLANK1;
+
+       lvl= MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
+       lvl->opname= opname;
+       lvl->propname= propname;
+       lvl->opcontext= layout->root->opcontext;
+
+       ui_item_menu(layout, name, icon, menu_item_enum_opname_menu, NULL, lvl);
+}
+
+static void menu_item_enum_rna_menu(bContext *C, uiLayout *layout, void *arg)
+{
+       MenuItemLevel *lvl= (MenuItemLevel*)(((uiBut*)arg)->func_argN);
+
+       uiLayoutSetOperatorContext(layout, lvl->opcontext);
+       uiItemsEnumR(layout, &lvl->rnapoin, lvl->propname);
+}
+
+void uiItemMenuEnumR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname)
+{
+       MenuItemLevel *lvl;
+       PropertyRNA *prop;
+
+       prop= RNA_struct_find_property(ptr, propname);
+       if(!prop) {
+               ui_item_disabled(layout, propname);
+               return;
+       }
+
+       if(!name)
+               name= (char*)RNA_property_ui_name(prop);
+       if(layout->root->type == UI_LAYOUT_MENU && !icon)
+               icon= ICON_BLANK1;
+
+       lvl= MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
+       lvl->rnapoin= *ptr;
+       lvl->propname= propname;
+       lvl->opcontext= layout->root->opcontext;
+
+       ui_item_menu(layout, name, icon, menu_item_enum_rna_menu, NULL, lvl);
+}
+
+/**************************** Layout Items ***************************/
+
+/* single-row layout */
+static void ui_litem_estimate_row(uiLayout *litem)
+{
+       uiItem *item;
+       int itemw, itemh;
+
+       litem->w= 0;
+       litem->h= 0;
+
+       for(item=litem->items.first; item; item=item->next) {
+               ui_item_size(item, &itemw, &itemh);
+
+               litem->w += itemw;
+               litem->h= MAX2(itemh, litem->h);
+
+               if(item->next)
+                       litem->w += litem->space;
+       }
+}
+
+static int ui_litem_min_width(int itemw)
+{
+       return MIN2(2*UI_UNIT_X, itemw);
+}
+
+static void ui_litem_layout_row(uiLayout *litem)
+{
+       uiItem *item;
+       int x, y, w, tot, totw, neww, itemw, minw, itemh, offset;
+       int fixedw, freew, fixedx, freex, flag= 0, lastw= 0;
+
+       x= litem->x;
+       y= litem->y;
+       w= litem->w;
+       totw= 0;
+       tot= 0;
+
+       for(item=litem->items.first; item; item=item->next) {
+               ui_item_size(item, &itemw, &itemh);
+               totw += itemw;
+               tot++;
+       }
+
+       if(totw == 0)
+               return;
+       
+       if(w != 0)
+               w -= (tot-1)*litem->space;
+       fixedw= 0;
+
+       /* keep clamping items to fixed minimum size until all are done */
+       do {
+               freew= 0;
+               x= 0;
+               flag= 0;
+
+               for(item=litem->items.first; item; item=item->next) {
+                       if(item->flag)
                                continue;
 
-                       ui_item_size(item, NULL, &itemh);
+                       ui_item_size(item, &itemw, &itemh);
+                       minw= ui_litem_min_width(itemw);
 
-                       y -= itemh;
-                       ui_item_buts(block, item, layout->x+x, layout->y+y, itemw, itemh);
-                       y -= BUTTON_SPACE_Y;
+                       if(w - lastw > 0)
+                               neww= ui_item_fit(itemw, x, totw, w-lastw, !item->next, litem->alignment, NULL);
+                       else
+                               neww= 0; /* no space left, all will need clamping to minimum size */
+
+                       x += neww;
+
+                       if((neww < minw || itemw == minw) && w != 0) {
+                               /* fixed size */
+                               item->flag= 1;
+                               fixedw += minw;
+                               flag= 1;
+                               totw -= itemw;
+                       }
+                       else {
+                               /* keep free size */
+                               item->flag= 0;
+                               freew += itemw;
+                       }
                }
 
-               x += itemw + COLUMN_SPACE;
-               miny= MIN2(miny, y);
+               lastw= fixedw;
+       } while(flag);
+
+       freex= 0;
+       fixedx= 0;
+       x= litem->x;
+
+       for(item=litem->items.first; item; item=item->next) {
+               ui_item_size(item, &itemw, &itemh);
+               minw= ui_litem_min_width(itemw);
+
+               if(item->flag) {
+                       /* fixed minimum size items */
+                       itemw= ui_item_fit(minw, fixedx, fixedw, MIN2(w, fixedw), !item->next, litem->alignment, NULL);
+                       fixedx += itemw;
+               }
+               else {
+                       /* free size item */
+                       itemw= ui_item_fit(itemw, freex, freew, w-fixedw, !item->next, litem->alignment, NULL);
+                       freex += itemw;
+               }
+
+               /* align right/center */
+               offset= 0;
+               if(litem->alignment == UI_LAYOUT_ALIGN_RIGHT) {
+                       if(fixedw == 0 && freew < w-fixedw)
+                               offset= (w - fixedw) - freew;
+               }
+               else if(litem->alignment == UI_LAYOUT_ALIGN_CENTER) {
+                       if(fixedw == 0 && freew < w-fixedw)
+                               offset= ((w - fixedw) - freew)/2;
+               }
+
+               /* position item */
+               ui_item_position(item, x+offset, y-itemh, itemw, itemh);
+
+               x += itemw;
+               if(item->next)
+                       x += litem->space;
        }
 
-       layout->y += miny;
+       litem->w= x - litem->x;
+       litem->h= litem->y - y;
+       litem->x= x;
+       litem->y= y;
+}
+
+/* single-column layout */
+static void ui_litem_estimate_column(uiLayout *litem)
+{
+       uiItem *item;
+       int itemw, itemh;
+
+       litem->w= 0;
+       litem->h= 0;
+
+       for(item=litem->items.first; item; item=item->next) {
+               ui_item_size(item, &itemw, &itemh);
+
+               litem->w= MAX2(litem->w, itemw);
+               litem->h += itemh;
+
+               if(item->next)
+                       litem->h += litem->space;
+       }
+}
+
+static void ui_litem_layout_column(uiLayout *litem)
+{
+       uiItem *item;
+       int itemh, x, y;
+
+       x= litem->x;
+       y= litem->y;
+
+       for(item=litem->items.first; item; item=item->next) {
+               ui_item_size(item, NULL, &itemh);
+
+               y -= itemh;
+               ui_item_position(item, x, y, litem->w, itemh);
+
+               if(item->next)
+                       y -= litem->space;
+       }
+
+       litem->h= litem->y - y;
+       litem->x= x;
+       litem->y= y;
+}
+
+/* root layout */
+static void ui_litem_estimate_root(uiLayout *litem)
+{
+       /* nothing to do */
+}
+
+static void ui_litem_layout_root(uiLayout *litem)
+{
+       if(litem->root->type == UI_LAYOUT_HEADER)
+               ui_litem_layout_row(litem);
+       else
+               ui_litem_layout_column(litem);
+}
+
+/* box layout */
+static void ui_litem_estimate_box(uiLayout *litem)
+{
+       uiStyle *style= litem->root->style;
+
+       ui_litem_estimate_column(litem);
+       litem->w += 2*style->boxspace;
+       litem->h += style->boxspace;
+}
+
+static void ui_litem_layout_box(uiLayout *litem)
+{
+       uiLayoutItemBx *box= (uiLayoutItemBx*)litem;
+       uiStyle *style= litem->root->style;
+       uiBut *but;
+       int w, h;
+
+       w= litem->w;
+       h= litem->h;
+
+       litem->x += style->boxspace;
+
+       if(w != 0) litem->w -= 2*style->boxspace;
+       if(h != 0) litem->h -= 2*style->boxspace;
+
+       ui_litem_layout_column(litem);
+
+       litem->x -= style->boxspace;
+       litem->y -= style->boxspace;
+
+       if(w != 0) litem->w += 2*style->boxspace;
+       if(h != 0) litem->h += style->boxspace;
+
+       /* roundbox around the sublayout */
+       but= box->roundbox;
+       but->x1= litem->x;
+       but->y1= litem->y;
+       but->x2= litem->x+litem->w;
+       but->y2= litem->y+litem->h;
 }
 
 /* multi-column layout, automatically flowing to the next */
-static void ui_layout_column_flow(uiLayout *layout, uiBlock *block, uiTemplate *template)
+static void ui_litem_estimate_column_flow(uiLayout *litem)
 {
-       uiTemplateFlow *flow= (uiTemplateFlow*)template;
+       uiStyle *style= litem->root->style;
+       uiLayoutItemFlow *flow= (uiLayoutItemFlow*)litem;
        uiItem *item;
-       int col, x, y, w, emh, emy, miny, itemw, itemh, maxw=0;
-       int toth, totcol, totitem;
+       int col, x, y, emh, emy, miny, itemw, itemh, maxw=0;
+       int toth, totitem;
 
        /* compute max needed width and total height */
        toth= 0;
        totitem= 0;
-       for(item=template->items.first; item; item=item->next) {
+       for(item=litem->items.first; item; item=item->next) {
                ui_item_size(item, &itemw, &itemh);
                maxw= MAX2(maxw, itemw);
                toth += itemh;
@@ -739,14 +1526,16 @@ static void ui_layout_column_flow(uiLayout *layout, uiBlock *block, uiTemplate *
 
        if(flow->number <= 0) {
                /* auto compute number of columns, not very good */
-               if(maxw == 0)
+               if(maxw == 0) {
+                       flow->totcol= 1;
                        return;
+               }
 
-               totcol= MAX2(layout->emw/maxw, 1);
-               totcol= MIN2(totcol, totitem);
+               flow->totcol= MAX2(litem->root->emw/maxw, 1);
+               flow->totcol= MIN2(flow->totcol, totitem);
        }
        else
-               totcol= flow->number;
+               flow->totcol= flow->number;
 
        /* compute sizes */
        x= 0;
@@ -754,551 +1543,731 @@ static void ui_layout_column_flow(uiLayout *layout, uiBlock *block, uiTemplate *
        emy= 0;
        miny= 0;
 
-       w= layout->w - totcol*(COLUMN_SPACE);
-       emh= toth/totcol;
+       maxw= 0;
+       emh= toth/flow->totcol;
 
        /* create column per column */
        col= 0;
-       for(item=template->items.first; item; item=item->next) {
-               ui_item_size(item, NULL, &itemh);
-               itemw= ui_item_fit(1, x, totcol, w, col == totcol-1, UI_FIT_EXPAND);
-       
-               y -= itemh;
-               emy -= itemh;
-               ui_item_buts(block, item, layout->x+x, layout->y+y, itemw, itemh);
-               y -= BUTTON_SPACE_Y;
+       for(item=litem->items.first; item; item=item->next) {
+               ui_item_size(item, &itemw, &itemh);
+
+               y -= itemh + style->buttonspacey;
                miny= MIN2(miny, y);
+               emy -= itemh;
+               maxw= MAX2(itemw, maxw);
 
                /* decide to go to next one */
-               if(col < totcol-1 && emy <= -emh) {
-                       x += itemw + COLUMN_SPACE;
+               if(col < flow->totcol-1 && emy <= -emh) {
+                       x += maxw + litem->space;
+                       maxw= 0;
                        y= 0;
                        col++;
                }
        }
 
-       layout->y += miny;
+       litem->w= x;
+       litem->h= litem->y - miny;
 }
 
-#if 0
-/* left-right layout, with buttons aligned on both sides */
-static void ui_layout_split(uiLayout *layout, uiBlock *block, uiTemplate *template)
+static void ui_litem_layout_column_flow(uiLayout *litem)
 {
+       uiStyle *style= litem->root->style;
+       uiLayoutItemFlow *flow= (uiLayoutItemFlow*)litem;
        uiItem *item;
-       int tot=0, totw= 0, maxh= 0, itemw, itemh, lx, rx, w;
+       int col, x, y, w, emh, emy, miny, itemw, itemh;
+       int toth, totitem, offset;
 
-       /* estimate total width of buttons */
-       for(item=template->items.first; item; item=item->next) {
+       /* compute max needed width and total height */
+       toth= 0;
+       totitem= 0;
+       for(item=litem->items.first; item; item=item->next) {
                ui_item_size(item, &itemw, &itemh);
-               totw += itemw;
-               maxh= MAX2(maxh, itemh);
-               tot++;
+               toth += itemh;
+               totitem++;
        }
 
-       if(totw == 0)
-               return;
-       
-       /* create buttons starting from left and right */
-       lx= 0;
-       rx= 0;
-       w= layout->w - BUTTON_SPACE_X*(tot-1) + BUTTON_SPACE_X;
+       /* compute sizes */
+       x= litem->x;
+       y= litem->y;
+       emy= 0;
+       miny= 0;
 
-       for(item=template->items.first; item; item=item->next) {
-               ui_item_size(item, &itemw, &itemh);
+       w= litem->w - (flow->totcol-1)*style->columnspace;
+       emh= toth/flow->totcol;
 
-               if(item->slot == UI_TSLOT_LR_LEFT) {
-                       itemw= ui_item_fit(itemw, lx, totw, w, 0, 0);
-                       ui_item_buts(block, item, layout->x+lx, layout->y-itemh, itemw, itemh);
-                       lx += itemw + BUTTON_SPACE_X;
-               }
-               else {
-                       itemw= ui_item_fit(itemw, totw + rx, totw, w, 0, 0);
-                       rx -= itemw + BUTTON_SPACE_X;
-                       ui_item_buts(block, item, layout->x+layout->w+rx, layout->y-itemh, itemw, itemh);
+       /* create column per column */
+       col= 0;
+       for(item=litem->items.first; item; item=item->next) {
+               ui_item_size(item, NULL, &itemh);
+               itemw= ui_item_fit(1, x-litem->x, flow->totcol, w, col == flow->totcol-1, litem->alignment, &offset);
+       
+               y -= itemh;
+               emy -= itemh;
+               ui_item_position(item, x+offset, y, itemw, itemh);
+               y -= style->buttonspacey;
+               miny= MIN2(miny, y);
+
+               /* decide to go to next one */
+               if(col < flow->totcol-1 && emy <= -emh) {
+                       x += itemw + style->columnspace;
+                       y= litem->y;
+                       col++;
                }
        }
 
-       layout->y -= maxh;
+       litem->h= litem->y - miny;
+       litem->x= x;
+       litem->y= miny;
 }
-#endif
 
-/* split in columns */
-static void ui_layout_split(const bContext *C, uiLayout *layout, uiBlock *block, uiTemplate *template)
+/* free layout */
+static void ui_litem_estimate_free(uiLayout *litem)
 {
-       uiTemplateSplt *split= (uiTemplateSplt*)template;
-       uiLayout *sublayout;
-       int a, x, y, miny, w= layout->w, h= layout->h, splitw;
-
-       x= 0;
-       y= 0;
-       miny= layout->y;
-
-       for(a=0; a<split->number; a++) {
-               sublayout= split->sublayout[a];
+       uiItem *item;
+       int itemx, itemy, itemw, itemh, minx, miny;
 
-               splitw= ui_item_fit(1, x, split->number, w, a == split->number-1, UI_FIT_EXPAND);
-               sublayout->x= layout->x + x;
-               sublayout->w= splitw;
-               sublayout->y= layout->y;
-               sublayout->h= h;
+       minx= 1e6;
+       miny= 1e6;
+       litem->w= 0;
+       litem->h= 0;
 
-               sublayout->emw= layout->emw/split->number;
-               sublayout->emh= layout->emh;
+       for(item=litem->items.first; item; item=item->next) {
+               ui_item_offset(item, &itemx, &itemy);
+               ui_item_size(item, &itemw, &itemh);
 
-               /* do layout for elements in sublayout */
-               ui_layout_end(C, block, sublayout, NULL, &y);
-               miny= MIN2(y, miny);
+               minx= MIN2(minx, itemx);
+               miny= MIN2(miny, itemy);
 
-               x += splitw + COLUMN_SPACE;
+               litem->w= MAX2(litem->w, itemx+itemw);
+               litem->h= MAX2(litem->h, itemy+itemh);
        }
 
-       layout->y= miny;
+       litem->w -= minx;
+       litem->h -= miny;
 }
 
-/* element in a box layout */
-static void ui_layout_box(const bContext *C, uiLayout *layout, uiBlock *block, uiTemplate *template)
+static void ui_litem_layout_free(uiLayout *litem)
 {
-       uiTemplateBx *box= (uiTemplateBx*)template;
-       int starty, startx, w= layout->w, h= layout->h;
+       uiItem *item;
+       float scalex=1.0f, scaley=1.0f;
+       int x, y, newx, newy, itemx, itemy, itemh, itemw, minx, miny, totw, toth;
 
-       startx= layout->x;
-       starty= layout->y;
+       minx= 1e6;
+       miny= 1e6;
+       totw= 0;
+       toth= 0;
 
-       /* some extra padding */
-       box->sublayout->x= layout->x + BOX_SPACE;
-       box->sublayout->w= w - 2*BOX_SPACE;
-       box->sublayout->y= layout->y - BOX_SPACE;
-       box->sublayout->h= h;
+       for(item=litem->items.first; item; item=item->next) {
+               ui_item_offset(item, &itemx, &itemy);
+               ui_item_size(item, &itemw, &itemh);
 
-       box->sublayout->emw= layout->emw;
-       box->sublayout->emh= layout->emh;
+               minx= MIN2(minx, itemx);
+               miny= MIN2(miny, itemy);
 
-       /* do layout for elements in sublayout */
-       ui_layout_end(C, block, box->sublayout, NULL, &layout->y);
+               totw= MAX2(totw, itemx+itemw);
+               toth= MAX2(toth, itemy+itemh);
+       }
 
-       /* roundbox around the sublayout */
-       uiDefBut(block, ROUNDBOX, 0, "", startx, layout->y, w, starty - layout->y, NULL, 7.0, 0.0, 3, 20, "");
-}
+       totw -= minx;
+       toth -= miny;
 
-static void ui_layout_header_buttons(uiLayout *layout, uiBlock *block, uiTemplate *template)
-{
-       uiItem *item;
-       int itemw, itemh;
+       if(litem->w && totw > 0)
+               scalex= (float)litem->w/(float)totw;
+       if(litem->h && toth > 0)
+               scaley= (float)litem->h/(float)toth;
        
-       uiBlockBeginAlign(block);
+       x= litem->x;
+       y= litem->y - scaley*toth;
 
-       for(item=template->items.first; item; item=item->next) {
+       for(item=litem->items.first; item; item=item->next) {
+               ui_item_offset(item, &itemx, &itemy);
                ui_item_size(item, &itemw, &itemh);
-               ui_item_buts(block, item, layout->x, layout->y, itemw, itemh);
-               layout->x += itemw;
+
+               if(scalex != 1.0f) {
+                       newx= (itemx - minx)*scalex;
+                       itemw= (itemx - minx + itemw)*scalex - newx;
+                       itemx= minx + newx;
+               }
+
+               if(scaley != 1.0f) {
+                       newy= (itemy - miny)*scaley;
+                       itemh= (itemy - miny + itemh)*scaley - newy;
+                       itemy= miny + newy;
+               }
+
+               ui_item_position(item, x+itemx-minx, y+itemy-miny, itemw, itemh);
        }
 
-       uiBlockEndAlign(block);
+       litem->w= scalex*totw;
+       litem->h= litem->y - y;
+       litem->x= x + litem->w;
+       litem->y= y;
+}
+
+/* split layout */
+static void ui_litem_estimate_split(uiLayout *litem)
+{
+       ui_litem_estimate_row(litem);
 }
 
-static void ui_layout_header_menus(const bContext *C, uiLayout *layout, uiBlock *block, uiTemplate *template)
+static void ui_litem_layout_split(uiLayout *litem)
 {
-       ScrArea *sa= CTX_wm_area(C);
+       uiLayoutItemSplt *split= (uiLayoutItemSplt*)litem;
+       uiItem *item;
+       float percentage;
+       int itemh, x, y, w, tot=0, colw=0;
+
+       x= litem->x;
+       y= litem->y;
+
+       for(item=litem->items.first; item; item=item->next)
+               tot++;
+       
+       if(tot == 0)
+               return;
+       
+       percentage= (split->percentage == 0.0f)? 1.0f/(float)tot: split->percentage;
+       
+       w= (litem->w - (tot-1)*litem->space);
+       colw= w*percentage;
+       colw= MAX2(colw, 0);
+
+       for(item=litem->items.first; item; item=item->next) {
+               ui_item_size(item, NULL, &itemh);
 
-       layout->x= ED_area_header_standardbuttons(C, block, layout->y);
+               ui_item_position(item, x, y-itemh, colw, itemh);
+               x += colw;
 
-       if((sa->flag & HEADER_NO_PULLDOWN)==0) {
-               uiBlockSetEmboss(block, UI_EMBOSSP);
-               ui_layout_header_buttons(layout, block, template);
+               if(item->next) {
+                       colw= (w - (int)(w*percentage))/(tot-1);
+                       colw= MAX2(colw, 0);
+
+                       x += litem->space;
+               }
        }
 
-       uiBlockSetEmboss(block, UI_EMBOSS);
+       litem->w= x - litem->x;
+       litem->h= litem->y - y;
+       litem->x= x;
+       litem->y= y;
 }
 
-static void ui_layout_header_id(const bContext *C, uiLayout *layout, uiBlock *block, uiTemplate *template)
+/* layout create functions */
+uiLayout *uiLayoutRow(uiLayout *layout, int align)
 {
-       uiTemplateHeadID *idtemplate= (uiTemplateHeadID*)template;
-       PointerRNA idptr;
+       uiLayout *litem;
 
-       idptr= RNA_pointer_get(&idtemplate->ptr, idtemplate->propname);
+       litem= MEM_callocN(sizeof(uiLayout), "uiLayoutRow");
+       litem->item.type= ITEM_LAYOUT_ROW;
+       litem->root= layout->root;
+       litem->align= align;
+       litem->active= 1;
+       litem->enabled= 1;
+       litem->context= layout->context;
+       litem->space= (align)? 0: layout->root->style->buttonspacex;
+       BLI_addtail(&layout->items, litem);
 
-       layout->x= uiDefIDPoinButs(block, CTX_data_main(C), NULL, (ID*)idptr.data, ID_TXT, NULL,
-               layout->x, layout->y, idtemplate->func,
-               UI_ID_BROWSE|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_OPEN|UI_ID_DELETE);
+       uiBlockSetCurLayout(layout->root->block, litem);
+
+       return litem;
 }
 
-void ui_template_free(uiTemplate *template)
+uiLayout *uiLayoutColumn(uiLayout *layout, int align)
 {
-       uiItem *item;
-       int a;
-
-       if(template->type == TEMPLATE_BOX) {
-               uiTemplateBx *box= (uiTemplateBx*)template;
-               ui_layout_free(box->sublayout);
-       }
-       if(template->type == TEMPLATE_SPLIT) {
-               uiTemplateSplt *split= (uiTemplateSplt*)template;
+       uiLayout *litem;
 
-               for(a=0; a<split->number; a++)
-                       ui_layout_free(split->sublayout[a]);
-               MEM_freeN(split->sublayout);
-       }
+       litem= MEM_callocN(sizeof(uiLayout), "uiLayoutColumn");
+       litem->item.type= ITEM_LAYOUT_COLUMN;
+       litem->root= layout->root;
+       litem->align= align;
+       litem->active= 1;
+       litem->enabled= 1;
+       litem->context= layout->context;
+       litem->space= (litem->align)? 0: layout->root->style->buttonspacey;
+       BLI_addtail(&layout->items, litem);
 
-       for(item=template->items.first; item; item=item->next)
-               ui_item_free(item);
+       uiBlockSetCurLayout(layout->root->block, litem);
 
-       BLI_freelistN(&template->items);
+       return litem;
 }
 
-/* template create functions */
-void uiLayoutRow(uiLayout *layout)
+uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align)
 {
-       uiTemplate *template;
+       uiLayoutItemFlow *flow;
+
+       flow= MEM_callocN(sizeof(uiLayoutItemFlow), "uiLayoutItemFlow");
+       flow->litem.item.type= ITEM_LAYOUT_COLUMN_FLOW;
+       flow->litem.root= layout->root;
+       flow->litem.align= align;
+       flow->litem.active= 1;
+       flow->litem.enabled= 1;
+       flow->litem.context= layout->context;
+       flow->litem.space= (flow->litem.align)? 0: layout->root->style->columnspace;
+       flow->number= number;
+       BLI_addtail(&layout->items, flow);
 
-       template= MEM_callocN(sizeof(uiTemplate), "uiTemplate");
-       template->type= TEMPLATE_ROW;
+       uiBlockSetCurLayout(layout->root->block, &flow->litem);
 
-       BLI_addtail(&layout->templates, template);
+       return &flow->litem;
 }
 
-void uiLayoutColumn(uiLayout *layout)
+static uiLayout *ui_layout_box(uiLayout *layout, int type)
 {
-       uiTemplate *template;
+       uiLayoutItemBx *box;
 
-       template= MEM_callocN(sizeof(uiTemplate), "uiTemplate");
-       template->type= TEMPLATE_COLUMN;
+       box= MEM_callocN(sizeof(uiLayoutItemBx), "uiLayoutItemBx");
+       box->litem.item.type= ITEM_LAYOUT_BOX;
+       box->litem.root= layout->root;
+       box->litem.active= 1;
+       box->litem.enabled= 1;
+       box->litem.context= layout->context;
+       box->litem.space= layout->root->style->columnspace;
+       BLI_addtail(&layout->items, box);
 
-       BLI_addtail(&layout->templates, template);
-}
+       uiBlockSetCurLayout(layout->root->block, &box->litem);
 
-void uiLayoutColumnFlow(uiLayout *layout, int number)
-{
-       uiTemplateFlow *flow;
+       box->roundbox= uiDefBut(layout->root->block, type, 0, "", 0, 0, 0, 0, NULL, 0.0, 0.0, 0, 0, "");
 
-       flow= MEM_callocN(sizeof(uiTemplateFlow), "uiTemplateFlow");
-       flow->template.type= TEMPLATE_COLUMN_FLOW;
-       flow->number= number;
-       BLI_addtail(&layout->templates, flow);
+       return &box->litem;
 }
 
 uiLayout *uiLayoutBox(uiLayout *layout)
 {
-       uiTemplateBx *box;
+       return ui_layout_box(layout, ROUNDBOX);
+}
 
-       box= MEM_callocN(sizeof(uiTemplateBx), "uiTemplateBx");
-       box->template.type= TEMPLATE_BOX;
-       box->sublayout= uiLayoutBegin(layout->dir, 0, 0, 0, 0);
-       BLI_addtail(&layout->templates, box);
+uiLayout *uiLayoutListBox(uiLayout *layout)
+{
+       return ui_layout_box(layout, LISTBOX);
+}
 
-       return box->sublayout;
+ListBase *uiLayoutBoxGetList(uiLayout *layout)
+{
+       uiLayoutItemBx *box= (uiLayoutItemBx*)layout;
+       return &box->items;
 }
 
-void uiLayoutSplit(uiLayout *layout, int number, int lr)
+uiLayout *uiLayoutFree(uiLayout *layout, int align)
 {
-       uiTemplateSplt *split;
-       int a;
+       uiLayout *litem;
 
-       split= MEM_callocN(sizeof(uiTemplateSplt), "uiTemplateSplt");
-       split->template.type= TEMPLATE_SPLIT;
-       split->number= number;
-       split->lr= lr;
-       split->sublayout= MEM_callocN(sizeof(uiLayout*)*number, "uiTemplateSpltSub");
+       litem= MEM_callocN(sizeof(uiLayout), "uiLayoutFree");
+       litem->item.type= ITEM_LAYOUT_FREE;
+       litem->root= layout->root;
+       litem->align= align;
+       litem->active= 1;
+       litem->enabled= 1;
+       litem->context= layout->context;
+       BLI_addtail(&layout->items, litem);
 
-       for(a=0; a<number; a++)
-               split->sublayout[a]= uiLayoutBegin(layout->dir, 0, 0, 0, 0);
+       uiBlockSetCurLayout(layout->root->block, litem);
 
-       BLI_addtail(&layout->templates, split);
+       return litem;
 }
 
-uiLayout *uiLayoutSub(uiLayout *layout, int n)
+uiBlock *uiLayoutFreeBlock(uiLayout *layout)
 {
-       uiTemplate *template= layout->templates.last;
+       uiBlock *block;
 
-       if(template) {
-               switch(template->type) {
-                       case TEMPLATE_SPLIT:
-                               if(n >= 0 && n < ((uiTemplateSplt*)template)->number)
-                                       return ((uiTemplateSplt*)template)->sublayout[n];
-                               break;
-                       case TEMPLATE_BOX:
-                               return ((uiTemplateBx*)template)->sublayout;
-                               break;
-                       default:
-                               break;
-               }
-       }
+       block= uiLayoutGetBlock(layout);
+       uiLayoutFree(layout, 0);
+
+       return block;
+}
+
+uiLayout *uiLayoutSplit(uiLayout *layout, float percentage)
+{
+       uiLayoutItemSplt *split;
+
+       split= MEM_callocN(sizeof(uiLayoutItemSplt), "uiLayoutItemSplt");
+       split->litem.item.type= ITEM_LAYOUT_SPLIT;
+       split->litem.root= layout->root;
+       split->litem.active= 1;
+       split->litem.enabled= 1;
+       split->litem.context= layout->context;
+       split->litem.space= layout->root->style->columnspace;
+       split->percentage= percentage;
+       BLI_addtail(&layout->items, split);
+
+       uiBlockSetCurLayout(layout->root->block, &split->litem);
 
-       return NULL;
+       return &split->litem;
 }
 
-void uiTemplateHeaderMenus(uiLayout *layout)
+void uiLayoutSetActive(uiLayout *layout, int active)
 {
-       uiTemplate *template;
+       layout->active= active;
+}
 
-       template= MEM_callocN(sizeof(uiTemplate), "uiTemplate");
-       template->type= TEMPLATE_HEADER_MENUS;
+void uiLayoutSetEnabled(uiLayout *layout, int enabled)
+{
+       layout->enabled= enabled;
+}
 
-       BLI_addtail(&layout->templates, template);
+void uiLayoutSetRedAlert(uiLayout *layout, int redalert)
+{
+       layout->redalert= redalert;
 }
 
-void uiTemplateHeaderButtons(uiLayout *layout)
+void uiLayoutSetKeepAspect(uiLayout *layout, int keepaspect)
 {
-       uiTemplate *template;
+       layout->keepaspect= keepaspect;
+}
 
-       template= MEM_callocN(sizeof(uiTemplate), "uiTemplate");
-       template->type= TEMPLATE_HEADER_BUTTONS;
+void uiLayoutSetAlignment(uiLayout *layout, int alignment)
+{
+       layout->alignment= alignment;
+}
 
-       BLI_addtail(&layout->templates, template);
+void uiLayoutSetScaleX(uiLayout *layout, float scale)
+{
+       layout->scale[0]= scale;
 }
 
-void uiTemplateHeaderID(uiLayout *layout, PointerRNA *ptr, char *propname, int flag, uiIDPoinFunc func)
+void uiLayoutSetScaleY(uiLayout *layout, float scale)
 {
-       uiTemplateHeadID *idtemplate;
+       layout->scale[1]= scale;
+}
 
-       idtemplate= MEM_callocN(sizeof(uiTemplateHeadID), "uiTemplateHeadID");
-       idtemplate->template.type= TEMPLATE_HEADER_ID;
-       idtemplate->ptr= *ptr;
-       idtemplate->propname= propname;
-       idtemplate->flag= flag;
-       idtemplate->func= func;
+int uiLayoutGetActive(uiLayout *layout)
+{
+       return layout->active;
+}
 
-       BLI_addtail(&layout->templates, idtemplate);
+int uiLayoutGetEnabled(uiLayout *layout)
+{
+       return layout->enabled;
+}
+
+int uiLayoutGetRedAlert(uiLayout *layout)
+{
+       return layout->redalert;
 }
 
-void uiTemplateSetColor(uiLayout *layout, int color)
+int uiLayoutGetKeepAspect(uiLayout *layout)
 {
-       uiTemplate *template= layout->templates.last;
+       return layout->keepaspect;
+}
 
-       if(template)
-               template->color= color;
+int uiLayoutGetAlignment(uiLayout *layout)
+{
+       return layout->alignment;
 }
 
-void uiTemplateSlot(uiLayout *layout, int slot)
+float uiLayoutGetScaleX(uiLayout *layout)
 {
-       uiTemplate *template= layout->templates.last;
+       return layout->scale[0];
+}
 
-       if(template)
-               template->slot= slot;
+float uiLayoutGetScaleY(uiLayout *layout)
+{
+       return layout->scale[0];
 }
 
 /********************** Layout *******************/
 
-static void ui_layout_templates(const bContext *C, uiBlock *block, uiLayout *layout)
+static void ui_item_scale(uiLayout *litem, float scale[2])
 {
-       uiTemplate *template;
+       uiItem *item;
+       int x, y, w, h;
 
-       if(layout->dir == UI_LAYOUT_HORIZONTAL) {
-               for(template=layout->templates.first; template; template=template->next) {
-                       switch(template->type) {
-                               case TEMPLATE_HEADER_MENUS:
-                                       ui_layout_header_menus(C, layout, block, template);
-                                       break;
-                               case TEMPLATE_HEADER_ID:
-                                       ui_layout_header_id(C, layout, block, template);
-                                       break;
-                               case TEMPLATE_HEADER_BUTTONS:
-                               default:
-                                       ui_layout_header_buttons(layout, block, template);
-                                       break;
-                       }
+       for(item=litem->items.last; item; item=item->prev) {
+               ui_item_size(item, &w, &h);
+               ui_item_offset(item, &x, &y);
+
+               if(scale[0] != 0.0f) {
+                       x *= scale[0];
+                       w *= scale[0];
+               }
+
+               if(scale[1] != 0.0f) {
+                       y *= scale[1];
+                       h *= scale[1];
                }
 
-               layout->x += TEMPLATE_SPACE;
+               ui_item_position(item, x, y, w, h);
        }
-       else {
-               for(template=layout->templates.first; template; template=template->next) {
-                       if(template->color) {
-                               // XXX oldcolor= uiBlockGetCol(block);
-                               // XXX uiBlockSetCol(block, template->color);
-                       }
+}
 
-                       switch(template->type) {
-                               case TEMPLATE_ROW:
-                                       ui_layout_row(layout, block, template);
-                                       break;
-                               case TEMPLATE_COLUMN_FLOW:
-                                       ui_layout_column_flow(layout, block, template);
-                                       break;
-                               case TEMPLATE_SPLIT:
-                                       ui_layout_split(C, layout, block, template);
-                                       break;
-                               case TEMPLATE_BOX:
-                                       ui_layout_box(C, layout, block, template);
-                                       break;
-                               case TEMPLATE_COLUMN:
-                               default:
-                                       ui_layout_column(layout, block, template);
-                                       break;
-                       }
+static void ui_item_estimate(uiItem *item)
+{
+       uiItem *subitem;
+
+       if(item->type != ITEM_BUTTON) {
+               uiLayout *litem= (uiLayout*)item;
+
+               for(subitem=litem->items.first; subitem; subitem=subitem->next)
+                       ui_item_estimate(subitem);
+
+               if(litem->items.first == NULL)
+                       return;
+
+               if(litem->scale[0] != 0.0f || litem->scale[1] != 0.0f)
+                       ui_item_scale(litem, litem->scale);
+
+               switch(litem->item.type) {
+                       case ITEM_LAYOUT_COLUMN:
+                               ui_litem_estimate_column(litem);
+                               break;
+                       case ITEM_LAYOUT_COLUMN_FLOW:
+                               ui_litem_estimate_column_flow(litem);
+                               break;
+                       case ITEM_LAYOUT_ROW:
+                               ui_litem_estimate_row(litem);
+                               break;
+                       case ITEM_LAYOUT_BOX:
+                               ui_litem_estimate_box(litem);
+                               break;
+                       case ITEM_LAYOUT_ROOT:
+                               ui_litem_estimate_root(litem);
+                               break;
+                       case ITEM_LAYOUT_FREE:
+                               ui_litem_estimate_free(litem);
+                               break;
+                       case ITEM_LAYOUT_SPLIT:
+                               ui_litem_estimate_split(litem);
+                               break;
+                       default:
+                               break;
+               }
+       }
+}
+
+static void ui_item_align(uiLayout *litem, int nr)
+{
+       uiItem *item;
+       uiButtonItem *bitem;
+       uiLayoutItemBx *box;
+
+       for(item=litem->items.last; item; item=item->prev) {
+               if(item->type == ITEM_BUTTON) {
+                       bitem= (uiButtonItem*)item;
+                       if(ui_but_can_align(bitem->but))
+                               if(!bitem->but->alignnr)
+                                       bitem->but->alignnr= nr;
+               }
+               else if(item->type == ITEM_LAYOUT_FREE);
+               else if(item->type == ITEM_LAYOUT_BOX) {
+                       box= (uiLayoutItemBx*)item;
+                       box->roundbox->alignnr= nr;
+                       BLI_remlink(&litem->root->block->buttons, box->roundbox);
+                       BLI_addhead(&litem->root->block->buttons, box->roundbox);
+               }
+               else
+                       ui_item_align((uiLayout*)item, nr);
+       }
+}
+
+static void ui_item_flag(uiLayout *litem, int flag)
+{
+       uiItem *item;
+       uiButtonItem *bitem;
+
+       for(item=litem->items.last; item; item=item->prev) {
+               if(item->type == ITEM_BUTTON) {
+                       bitem= (uiButtonItem*)item;
+                       bitem->but->flag |= flag;
+               }
+               else
+                       ui_item_flag((uiLayout*)item, flag);
+       }
+}
+
+static void ui_item_layout(uiItem *item)
+{
+       uiItem *subitem;
+
+       if(item->type != ITEM_BUTTON) {
+               uiLayout *litem= (uiLayout*)item;
+
+               if(litem->items.first == NULL)
+                       return;
 
-       // XXX  if(template->color)
-       // XXX          uiBlockSetCol(block, oldcolor);
+               if(litem->align)
+                       ui_item_align(litem, ++litem->root->block->alignnr);
+               if(!litem->active)
+                       ui_item_flag(litem, UI_BUT_INACTIVE);
+               if(!litem->enabled)
+                       ui_item_flag(litem, UI_BUT_DISABLED);
 
-                       layout->y -= TEMPLATE_SPACE;
+               switch(litem->item.type) {
+                       case ITEM_LAYOUT_COLUMN:
+                               ui_litem_layout_column(litem);
+                               break;
+                       case ITEM_LAYOUT_COLUMN_FLOW:
+                               ui_litem_layout_column_flow(litem);
+                               break;
+                       case ITEM_LAYOUT_ROW:
+                               ui_litem_layout_row(litem);
+                               break;
+                       case ITEM_LAYOUT_BOX:
+                               ui_litem_layout_box(litem);
+                               break;
+                       case ITEM_LAYOUT_ROOT:
+                               ui_litem_layout_root(litem);
+                               break;
+                       case ITEM_LAYOUT_FREE:
+                               ui_litem_layout_free(litem);
+                               break;
+                       case ITEM_LAYOUT_SPLIT:
+                               ui_litem_layout_split(litem);
+                               break;
+                       default:
+                               break;
                }
+
+               for(subitem=litem->items.first; subitem; subitem=subitem->next)
+                       ui_item_layout(subitem);
        }
 }
 
-void ui_layout_end(const bContext *C, uiBlock *block, uiLayout *layout, int *x, int *y)
+static void ui_layout_items(const bContext *C, uiBlock *block, uiLayout *layout)
+{
+       ui_item_estimate(&layout->item);
+       ui_item_layout(&layout->item);
+}
+
+static void ui_layout_end(const bContext *C, uiBlock *block, uiLayout *layout, int *x, int *y)
 {
-       ui_layout_templates(C, block, layout);
+       if(layout->root->handlefunc)
+               uiBlockSetButmFunc(block, layout->root->handlefunc, layout->root->argv);
+
+       ui_layout_items(C, block, layout);
 
        if(x) *x= layout->x;
        if(y) *y= layout->y;
-       
 }
 
-void ui_layout_free(uiLayout *layout)
+static void ui_layout_free(uiLayout *layout)
 {
-       uiTemplate *template;
+       uiItem *item, *next;
 
-       for(template=layout->templates.first; template; template=template->next)
-               ui_template_free(template);
+       for(item=layout->items.first; item; item=next) {
+               next= item->next;
+
+               if(item->type == ITEM_BUTTON)
+                       MEM_freeN(item);
+               else
+                       ui_layout_free((uiLayout*)item);
+       }
+
+       if(layout->item.type == ITEM_LAYOUT_BOX)
+               BLI_freelistN(&((uiLayoutItemBx*)layout)->items);
 
-       BLI_freelistN(&layout->templates);
        MEM_freeN(layout);
 }
 
-uiLayout *uiLayoutBegin(int dir, int x, int y, int size, int em)
+uiLayout *uiBlockLayout(uiBlock *block, int dir, int type, int x, int y, int size, int em, uiStyle *style)
 {
        uiLayout *layout;
+       uiLayoutRoot *root;
+
+       root= MEM_callocN(sizeof(uiLayoutRoot), "uiLayoutRoot");
+       root->type= type;
+       root->style= style;
+       root->block= block;
+       root->opcontext= WM_OP_INVOKE_REGION_WIN;
 
        layout= MEM_callocN(sizeof(uiLayout), "uiLayout");
-       layout->opcontext= WM_OP_INVOKE_REGION_WIN;
-       layout->dir= dir;
+       layout->item.type= ITEM_LAYOUT_ROOT;
+
        layout->x= x;
        layout->y= y;
+       layout->root= root;
+       layout->space= style->templatespace;
+       layout->active= 1;
+       layout->enabled= 1;
+       layout->context= NULL;
+
+       if(type == UI_LAYOUT_MENU)
+               layout->space= 0;
 
        if(dir == UI_LAYOUT_HORIZONTAL) {
                layout->h= size;
-               layout->emh= em*EM_UNIT_Y;
+               layout->root->emh= em*UI_UNIT_Y;
        }
        else {
                layout->w= size;
-               layout->emw= em*EM_UNIT_X;
+               layout->root->emw= em*UI_UNIT_X;
        }
 
+       block->curlayout= layout;
+       root->layout= layout;
+       BLI_addtail(&block->layouts, root);
+       
        return layout;
 }
 
-void uiLayoutContext(uiLayout *layout, int opcontext)
+uiBlock *uiLayoutGetBlock(uiLayout *layout)
 {
-       layout->opcontext= opcontext;
+       return layout->root->block;
 }
 
-void uiLayoutEnd(const bContext *C, uiBlock *block, uiLayout *layout, int *x, int *y)
+int uiLayoutGetOperatorContext(uiLayout *layout)
 {
-       ui_layout_end(C, block, layout, x, y);
-       ui_layout_free(layout);
+       return layout->root->opcontext;
 }
 
-/************************ Utilities ************************/
 
-void uiRegionPanelLayout(const bContext *C, ARegion *ar, int vertical, char *context)
+void uiBlockSetCurLayout(uiBlock *block, uiLayout *layout)
 {
-       uiBlock *block;
-       PanelType *pt;
-       Panel *panel;
-       float col[3];
-       int xco, yco, x=PNL_DIST, y=-PNL_HEADER-PNL_DIST, w, em;
-
-       // XXX this only hides cruft
+       block->curlayout= layout;
+}
 
-       /* clear */
-       UI_GetThemeColor3fv(TH_HEADER, col);
-       glClearColor(col[0], col[1], col[2], 0.0);
-       glClear(GL_COLOR_BUFFER_BIT);
-       
-       /* set view2d view matrix for scrolling (without scrollers) */
-       UI_view2d_view_ortho(C, &ar->v2d);
+void ui_layout_add_but(uiLayout *layout, uiBut *but)
+{
+       uiButtonItem *bitem;
        
-       uiBeginPanels(C, ar);
-
-       for(pt= ar->type->paneltypes.first; pt; pt= pt->next) {
-               if(context)
-                       if(!pt->context || strcmp(context, pt->context) != 0)
-                               continue;
-
-               if(pt->draw && (!pt->poll || pt->poll(C))) {
-                       block= uiBeginBlock(C, ar, pt->idname, UI_EMBOSS);
-                       
-                       if(vertical) {
-                               w= (ar->type->minsizex)? ar->type->minsizex-12: block->aspect*ar->winx-12;
-                               em= (ar->type->minsizex)? 10: 20;
-                       }
-                       else {
-                               w= (ar->type->minsizex)? ar->type->minsizex-12: UI_PANEL_WIDTH-12;
-                               em= (ar->type->minsizex)? 10: 20;
-                       }
-
-                       if(uiNewPanel(C, ar, block, pt->name, pt->name, x, y, w, 0)) {
-                               panel= uiPanelFromBlock(block);
-                               panel->type= pt;
-                               panel->layout= uiLayoutBegin(UI_LAYOUT_VERTICAL, x, y, w, em);
-
-                               pt->draw(C, panel);
-
-                               uiLayoutEnd(C, block, panel->layout, &xco, &yco);
-                               panel->layout= NULL;
-                               uiNewPanelHeight(block, y - yco + 12);
-                       }
-                       else {
-                               w= PNL_HEADER;
-                               yco= PNL_HEADER;
-                       }
-
-                       uiEndBlock(C, block);
-
-                       if(vertical)
-                               y += yco+PNL_DIST;
-                       else
-                               x += w+PNL_DIST;
-               }
+       bitem= MEM_callocN(sizeof(uiButtonItem), "uiButtonItem");
+       bitem->item.type= ITEM_BUTTON;
+       bitem->but= but;
+       BLI_addtail(&layout->items, bitem);
+
+       if(layout->context) {
+               but->context= layout->context;
+               but->context->used= 1;
        }
-
-       uiEndPanels(C, ar);
-       
-       /* restore view matrix? */
-       UI_view2d_view_restore(C);
 }
 
-void uiRegionHeaderLayout(const bContext *C, ARegion *ar)
+void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext)
 {
-       uiBlock *block;
-       uiLayout *layout;
-       HeaderType *ht;
-       float col[3];
-       int xco, yco;
+       layout->root->opcontext= opcontext;
+}
 
-       // XXX this only hides cruft
-       
-       /* clear */
-       if(ED_screen_area_active(C))
-               UI_GetThemeColor3fv(TH_HEADER, col);
-       else
-               UI_GetThemeColor3fv(TH_HEADERDESEL, col);
-       
-       glClearColor(col[0], col[1], col[2], 0.0);
-       glClear(GL_COLOR_BUFFER_BIT);
-       
-       /* set view2d view matrix for scrolling (without scrollers) */
-       UI_view2d_view_ortho(C, &ar->v2d);
+void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv)
+{
+       layout->root->handlefunc= handlefunc;
+       layout->root->argv= argv;
+}
 
-       xco= 8;
-       yco= 3;
+void uiBlockLayoutResolve(const bContext *C, uiBlock *block, int *x, int *y)
+{
+       uiLayoutRoot *root;
 
-       /* draw all headers types */
-       for(ht= ar->type->headertypes.first; ht; ht= ht->next) {
-               block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS);
-               layout= uiLayoutBegin(UI_LAYOUT_HORIZONTAL, xco, yco, 24, 1);
+       if(x) *x= 0;
+       if(y) *y= 0;
 
-               if(ht->draw)
-                       ht->draw(C, layout);
+       block->curlayout= NULL;
 
-               uiLayoutEnd(C, block, layout, &xco, &yco);
-               uiEndBlock(C, block);
-               uiDrawBlock(C, block);
+       for(root=block->layouts.first; root; root=root->next) {
+               /* NULL in advance so we don't interfere when adding button */
+               ui_layout_end(C, block, root->layout, x, y);
+               ui_layout_free(root->layout);
        }
 
-       /* always as last  */
-       UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
+       BLI_freelistN(&block->layouts);
 
-       /* restore view matrix? */
-       UI_view2d_view_restore(C);
+       /* XXX silly trick, interface_templates.c doesn't get linked
+        * because it's not used by other files in this module? */
+       {
+               void ui_template_fix_linking();
+               ui_template_fix_linking();
+       }
+}
+
+void uiLayoutSetContextPointer(uiLayout *layout, char *name, PointerRNA *ptr)
+{
+       uiBlock *block= layout->root->block;
+       layout->context= CTX_store_add(&block->contexts, name, ptr);
 }