Merge with 2.5 -r 21619:21756.
[blender.git] / source / blender / editors / interface / interface_layout.c
index ea26bafc1f805189a83a45609f7307a0e0640155..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"
 
 #include "RNA_access.h"
 #include "WM_api.h"
 #include "WM_types.h"
 
-/************************ Structs and Defines *************************/
+#include "interface_intern.h"
 
-#define COLUMN_SPACE   5
-#define TEMPLATE_SPACE 5
-#define STACK_SPACE            5
-#define BUTTON_SPACE_X 5
-#define BUTTON_SPACE_Y 2
+/************************ Structs and Defines *************************/
 
 #define RNA_NO_INDEX   -1
+#define RNA_ENUM_VALUE -2
+
+#define EM_SEPR_X              6
+#define EM_SEPR_Y              6
+
+/* uiLayoutRoot */
+
+typedef struct uiLayoutRoot {
+       struct uiLayoutRoot *next, *prev;
+
+       int type;
+       int opcontext;
+
+       int emw, emh;
+
+       uiMenuHandleFunc handlefunc;
+       void *argv;
+
+       uiStyle *style;
+       uiBlock *block;
+       uiLayout *layout;
+} uiLayoutRoot;
 
 /* Item */
 
 typedef enum uiItemType {
-       ITEM_OPERATOR,
-       ITEM_RNA_PROPERTY,
-       ITEM_MENU,
-       ITEM_LABEL
+       ITEM_BUTTON,
+
+       ITEM_LAYOUT_ROW,
+       ITEM_LAYOUT_COLUMN,
+       ITEM_LAYOUT_COLUMN_FLOW,
+       ITEM_LAYOUT_ROW_FLOW,
+       ITEM_LAYOUT_BOX,
+       ITEM_LAYOUT_FREE,
+       ITEM_LAYOUT_SPLIT,
+
+       ITEM_LAYOUT_ROOT
+#if 0
+       TEMPLATE_COLUMN_FLOW,
+       TEMPLATE_SPLIT,
+       TEMPLATE_BOX,
+
+       TEMPLATE_HEADER,
+       TEMPLATE_HEADER_ID
+#endif
 } uiItemType;
 
-enum uiItemFlag {
-       ITEM_ICON,
-       ITEM_TEXT
-};
-
 typedef struct uiItem {
-       struct uiItem *next, *prev;
+       void *next, *prev;
        uiItemType type;
-       int slot;
-
-       const char *name;
-       int icon;
+       int flag;
 } uiItem;
 
-typedef struct uiItemRNA {
+typedef struct uiButtonItem {
        uiItem item;
+       uiBut *but;
+} uiButtonItem;
 
-       PointerRNA ptr;
-       PropertyRNA *prop;
-       int index;
-} uiItemRNA;
-
-typedef struct uiItemOp {
+struct uiLayout {
        uiItem item;
 
-       wmOperatorType *ot;
-       IDProperty *properties;
-       int context;
-} uiItemOp;
+       uiLayoutRoot *root;
+       bContextStore *context;
+       ListBase items;
 
-typedef struct uiItemLMenu {
-       uiItem item;
+       int x, y, w, h;
+       float scale[2];
+       short space;
+       char align;
+       char active;
+       char enabled;
+       char redalert;
+       char keepaspect;
+       char alignment;
+};
+
+typedef struct uiLayoutItemFlow {
+       uiLayout litem;
+       int number;
+       int totcol;
+} uiLayoutItemFlow;
 
-       uiMenuCreateFunc func;
-} uiItemLMenu;
+typedef struct uiLayoutItemBx {
+       uiLayout litem;
+       uiBut *roundbox;
+       ListBase items;
+} uiLayoutItemBx;
 
-/* Template */
+typedef struct uiLayoutItemSplt {
+       uiLayout litem;
+       float percentage;
+} uiLayoutItemSplt;
 
-typedef enum uiTemplateType {
-       TEMPLATE_COLUMN,
-       TEMPLATE_LR,
-       TEMPLATE_STACK,
+typedef struct uiLayoutItemRoot {
+       uiLayout litem;
+} uiLayoutItemRoot;
 
-       TEMPLATE_HEADER_MENUS,
-       TEMPLATE_HEADER_BUTTONS,
-       TEMPLATE_HEADER_ID
-} uiTemplateType;
+/************************** Item ***************************/
 
-typedef struct uiTemplate {
-       struct uiTemplate *next, *prev;
-       uiTemplateType type;
+static char *ui_item_name_add_colon(char *name, char namestr[UI_MAX_NAME_STR])
+{
+       int len= strlen(name);
 
-       ListBase items;
-       int color;
-} uiTemplate;
+       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;
+       }
 
-typedef struct uiTemplateStck {
-       uiTemplate template;
-       uiLayout *sublayout;
-} uiTemplateStck;
+       return name;
+}
+
+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)
+                       return available-pos;
+               else
+                       return (item*available)/all;
+       }
+       else {
+               /* contents is smaller or equal to available space */
+               if(alignment == UI_LAYOUT_ALIGN_EXPAND) {
+                       if(last)
+                               return available-pos;
+                       else
+                               return (item*available)/all;
+               }
+               else
+                       return item;
+       }
+}
 
-typedef struct uiTemplateHeadID {
-       uiTemplate template;
+/* variable button size in which direction? */
+#define UI_ITEM_VARY_X 1
+#define UI_ITEM_VARY_Y 2
 
-       PointerRNA ptr;
-       char *propname;
-       int flag;
-       uiIDPoinFunc func;
-} uiTemplateHeadID;
+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;
+}
 
-/* Layout */
+/* 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;
 
-struct uiLayout {
-       ListBase templates;
-       int opcontext;
-       int dir;
-       int x, y, w, h;
-};
+       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;
 
-void ui_layout_free(uiLayout *layout);
-void ui_layout_end(const bContext *C, uiBlock *block, uiLayout *layout, int *x, int *y);
+               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;
 
-/************************** 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 int ui_item_fit(int item, int all, int available)
+static uiLayout *ui_item_local_sublayout(uiLayout *test, uiLayout *layout, int align)
 {
-       if(all > available)
-               return (item*available)/all;
+       uiLayout *sub;
+
+       if(ui_layout_local_dir(test) == UI_LAYOUT_HORIZONTAL)
+               sub= uiLayoutRow(layout, align);
+       else
+               sub= uiLayoutColumn(layout, align);
        
-       return all;
+       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 - YIC, w, YIC, 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(XIC, XIC*10 + BUTTON_SPACE_X, w);
-               buth= MIN2(YIC, butw);
+               uiBlockSetCurLayout(block, uiLayoutFree(layout, 0));
 
-               y += 2*(YIC - 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;
@@ -205,753 +374,1900 @@ 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)*YIC, w, YIC);
+                       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)*YIC, w, YIC);
+               }
+               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)*YIC, w, YIC);
+               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);
 }
 
-/* create lable + button for RNA property */
-static void ui_item_with_label(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)
 {
+       EnumPropertyItem *item;
+       const char *identifier;
        char *name;
-       int butw;
+       int a, totitem, itemw, icon, value, free;
 
-       if(rnaitem->item.name)
-               name= (char*)rnaitem->item.name;
-       else
-               name= (char*)RNA_property_ui_name(&rnaitem->ptr, rnaitem->prop);
-       
-       if(strcmp(name, "") != 0) {
-               butw= GetButStringLength(name);
-               uiDefBut(block, LABEL, 0, name, x, y, butw, h, NULL, 0.0, 0.0, 0, 0, "");
+       identifier= RNA_property_identifier(prop);
+       RNA_property_enum_items(block->evil_C, ptr, prop, &item, &totitem, &free);
 
-               x += butw;
-               w -= butw;
+       uiBlockSetCurLayout(block, ui_item_local_sublayout(layout, layout, 1));
+       for(a=0; a<totitem; a++) {
+               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);
        }
+       uiBlockSetCurLayout(block, layout);
 
-       uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, rnaitem->index, "", rnaitem->item.icon, x, y, w, h);
+       if(free)
+               MEM_freeN(item);
 }
 
-/* create buttons for an arbitrary item */
-static void ui_item_buts(uiBlock *block, uiItem *item, int x, int y, int w, int h)
+/* create label + button for RNA property */
+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)
 {
-       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);
-               /* 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;
+       uiLayout *sub;
+       uiBut *but;
+       PropertySubType subtype;
+       int labelw;
 
-               if(item->icon && item->name)
-                       uiDefIconTextButO(block, BUT, opitem->ot->idname, opitem->context, item->icon, (char*)item->name, x, y, w, h, NULL);
-               else if(item->icon)
-                       uiDefIconButO(block, BUT, opitem->ot->idname, opitem->context, item->icon, x, y, w, h, NULL);
-               /* text only */
-               else
-                       uiDefButO(block, BUT, opitem->ot->idname, opitem->context, (char*)item->name, x, y, w, h, NULL);
-       }
-       else if(item->type == ITEM_MENU) {
-               /* menu */
-               uiItemLMenu *menuitem= (uiItemLMenu*)item;
+       sub= uiLayoutRow(layout, 0);
+       uiBlockSetCurLayout(block, sub);
 
-               uiDefMenuBut(block, menuitem->func, NULL, (char*)item->name, x, y-2, w-3, h+4, "");
+       if(strcmp(name, "") != 0) {
+               /* 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;
        }
-       else if(item->type == ITEM_LABEL) {
-               /* label */
 
-               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, "");
-       }
-}
+       subtype= RNA_property_subtype(prop);
 
-/* estimated size of text + icon */
-static int ui_text_icon_width(const char *name, int icon)
-{
-       if(icon && name && strcmp(name, "") == 0)
-               return XIC; /* icon only */
-       else if(icon && name)
-               return XIC + GetButStringLength((char*)name); /* icon + text */
-       else if(name)
-               return GetButStringLength((char*)name); /* text only */
+       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
-               return 0;
+               but= uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w, h);
+
+       uiBlockSetCurLayout(block, layout);
+       return but;
 }
 
-/* estimated size of an item */
-static void ui_item_size(uiItem *item, int *r_w, int *r_h)
+/********************* Button Items *************************/
+
+/* disabled item */
+static void ui_item_disabled(uiLayout *layout, char *name)
 {
-       const char *name;
-       int w, h;
+       uiBlock *block= layout->root->block;
+       uiBut *but;
+       int w;
 
-       if(item->type == ITEM_RNA_PROPERTY) {
-               /* RNA property */
-               uiItemRNA *rnaitem= (uiItemRNA*)item;
-               PropertyType type;
-               PropertySubType subtype;
-               int len;
-
-               name= item->name;
-               if(!name)
-                       name= RNA_property_ui_name(&rnaitem->ptr, rnaitem->prop);
-
-               w= ui_text_icon_width(name, item->icon);
-               h= YIC;
-
-               /* 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_BOOLEAN && !item->icon)
-                       w += XIC;
-               else if(type == PROP_INT || type == PROP_FLOAT)
-                       w += 2*XIC;
-               else if(type == PROP_STRING)
-                       w += 8*XIC;
-
-               /* increase height for arrays */
-               if(rnaitem->index == RNA_NO_INDEX && len > 0) {
-                       if(name && strcmp(name, "") == 0 && item->icon == 0)
-                               h= 0;
-
-                       if(type == PROP_BOOLEAN && len == 20)
-                               h += 2*YIC;
-                       else if(subtype == PROP_MATRIX)
-                               h += ceil(sqrt(len))*YIC;
-                       else
-                               h += len*YIC;
-               }
-       }
-       else if(item->type == ITEM_OPERATOR) {
-               /* operator */
-               uiItemOp *opitem= (uiItemOp*)item;
+       uiBlockSetCurLayout(block, layout);
 
-               name= item->name;
-               if(!name)
-                       name= opitem->ot->name;
+       if(!name)
+               name= "";
 
-               w= ui_text_icon_width(name, item->icon);
-               h= YIC;
-       }
-       else {
-               /* other */
-               w= ui_text_icon_width(item->name, item->icon);
-               h= YIC;
-       }
+       w= ui_text_icon_width(layout, name, 0);
 
-       if(r_w) *r_w= w;
-       if(r_h) *r_h= h;
+       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 = "";
 }
 
-static void ui_item_free(uiItem *item)
+/* operator items */
+void uiItemFullO(uiLayout *layout, char *name, int icon, char *idname, IDProperty *properties, int context)
 {
-       if(item->type == ITEM_OPERATOR) {
-               uiItemOp *opitem= (uiItemOp*)item;
+       uiBlock *block= layout->root->block;
+       wmOperatorType *ot= WM_operatortype_find(idname, 0);
+       uiBut *but;
+       int w;
 
-               if(opitem->properties) {
-                       IDP_FreeProperty(opitem->properties);
-                       MEM_freeN(opitem->properties);
-               }
+       if(!ot) {
+               ui_item_disabled(layout, idname);
+               return;
+       }
+
+       if(!name)
+               name= ot->name;
+       if(layout->root->type == UI_LAYOUT_MENU && !icon)
+               icon= ICON_BLANK1;
+
+       /* create button */
+       uiBlockSetCurLayout(block, layout);
+
+       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, int slot, const 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(!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= 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, int slot, const char *name, int icon, char *opname, char *propname, int value)
+void uiItemEnumO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
 {
        PointerRNA ptr;
 
        WM_operator_properties_create(&ptr, opname);
        RNA_enum_set(&ptr, propname, value);
 
-       uiItemFullO(layout, slot, 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, int slot, char *opname, char *propname)
+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, slot, "", 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, int slot, const char *name, int icon, char *opname, char *propname, int value)
+void uiItemBooleanO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
 {
        PointerRNA ptr;
 
        WM_operator_properties_create(&ptr, opname);
        RNA_boolean_set(&ptr, propname, value);
 
-       uiItemFullO(layout, slot, name, icon, opname, ptr.data, layout->opcontext);
+       uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
 }
 
-void uiItemIntO(uiLayout *layout, int slot, const char *name, int icon, char *opname, char *propname, int value)
+void uiItemIntO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
 {
        PointerRNA ptr;
 
        WM_operator_properties_create(&ptr, opname);
        RNA_int_set(&ptr, propname, value);
 
-       uiItemFullO(layout, slot, name, icon, opname, ptr.data, layout->opcontext);
+       uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
 }
 
-void uiItemFloatO(uiLayout *layout, int slot, const char *name, int icon, char *opname, char *propname, float value)
+void uiItemFloatO(uiLayout *layout, char *name, int icon, char *opname, char *propname, float value)
 {
        PointerRNA ptr;
 
        WM_operator_properties_create(&ptr, opname);
        RNA_float_set(&ptr, propname, value);
 
-       uiItemFullO(layout, slot, name, icon, opname, ptr.data, layout->opcontext);
+       uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
 }
 
-void uiItemStringO(uiLayout *layout, int slot, const char *name, int icon, char *opname, char *propname, char *value)
+void uiItemStringO(uiLayout *layout, char *name, int icon, char *opname, char *propname, char *value)
 {
        PointerRNA ptr;
 
        WM_operator_properties_create(&ptr, opname);
        RNA_string_set(&ptr, propname, value);
 
-       uiItemFullO(layout, slot, name, icon, opname, ptr.data, layout->opcontext);
+       uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
 }
 
-void uiItemO(uiLayout *layout, int slot, const char *name, int icon, char *opname)
+void uiItemO(uiLayout *layout, char *name, int icon, char *opname)
 {
-       uiItemFullO(layout, slot, name, icon, opname, NULL, layout->opcontext);
+       uiItemFullO(layout, name, icon, opname, NULL, layout->root->opcontext);
 }
 
 /* RNA property items */
-void uiItemFullR(uiLayout *layout, int slot, const char *name, int icon, PointerRNA *ptr, char *propname, int index)
-{
-       uiTemplate *template= layout->templates.last;
-       PropertyRNA *prop;
-       uiItemRNA *rnaitem;
-       
-       prop= RNA_struct_find_property(ptr, propname);
-       if(!prop)
-               return;
-       
-       rnaitem= MEM_callocN(sizeof(uiItemRNA), "uiItemRNA");
-
-       rnaitem->item.name= name;
-       rnaitem->item.icon= icon;
-       rnaitem->item.type= ITEM_RNA_PROPERTY;
-       rnaitem->item.slot= slot;
 
-       rnaitem->ptr= *ptr;
-       rnaitem->prop= prop;
-       rnaitem->index= index;
+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;
+       }
 
-       BLI_addtail(&template->items, rnaitem);
+       *r_w= w;
+       *r_h= h;
 }
 
-void uiItemR(uiLayout *layout, int slot, const char *name, int icon, PointerRNA *ptr, char *propname)
+void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int value, int expand, int slider, int toggle)
 {
-       uiItemFullR(layout, slot, name, icon, ptr, propname, RNA_NO_INDEX);
-}
+       uiBlock *block= layout->root->block;
+       uiBut *but;
+       PropertyType type;
+       char namestr[UI_MAX_NAME_STR];
+       int len, w, h;
 
-/* menu item */
-void uiItemMenu(uiLayout *layout, int slot, const char *name, int icon, uiMenuCreateFunc func)
-{
-       uiTemplate *template= layout->templates.last;
-       uiItemLMenu *menuitem= MEM_callocN(sizeof(uiItemLMenu), "uiItemLMenu");
+       if(!ptr->data || !prop)
+               return;
 
-       menuitem->item.name= name;
-       menuitem->item.icon= icon;
-       menuitem->item.type= ITEM_MENU;
-       menuitem->item.slot= slot;
+       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; 
+       }
 
-       menuitem->func= func;
+       /* get size */
+       ui_item_rna_size(layout, name, icon, prop, index, &w, &h);
 
-       BLI_addtail(&template->items, menuitem);
-}
+       /* 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);
 
-/* label item */
-void uiItemLabel(uiLayout *layout, int slot, const char *name, int icon)
-{
-       uiTemplate *template= layout->templates.last;
-       uiItem *item= MEM_callocN(sizeof(uiItem), "uiItem");
+               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);
 
-       item->name= name;
-       item->icon= icon;
-       item->type= ITEM_LABEL;
-       item->slot= slot;
+               if(slider && but->type==NUM)
+                       but->type= NUMSLI;
 
-       BLI_addtail(&template->items, item);
+               if(toggle && but->type==OPTION)
+                       but->type= TOG;
+       }
 }
 
-/**************************** Template ***************************/
-
-/* multi-column layout */
-static void ui_layout_column(uiLayout *layout, uiBlock *block, uiTemplate *template, int *x, int *y, int w, int h)
+void uiItemR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, char *propname, int expand, int slider, int toggle)
 {
-       uiItem *item;
-       int col, totcol= 0, colx, coly, colw, miny, itemw, itemh;
+       PropertyRNA *prop;
 
-       /* compute number of columns */
-       for(item=template->items.first; item; item=item->next)
-               totcol= MAX2(item->slot+1, totcol);
-       
-       if(totcol == 0)
+       if(!ptr->data || !propname)
                return;
-       
-       colx= *x;
-       colw= (w - (totcol-1)*COLUMN_SPACE)/totcol;
-       miny= *y;
-
-       /* create column per column */
-       for(col=0; col<totcol; col++) {
-               coly= *y;
-
-               for(item=template->items.first; item; item=item->next) {
-                       if(item->slot != col)
-                               continue;
-
-                       ui_item_size(item, &itemw, &itemh);
 
-                       coly -= itemh + BUTTON_SPACE_Y;
-                       ui_item_buts(block, item, colx, coly, colw, itemh);
-               }
+       prop= RNA_struct_find_property(ptr, propname);
 
-               colx += colw + COLUMN_SPACE;
-               miny= MIN2(miny, coly);
+       if(!prop) {
+               ui_item_disabled(layout, propname);
+               printf("uiItemR: property not found: %s\n", propname);
+               return;
        }
 
-       *y= miny;
+       uiItemFullR(layout, name, icon, ptr, prop, RNA_NO_INDEX, 0, expand, slider, toggle);
 }
 
-/* left-right layout, with buttons aligned on both sides */
-static void ui_layout_lr(uiLayout *layout, uiBlock *block, uiTemplate *template, int *x, int *y, int w, int h)
+void uiItemEnumR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, int value)
 {
-       uiItem *item;
-       int totw= 0, maxh= 0, itemw, itemh, leftx, rightx;
-
-       /* 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);
-       }
+       PropertyRNA *prop;
 
-       if(totw == 0)
+       if(!ptr->data || !propname)
                return;
-       
-       /* create buttons starting from left and right */
-       leftx= *x;
-       rightx= *x + w;
 
-       for(item=template->items.first; item; item=item->next) {
-               ui_item_size(item, &itemw, &itemh);
-               itemw= ui_item_fit(itemw, totw+BUTTON_SPACE_X, w);
+       prop= RNA_struct_find_property(ptr, propname);
 
-               if(item->slot == UI_TSLOT_LR_LEFT) {
-                       ui_item_buts(block, item, leftx, *y-itemh, itemw, itemh);
-                       leftx += itemw;
-               }
-               else {
-                       rightx -= itemw;
-                       ui_item_buts(block, item, rightx, *y-itemh, itemw, itemh);
-               }
+       if(!prop || RNA_property_type(prop) != PROP_ENUM) {
+               ui_item_disabled(layout, propname);
+               printf("uiItemEnumR: enum property not found: %s\n", propname);
+               return;
        }
 
-       *y -= maxh;
+       uiItemFullR(layout, name, icon, ptr, prop, RNA_ENUM_VALUE, value, 0, 0, 0);
 }
 
-/* element in a stack layout */
-static void ui_layout_stack(const bContext *C, uiLayout *layout, uiBlock *block, uiTemplate *template, int *x, int *y, int w, int h)
+void uiItemEnumR_string(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, char *value)
 {
-       uiTemplateStck *stack= (uiTemplateStck*)template;
-       int starty, startx;
+       PropertyRNA *prop;
+       EnumPropertyItem *item;
+       int ivalue, a, free;
 
-       startx= *x;
-       starty= *y;
+       if(!ptr->data || !propname)
+               return;
 
-       /* some extra padding */
-       stack->sublayout->x= *x + STACK_SPACE;
-       stack->sublayout->w= w - 2*STACK_SPACE;
-       stack->sublayout->y= *y - STACK_SPACE;
-       stack->sublayout->h= h;
+       prop= RNA_struct_find_property(ptr, propname);
 
-       /* do layout for elements in sublayout */
-       ui_layout_end(C, block, stack->sublayout, NULL, y);
+       if(!prop || RNA_property_type(prop) != PROP_ENUM) {
+               ui_item_disabled(layout, propname);
+               printf("uiItemEnumR: enum property not found: %s\n", propname);
+               return;
+       }
 
-       /* roundbox around the sublayout */
-       uiDefBut(block, ROUNDBOX, 0, "", startx, *y, w, starty - *y, NULL, 7.0, 0.0, 3, 20, "");
-}
+       RNA_property_enum_items(layout->root->block->evil_C, ptr, prop, &item, NULL, &free);
 
-static void ui_layout_header_buttons(uiLayout *layout, uiBlock *block, uiTemplate *template, int *x, int *y, int w, int h)
-{
-       uiItem *item;
-       int itemw, itemh;
-       
-       uiBlockBeginAlign(block);
+       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;
+       }
 
-       for(item=template->items.first; item; item=item->next) {
-               ui_item_size(item, &itemw, &itemh);
-               ui_item_buts(block, item, *x, *y, itemw, itemh);
-               *x += itemw;
+       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;
+               }
        }
 
-       uiBlockEndAlign(block);
+       if(free)
+               MEM_freeN(item);
 }
 
-static void ui_layout_header_menus(const bContext *C, uiLayout *layout, uiBlock *block, uiTemplate *template, int *x, int *y, int w, int h)
+void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, char *propname)
 {
-       ScrArea *sa= CTX_wm_area(C);
+       PropertyRNA *prop;
 
-       *x= ED_area_header_standardbuttons(C, block, *y);
+       prop= RNA_struct_find_property(ptr, propname);
 
-       if((sa->flag & HEADER_NO_PULLDOWN)==0) {
-               uiBlockSetEmboss(block, UI_EMBOSSP);
-               ui_layout_header_buttons(layout, block, template, x, y, w, h);
+       if(!prop) {
+               ui_item_disabled(layout, propname);
+               return;
        }
 
-       uiBlockSetEmboss(block, UI_EMBOSS);
-}
+       if(RNA_property_type(prop) == PROP_ENUM) {
+               EnumPropertyItem *item;
+               int totitem, i, free;
 
-static void ui_layout_header_id(const bContext *C, uiLayout *layout, uiBlock *block, uiTemplate *template, int *x, int *y, int w, int h)
-{
-       uiTemplateHeadID *idtemplate= (uiTemplateHeadID*)template;
-       PointerRNA idptr;
+               RNA_property_enum_items(layout->root->block->evil_C, ptr, prop, &item, &totitem, &free);
 
-       idptr= RNA_pointer_get(&idtemplate->ptr, idtemplate->propname);
+               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);
 
-       *x= uiDefIDPoinButs(block, CTX_data_main(C), NULL, (ID*)idptr.data, ID_TXT, NULL, *x, *y,
-               idtemplate->func, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_OPEN|UI_ID_DELETE);
+               if(free)
+                       MEM_freeN(item);
+       }
 }
 
-void ui_template_free(uiTemplate *template)
+/* Pointer RNA button with search */
+
+static void rna_search_cb(const struct bContext *C, void *arg_but, char *str, uiSearchItems *items)
+{
+       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;
+
+       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;
+       
+       /* 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;
+       }
+       
+       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;
+       }
+
+       searchprop= RNA_struct_find_property(searchptr, searchpropname);
+
+       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};
+
+       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;
 
-       if(template->type == TEMPLATE_STACK) {
-               uiTemplateStck *stack= (uiTemplateStck*)template;
-               ui_layout_free(stack->sublayout);
+       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++;
        }
 
-       for(item=template->items.first; item; item=item->next)
-               ui_item_free(item);
+       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, &itemw, &itemh);
+                       minw= ui_litem_min_width(itemw);
+
+                       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;
 
-       BLI_freelistN(&template->items);
+                       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;
+                       }
+               }
+
+               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;
+       }
+
+       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;
+       }
 }
 
-/* template create functions */
-void uiTemplateColumn(uiLayout *layout)
+static void ui_litem_layout_column(uiLayout *litem)
 {
-       uiTemplate *template;
+       uiItem *item;
+       int itemh, x, y;
+
+       x= litem->x;
+       y= litem->y;
 
-       template= MEM_callocN(sizeof(uiTemplate), "uiTemplate");
-       template->type= TEMPLATE_COLUMN;
+       for(item=litem->items.first; item; item=item->next) {
+               ui_item_size(item, NULL, &itemh);
 
-       BLI_addtail(&layout->templates, template);
+               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 */
+}
 
-void uiTemplateLeftRight(uiLayout *layout)
+static void ui_litem_layout_root(uiLayout *litem)
 {
-       uiTemplate *template;
+       if(litem->root->type == UI_LAYOUT_HEADER)
+               ui_litem_layout_row(litem);
+       else
+               ui_litem_layout_column(litem);
+}
 
-       template= MEM_callocN(sizeof(uiTemplate), "uiTemplate");
-       template->type= TEMPLATE_LR;
+/* box layout */
+static void ui_litem_estimate_box(uiLayout *litem)
+{
+       uiStyle *style= litem->root->style;
 
-       BLI_addtail(&layout->templates, template);
+       ui_litem_estimate_column(litem);
+       litem->w += 2*style->boxspace;
+       litem->h += style->boxspace;
 }
 
-uiLayout *uiTemplateStack(uiLayout *layout)
+static void ui_litem_layout_box(uiLayout *litem)
 {
-       uiTemplateStck *stack;
+       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;
 
-       stack= MEM_callocN(sizeof(uiTemplateStck), "uiTemplateStck");
-       stack->template.type= TEMPLATE_STACK;
-       stack->sublayout= uiLayoutBegin(layout->dir, 0, 0, 0, 0);
-       BLI_addtail(&layout->templates, stack);
+       if(w != 0) litem->w += 2*style->boxspace;
+       if(h != 0) litem->h += style->boxspace;
 
-       return stack->sublayout;
+       /* 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;
 }
 
-void uiTemplateHeaderMenus(uiLayout *layout)
+/* multi-column layout, automatically flowing to the next */
+static void ui_litem_estimate_column_flow(uiLayout *litem)
 {
-       uiTemplate *template;
+       uiStyle *style= litem->root->style;
+       uiLayoutItemFlow *flow= (uiLayoutItemFlow*)litem;
+       uiItem *item;
+       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=litem->items.first; item; item=item->next) {
+               ui_item_size(item, &itemw, &itemh);
+               maxw= MAX2(maxw, itemw);
+               toth += itemh;
+               totitem++;
+       }
+
+       if(flow->number <= 0) {
+               /* auto compute number of columns, not very good */
+               if(maxw == 0) {
+                       flow->totcol= 1;
+                       return;
+               }
 
-       template= MEM_callocN(sizeof(uiTemplate), "uiTemplate");
-       template->type= TEMPLATE_HEADER_MENUS;
+               flow->totcol= MAX2(litem->root->emw/maxw, 1);
+               flow->totcol= MIN2(flow->totcol, totitem);
+       }
+       else
+               flow->totcol= flow->number;
+
+       /* compute sizes */
+       x= 0;
+       y= 0;
+       emy= 0;
+       miny= 0;
+
+       maxw= 0;
+       emh= toth/flow->totcol;
+
+       /* create column per column */
+       col= 0;
+       for(item=litem->items.first; item; item=item->next) {
+               ui_item_size(item, &itemw, &itemh);
 
-       BLI_addtail(&layout->templates, template);
+               y -= itemh + style->buttonspacey;
+               miny= MIN2(miny, y);
+               emy -= itemh;
+               maxw= MAX2(itemw, maxw);
+
+               /* decide to go to next one */
+               if(col < flow->totcol-1 && emy <= -emh) {
+                       x += maxw + litem->space;
+                       maxw= 0;
+                       y= 0;
+                       col++;
+               }
+       }
+
+       litem->w= x;
+       litem->h= litem->y - miny;
+}
+
+static void ui_litem_layout_column_flow(uiLayout *litem)
+{
+       uiStyle *style= litem->root->style;
+       uiLayoutItemFlow *flow= (uiLayoutItemFlow*)litem;
+       uiItem *item;
+       int col, x, y, w, emh, emy, miny, itemw, itemh;
+       int toth, totitem, offset;
+
+       /* 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);
+               toth += itemh;
+               totitem++;
+       }
+
+       /* compute sizes */
+       x= litem->x;
+       y= litem->y;
+       emy= 0;
+       miny= 0;
+
+       w= litem->w - (flow->totcol-1)*style->columnspace;
+       emh= toth/flow->totcol;
+
+       /* 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++;
+               }
+       }
+
+       litem->h= litem->y - miny;
+       litem->x= x;
+       litem->y= miny;
+}
+
+/* free layout */
+static void ui_litem_estimate_free(uiLayout *litem)
+{
+       uiItem *item;
+       int itemx, itemy, itemw, itemh, minx, miny;
+
+       minx= 1e6;
+       miny= 1e6;
+       litem->w= 0;
+       litem->h= 0;
+
+       for(item=litem->items.first; item; item=item->next) {
+               ui_item_offset(item, &itemx, &itemy);
+               ui_item_size(item, &itemw, &itemh);
+
+               minx= MIN2(minx, itemx);
+               miny= MIN2(miny, itemy);
+
+               litem->w= MAX2(litem->w, itemx+itemw);
+               litem->h= MAX2(litem->h, itemy+itemh);
+       }
+
+       litem->w -= minx;
+       litem->h -= miny;
+}
+
+static void ui_litem_layout_free(uiLayout *litem)
+{
+       uiItem *item;
+       float scalex=1.0f, scaley=1.0f;
+       int x, y, newx, newy, itemx, itemy, itemh, itemw, minx, miny, totw, toth;
+
+       minx= 1e6;
+       miny= 1e6;
+       totw= 0;
+       toth= 0;
+
+       for(item=litem->items.first; item; item=item->next) {
+               ui_item_offset(item, &itemx, &itemy);
+               ui_item_size(item, &itemw, &itemh);
+
+               minx= MIN2(minx, itemx);
+               miny= MIN2(miny, itemy);
+
+               totw= MAX2(totw, itemx+itemw);
+               toth= MAX2(toth, itemy+itemh);
+       }
+
+       totw -= minx;
+       toth -= miny;
+
+       if(litem->w && totw > 0)
+               scalex= (float)litem->w/(float)totw;
+       if(litem->h && toth > 0)
+               scaley= (float)litem->h/(float)toth;
+       
+       x= litem->x;
+       y= litem->y - scaley*toth;
+
+       for(item=litem->items.first; item; item=item->next) {
+               ui_item_offset(item, &itemx, &itemy);
+               ui_item_size(item, &itemw, &itemh);
+
+               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);
+       }
+
+       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_litem_layout_split(uiLayout *litem)
+{
+       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);
+
+               ui_item_position(item, x, y-itemh, colw, itemh);
+               x += colw;
+
+               if(item->next) {
+                       colw= (w - (int)(w*percentage))/(tot-1);
+                       colw= MAX2(colw, 0);
+
+                       x += litem->space;
+               }
+       }
+
+       litem->w= x - litem->x;
+       litem->h= litem->y - y;
+       litem->x= x;
+       litem->y= y;
+}
+
+/* layout create functions */
+uiLayout *uiLayoutRow(uiLayout *layout, int align)
+{
+       uiLayout *litem;
+
+       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);
+
+       uiBlockSetCurLayout(layout->root->block, litem);
+
+       return litem;
+}
+
+uiLayout *uiLayoutColumn(uiLayout *layout, int align)
+{
+       uiLayout *litem;
+
+       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);
+
+       uiBlockSetCurLayout(layout->root->block, litem);
+
+       return litem;
+}
+
+uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align)
+{
+       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);
+
+       uiBlockSetCurLayout(layout->root->block, &flow->litem);
+
+       return &flow->litem;
+}
+
+static uiLayout *ui_layout_box(uiLayout *layout, int type)
+{
+       uiLayoutItemBx *box;
+
+       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);
+
+       uiBlockSetCurLayout(layout->root->block, &box->litem);
+
+       box->roundbox= uiDefBut(layout->root->block, type, 0, "", 0, 0, 0, 0, NULL, 0.0, 0.0, 0, 0, "");
+
+       return &box->litem;
+}
+
+uiLayout *uiLayoutBox(uiLayout *layout)
+{
+       return ui_layout_box(layout, ROUNDBOX);
+}
+
+uiLayout *uiLayoutListBox(uiLayout *layout)
+{
+       return ui_layout_box(layout, LISTBOX);
+}
+
+ListBase *uiLayoutBoxGetList(uiLayout *layout)
+{
+       uiLayoutItemBx *box= (uiLayoutItemBx*)layout;
+       return &box->items;
+}
+
+uiLayout *uiLayoutFree(uiLayout *layout, int align)
+{
+       uiLayout *litem;
+
+       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);
+
+       uiBlockSetCurLayout(layout->root->block, litem);
+
+       return litem;
+}
+
+uiBlock *uiLayoutFreeBlock(uiLayout *layout)
+{
+       uiBlock *block;
+
+       block= uiLayoutGetBlock(layout);
+       uiLayoutFree(layout, 0);
+
+       return block;
 }
 
-void uiTemplateHeaderButtons(uiLayout *layout)
+uiLayout *uiLayoutSplit(uiLayout *layout, float percentage)
 {
-       uiTemplate *template;
+       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);
 
-       template= MEM_callocN(sizeof(uiTemplate), "uiTemplate");
-       template->type= TEMPLATE_HEADER_BUTTONS;
+       uiBlockSetCurLayout(layout->root->block, &split->litem);
 
-       BLI_addtail(&layout->templates, template);
+       return &split->litem;
 }
 
-void uiTemplateHeaderID(uiLayout *layout, PointerRNA *ptr, char *propname, int flag, uiIDPoinFunc func)
+void uiLayoutSetActive(uiLayout *layout, int active)
 {
-       uiTemplateHeadID *idtemplate;
+       layout->active= active;
+}
 
-       idtemplate= MEM_callocN(sizeof(uiTemplateHeadID), "uiTemplateHeadID");
-       idtemplate->template.type= TEMPLATE_HEADER_ID;
-       idtemplate->ptr= *ptr;
-       idtemplate->propname= propname;
-       idtemplate->flag= flag;
-       idtemplate->func= func;
+void uiLayoutSetEnabled(uiLayout *layout, int enabled)
+{
+       layout->enabled= enabled;
+}
 
-       BLI_addtail(&layout->templates, idtemplate);
+void uiLayoutSetRedAlert(uiLayout *layout, int redalert)
+{
+       layout->redalert= redalert;
 }
 
-void uiTemplateSetColor(uiLayout *layout, int color)
+void uiLayoutSetKeepAspect(uiLayout *layout, int keepaspect)
 {
-       uiTemplate *template= layout->templates.last;
+       layout->keepaspect= keepaspect;
+}
 
-       template->color= color;
+void uiLayoutSetAlignment(uiLayout *layout, int alignment)
+{
+       layout->alignment= alignment;
+}
+
+void uiLayoutSetScaleX(uiLayout *layout, float scale)
+{
+       layout->scale[0]= scale;
+}
+
+void uiLayoutSetScaleY(uiLayout *layout, float scale)
+{
+       layout->scale[1]= scale;
+}
+
+int uiLayoutGetActive(uiLayout *layout)
+{
+       return layout->active;
+}
+
+int uiLayoutGetEnabled(uiLayout *layout)
+{
+       return layout->enabled;
+}
+
+int uiLayoutGetRedAlert(uiLayout *layout)
+{
+       return layout->redalert;
+}
+
+int uiLayoutGetKeepAspect(uiLayout *layout)
+{
+       return layout->keepaspect;
+}
+
+int uiLayoutGetAlignment(uiLayout *layout)
+{
+       return layout->alignment;
+}
+
+float uiLayoutGetScaleX(uiLayout *layout)
+{
+       return layout->scale[0];
+}
+
+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;
-       int oldcolor= 0;
+       uiItem *item;
+       int x, y, w, h;
+
+       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];
+               }
 
-       for(template=layout->templates.first; template; template=template->next) {
-               if(template->color) {
-                       oldcolor= uiBlockGetCol(block);
-                       uiBlockSetCol(block, template->color);
+               if(scale[1] != 0.0f) {
+                       y *= scale[1];
+                       h *= scale[1];
                }
 
-               switch(template->type) {
-                       case TEMPLATE_COLUMN:
-                               ui_layout_column(layout, block, template, &layout->x, &layout->y, layout->w, layout->h);
+               ui_item_position(item, x, y, w, h);
+       }
+}
+
+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 TEMPLATE_LR:
-                               ui_layout_lr(layout, block, template, &layout->x, &layout->y, layout->w, layout->h);
+                       case ITEM_LAYOUT_ROW:
+                               ui_litem_estimate_row(litem);
                                break;
-                       case TEMPLATE_STACK:
-                               ui_layout_stack(C, layout, block, template, &layout->x, &layout->y, layout->w, layout->h);
+                       case ITEM_LAYOUT_BOX:
+                               ui_litem_estimate_box(litem);
                                break;
-                       case TEMPLATE_HEADER_MENUS:
-                               ui_layout_header_menus(C, layout, block, template, &layout->x, &layout->y, layout->w, layout->h);
+                       case ITEM_LAYOUT_ROOT:
+                               ui_litem_estimate_root(litem);
                                break;
-                       case TEMPLATE_HEADER_BUTTONS:
-                               ui_layout_header_buttons(layout, block, template, &layout->x, &layout->y, layout->w, layout->h);
+                       case ITEM_LAYOUT_FREE:
+                               ui_litem_estimate_free(litem);
                                break;
-                       case TEMPLATE_HEADER_ID:
-                               ui_layout_header_id(C, layout, block, template, &layout->x, &layout->y, layout->w, layout->h);
+                       case ITEM_LAYOUT_SPLIT:
+                               ui_litem_estimate_split(litem);
+                               break;
+                       default:
                                break;
                }
+       }
+}
 
-               if(template->color)
-                       uiBlockSetCol(block, oldcolor);
+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);
+       }
+}
 
-               if(layout->dir == UI_LAYOUT_HORIZONTAL)
-                       layout->x += TEMPLATE_SPACE;
+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
-                       layout->y -= TEMPLATE_SPACE;
+                       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;
+
+               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);
+
+               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;
-       
-       /* XXX temp, migration flag for drawing code */
-       uiBlockSetFlag(block, UI_BLOCK_2_50);
 }
 
-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 w, int h)
+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->w= w;
-       layout->h= h;
+       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->root->emh= em*UI_UNIT_Y;
+       }
+       else {
+               layout->w= size;
+               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 */
 
-static void ui_panel_layout(const bContext *C, ARegion *ar, char *blockname, char *panelname, char *tabname, uiPanelCreateFunc func, int order, int w)
+void uiBlockSetCurLayout(uiBlock *block, uiLayout *layout)
 {
-       uiBlock *block;
-       uiLayout *layout;
-       int xco, yco, x, y;
-
-       // XXX this only hides cruft
-
-       x= 20*order;
-       y= -100*(order+1);
+       block->curlayout= layout;
+}
 
-       block= uiBeginBlock(C, ar, blockname, UI_EMBOSS, UI_HELV);
-       if(uiNewPanel(C, ar, block, panelname, tabname, x, y, w, 0)==0) return;
+void ui_layout_add_but(uiLayout *layout, uiBut *but)
+{
+       uiButtonItem *bitem;
        
-       layout= uiLayoutBegin(UI_LAYOUT_VERTICAL, x, y, w, 0);
-
-       func(C, layout);
-
-       uiLayoutEnd(C, block, layout, &xco, &yco);
-       uiEndBlock(C, block);
-
-       uiNewPanelHeight(block, y - yco + 6);
+       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;
+       }
 }
 
-void uiCompactPanelLayout(const bContext *C, ARegion *ar, char *blockname, char *panelname, char *tabname, uiPanelCreateFunc func, int order)
+void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext)
 {
-       ui_panel_layout(C, ar, blockname, panelname, tabname, func, order, UI_COMPACT_PANEL_WIDTH-22);
+       layout->root->opcontext= opcontext;
 }
 
-void uiPanelLayout(const bContext *C, ARegion *ar, char *blockname, char *panelname, char *tabname, uiPanelCreateFunc func, int order)
+void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv)
 {
-       ui_panel_layout(C, ar, blockname, panelname, tabname, func, order, UI_PANEL_WIDTH-22);
+       layout->root->handlefunc= handlefunc;
+       layout->root->argv= argv;
 }
 
-void uiHeaderLayout(const bContext *C, ARegion *ar, uiHeaderCreateFunc func)
+void uiBlockLayoutResolve(const bContext *C, uiBlock *block, int *x, int *y)
 {
-       uiBlock *block;
-       uiLayout *layout;
-       int xco, yco;
+       uiLayoutRoot *root;
 
-       // XXX this only hides cruft
+       if(x) *x= 0;
+       if(y) *y= 0;
 
-       block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS, UI_HELV);
-       layout= uiLayoutBegin(UI_LAYOUT_HORIZONTAL, 8, 3, 0, 24);
+       block->curlayout= NULL;
 
-       func(C, layout);
+       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);
+       }
 
-       uiLayoutEnd(C, block, layout, &xco, &yco);
-       uiEndBlock(C, block);
-       uiDrawBlock(C, block);
+       BLI_freelistN(&block->layouts);
 
-       /* always as last  */
-       UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
+       /* 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);
+}