Merge of itasc branch. Project files, scons and cmake should be working. Makefile...
[blender.git] / source / blender / editors / interface / interface_templates.c
index a006187..31f371c 100644 (file)
@@ -36,6 +36,7 @@
 #include "BKE_icons.h"
 #include "BKE_global.h"
 #include "BKE_library.h"
+#include "BKE_main.h"
 #include "BKE_utildefines.h"
 
 #include "ED_screen.h"
@@ -56,12 +57,13 @@ void ui_template_fix_linking()
 
 /********************** Header Template *************************/
 
-void uiTemplateHeader(uiLayout *layout, bContext *C)
+void uiTemplateHeader(uiLayout *layout, bContext *C, int menus)
 {
        uiBlock *block;
        
        block= uiLayoutFreeBlock(layout);
-       ED_area_header_standardbuttons(C, block, 0);
+       if(menus) ED_area_header_standardbuttons(C, block, 0);
+       else ED_area_header_switchbutton(C, block, 0);
 }
 
 /********************** Search Callbacks *************************/
@@ -74,7 +76,7 @@ typedef struct TemplateID {
 } TemplateID;
 
 /* Search browse menu, assign  */
-static void id_search_call_cb(struct bContext *C, void *arg_template, void *item)
+static void id_search_call_cb(bContext *C, void *arg_template, void *item)
 {
        TemplateID *template= (TemplateID*)arg_template;
 
@@ -89,7 +91,7 @@ static void id_search_call_cb(struct bContext *C, void *arg_template, void *item
 }
 
 /* ID Search browse menu, do the search */
-static void id_search_cb(const struct bContext *C, void *arg_template, char *str, uiSearchItems *items)
+static void id_search_cb(const bContext *C, void *arg_template, char *str, uiSearchItems *items)
 {
        TemplateID *template= (TemplateID*)arg_template;
        Scene *scene= CTX_data_scene(C);
@@ -99,11 +101,12 @@ static void id_search_cb(const struct bContext *C, void *arg_template, char *str
 
        /* ID listbase */
        for(id= lb->first; id; id= id->next) {
-               iconid= ui_id_icon_get(scene, id);
+               if(BLI_strcasestr(id->name+2, str)) {
+                       iconid= ui_id_icon_get(scene, id);
 
-               if(BLI_strcasestr(id->name+2, str))
                        if(!uiSearchItemAdd(items, id->name+2, id, iconid))
                                break;
+               }
        }
 }
 
@@ -112,6 +115,7 @@ static uiBlock *search_menu(bContext *C, ARegion *ar, void *arg_litem)
 {
        static char search[256];
        static TemplateID template;
+       PointerRNA idptr;
        wmEvent event;
        wmWindow *win= CTX_wm_window(C);
        uiBlock *block;
@@ -122,6 +126,9 @@ static uiBlock *search_menu(bContext *C, ARegion *ar, void *arg_litem)
        /* arg_litem is malloced, can be freed by parent button */
        template= *((TemplateID*)arg_litem);
        
+       /* get active id for showing first item */
+       idptr= RNA_property_pointer_get(&template.ptr, template.prop);
+
        block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
        uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
        
@@ -129,7 +136,7 @@ static uiBlock *search_menu(bContext *C, ARegion *ar, void *arg_litem)
        uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
        
        but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, "");
-       uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb);
+       uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
        
        uiBoundsBlock(block, 6);
        uiBlockSetDirection(block, UI_DOWN);    
@@ -151,15 +158,21 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
 {
        TemplateID *template= (TemplateID*)arg_litem;
        PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop);
-       ID *id= idptr.data;
+       ID *id= idptr.data, *newid;
        int event= GET_INT_FROM_POINTER(arg_event);
        
        switch(event) {
                case UI_ID_BROWSE:
                case UI_ID_PIN:
+                       printf("warning, id event %d shouldnt come here\n", event);
+                       break;
                case UI_ID_OPEN:
                case UI_ID_ADD_NEW:
-                       printf("warning, id event %d shouldnt come here\n", event);
+                       if(template->idlb->last) {
+                               RNA_id_pointer_create(template->idlb->last, &idptr);
+                               RNA_property_pointer_set(&template->ptr, template->prop, idptr);
+                               RNA_property_update(C, &template->ptr, template->prop);
+                       }
                        break;
                case UI_ID_DELETE:
                        memset(&idptr, 0, sizeof(idptr));
@@ -173,76 +186,158 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
                        }
                        else return;
                        break;
-#if 0
-               case UI_ID_ALONE:
-                       if(!id || id->us < 1)
-                               return;
-                       break;
                case UI_ID_LOCAL:
-                       if(!id || id->us < 1)
-                               return;
+                       if(id) {
+                               if(id_make_local(id, 0)) {
+                                       /* reassign to get get proper updates/notifiers */
+                                       idptr= RNA_property_pointer_get(&template->ptr, template->prop);
+                                       RNA_property_pointer_set(&template->ptr, template->prop, idptr);
+                                       RNA_property_update(C, &template->ptr, template->prop);
+                               }
+                       }
+                       break;
+               case UI_ID_ALONE:
+                       if(id) {
+                               /* make copy */
+                               if(id_copy(id, &newid, 0) && newid) {
+                                       /* us is 1 by convention, but RNA_property_pointer_set
+                                          will also incremement it, so set it to zero */
+                                       newid->us= 0;
+
+                                       /* assign copy */
+                                       RNA_id_pointer_create(newid, &idptr);
+                                       RNA_property_pointer_set(&template->ptr, template->prop, idptr);
+                                       RNA_property_update(C, &template->ptr, template->prop);
+                               }
+                       }
                        break;
+#if 0
                case UI_ID_AUTO_NAME:
                        break;
 #endif
        }
 }
 
-static void template_ID(bContext *C, uiBlock *block, TemplateID *template, StructRNA *type, int flag, char *newop, char *unlinkop)
+static void template_ID(bContext *C, uiBlock *block, TemplateID *template, StructRNA *type, int flag, char *newop, char *openop, char *unlinkop)
 {
        uiBut *but;
        PointerRNA idptr;
        ListBase *lb;
+       ID *id, *idfrom;
 
        idptr= RNA_property_pointer_get(&template->ptr, template->prop);
+       id= idptr.data;
+       idfrom= template->ptr.id.data;
        lb= template->idlb;
 
+       uiBlockBeginAlign(block);
+
        if(idptr.type)
                type= idptr.type;
-       if(type)
-               uiDefIconBut(block, LABEL, 0, RNA_struct_ui_icon(type), 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
 
-       uiBlockBeginAlign(block);
-       if(flag & UI_ID_BROWSE)
-               uiDefBlockButN(block, search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X, UI_UNIT_Y, "Browse ID data");
+       if(flag & UI_ID_BROWSE) {
+               but= uiDefBlockButN(block, search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*1.6, UI_UNIT_Y, "Browse ID data");
+               if(type) {
+                       but->icon= RNA_struct_ui_icon(type);
+                       but->flag|= UI_HAS_ICON;
+                       but->flag|= UI_ICON_LEFT;
+               }
+
+               if((idfrom && idfrom->lib))
+                       uiButSetFlag(but, UI_BUT_DISABLED);
+       }
 
        /* text button with name */
-       if(idptr.data) {
+       if(id) {
                char name[64];
 
-               //text_idbutton(idptr.data, name);
+               //text_idbutton(id, name);
                name[0]= '\0';
                but= uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X*6, UI_UNIT_Y, &idptr, "name", -1, 0, 0, -1, -1, NULL);
                uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
+
+               if(id->lib) {
+                       if(id->flag & LIB_INDIRECT) {
+                               but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, 0, 0, 0, 0, 0,
+                                       "Indirect library datablock, cannot change.");
+                               uiButSetFlag(but, UI_BUT_DISABLED);
+                       }
+                       else {
+                               but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, 0, 0, 0, 0, 0,
+                                       "Direct linked library datablock, click to make local.");
+                               if(!id_make_local(id, 1 /* test */) || (idfrom && idfrom->lib))
+                                       uiButSetFlag(but, UI_BUT_DISABLED);
+                       }
+
+                       uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_LOCAL));
+               }
+
+               if(id->us > 1) {
+                       char str[32];
+
+                       sprintf(str, "%d", id->us);
+
+                       if(id->us<10)
+                               but= uiDefBut(block, BUT, 0, str, 0,0,UI_UNIT_X,UI_UNIT_Y, 0, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy.");
+                       else
+                               but= uiDefBut(block, BUT, 0, str, 0,0,UI_UNIT_X+10,UI_UNIT_Y, 0, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy.");
+
+                       uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE));
+                       if(!id_copy(id, NULL, 1 /* test only */) || (idfrom && idfrom->lib))
+                               uiButSetFlag(but, UI_BUT_DISABLED);
+               }
        }
        
        if(flag & UI_ID_ADD_NEW) {
-               int w= idptr.data?UI_UNIT_X:UI_UNIT_X*6;
+               int w= id?UI_UNIT_X: (flag & UI_ID_OPEN)? UI_UNIT_X*3: UI_UNIT_X*6;
                
                if(newop) {
-                       but= uiDefIconTextButO(block, BUT, newop, WM_OP_EXEC_REGION_WIN, ICON_ZOOMIN, "Add New", 0, 0, w, UI_UNIT_Y, NULL);
+                       but= uiDefIconTextButO(block, BUT, newop, WM_OP_EXEC_REGION_WIN, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL);
+                       uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
                }
                else {
-                       but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, "Add New", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+                       but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
                        uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
                }
+
+               if((idfrom && idfrom->lib))
+                       uiButSetFlag(but, UI_BUT_DISABLED);
+       }
+
+       if(flag & UI_ID_OPEN) {
+               int w= id?UI_UNIT_X: (flag & UI_ID_ADD_NEW)? UI_UNIT_X*3: UI_UNIT_X*6;
+               
+               if(openop) {
+                       but= uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_REGION_WIN, ICON_FILESEL, (id)? "": "Open", 0, 0, w, UI_UNIT_Y, NULL);
+                       uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
+               }
+               else {
+                       but= uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id)? "": "Open", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+                       uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
+               }
+
+               if((idfrom && idfrom->lib))
+                       uiButSetFlag(but, UI_BUT_DISABLED);
        }
        
        /* delete button */
-       if(idptr.data && (flag & UI_ID_DELETE)) {
+       if(id && (flag & UI_ID_DELETE)) {
                if(unlinkop) {
-                       but= uiDefIconButO(block, BUT, unlinkop, WM_OP_EXEC_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+                       but= uiDefIconButO(block, BUT, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
                }
                else {
                        but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
                        uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE));
                }
+
+               if((idfrom && idfrom->lib))
+                       uiButSetFlag(but, UI_BUT_DISABLED);
        }
        
        uiBlockEndAlign(block);
 }
 
-void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *unlinkop)
+void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop)
 {
        TemplateID *template;
        uiBlock *block;
@@ -250,9 +345,6 @@ void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname
        StructRNA *type;
        int flag;
 
-       if(!ptr->data)
-               return;
-
        prop= RNA_struct_find_property(ptr, propname);
 
        if(!prop || RNA_property_type(prop) != PROP_POINTER) {
@@ -268,6 +360,8 @@ void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname
 
        if(newop)
                flag |= UI_ID_ADD_NEW;
+       if(openop)
+               flag |= UI_ID_OPEN;
 
        type= RNA_property_pointer_type(ptr, prop);
        template->idlb= wich_libbase(CTX_data_main(C), RNA_type_to_ID_code(type));
@@ -275,7 +369,7 @@ void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname
        if(template->idlb) {
                uiLayoutRow(layout, 1);
                block= uiLayoutGetBlock(layout);
-               template_ID(C, block, template, type, flag, newop, unlinkop);
+               template_ID(C, block, template, type, flag, newop, openop, unlinkop);
        }
 
        MEM_freeN(template);
@@ -308,142 +402,15 @@ void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname
 
 #include "ED_object.h"
 
-static void modifiers_del(bContext *C, void *ob_v, void *md_v)
-{
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= ob_v;
-       ReportList reports;
-
-       BKE_reports_init(&reports, RPT_STORE);
-
-       if(ED_object_modifier_delete(&reports, ob_v, md_v)) {
-               WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
-               DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
-
-               ED_undo_push(C, "Delete modifier");
-       }
-       else
-               uiPupMenuReports(C, &reports);
-
-       BKE_reports_clear(&reports);
-}
-
-static void modifiers_activate(bContext *C, void *ob_v, void *md_v)
-{
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= ob_v;
-
-       WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
-       DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
-}
-
-static void modifiers_moveUp(bContext *C, void *ob_v, void *md_v)
-{
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= ob_v;
-       ReportList reports;
-
-       BKE_reports_init(&reports, RPT_STORE);
-
-       if(ED_object_modifier_move_up(&reports, ob_v, md_v)) {
-               WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
-               DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
-
-               ED_undo_push(C, "Move modifier");
-       }
-       else
-               uiPupMenuReports(C, &reports);
-
-       BKE_reports_clear(&reports);
-}
-
-static void modifiers_moveDown(bContext *C, void *ob_v, void *md_v)
-{
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= ob_v;
-       ReportList reports;
-
-       BKE_reports_init(&reports, RPT_STORE);
-
-       if(ED_object_modifier_move_down(&reports, ob_v, md_v)) {
-               WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
-               DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
-
-               ED_undo_push(C, "Move modifier");
-       }
-       else
-               uiPupMenuReports(C, &reports);
-
-       BKE_reports_clear(&reports);
-}
-
-static void modifiers_convertParticles(bContext *C, void *obv, void *mdv)
-{
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= obv;
-       ReportList reports;
-
-       BKE_reports_init(&reports, RPT_STORE);
-
-       if(ED_object_modifier_convert(&reports, scene, obv, mdv)) {
-               WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
-               DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
-
-               ED_undo_push(C, "Convert particles to mesh object(s).");
-       }
-       else
-               uiPupMenuReports(C, &reports);
-
-       BKE_reports_clear(&reports);
-}
-
-static void modifiers_applyModifier(bContext *C, void *obv, void *mdv)
-{
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= obv;
-       ReportList reports;
-
-       BKE_reports_init(&reports, RPT_STORE);
-
-       if(ED_object_modifier_apply(&reports, scene, obv, mdv)) {
-               WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
-               DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
-
-               ED_undo_push(C, "Apply modifier");
-       }
-       else
-               uiPupMenuReports(C, &reports);
-
-       BKE_reports_clear(&reports);
-}
-
-static void modifiers_copyModifier(bContext *C, void *ob_v, void *md_v)
-{
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= ob_v;
-       ReportList reports;
-
-       BKE_reports_init(&reports, RPT_STORE);
-
-       if(ED_object_modifier_copy(&reports, ob_v, md_v)) {
-               WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
-               DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
-               ED_undo_push(C, "Copy modifier");
-       }
-       else
-               uiPupMenuReports(C, &reports);
-
-       BKE_reports_clear(&reports);
-}
-
 static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v)
 {
-       Scene *scene= CTX_data_scene(C);
        Object *ob = ob_v;
-       ModifierData *md;
-       
+       ModifierData *md= md_v;
        int i, cageIndex = modifiers_getCageIndex(ob, NULL );
 
+       /* undo button operation */
+       md->mode ^= eModifierMode_OnCage;
+
        for(i = 0, md=ob->modifiers.first; md; ++i, md=md->next) {
                if(md == md_v) {
                        if(i >= cageIndex)
@@ -453,12 +420,11 @@ static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v)
        }
 
        WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
-       DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
 }
 
 static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v)
 {
-       Scene *scene= CTX_data_scene(C);
        Object *ob = ob_v;
        ModifierData *md = md_v;
        ModifierData *nmd = modifier_new(md->type);
@@ -471,22 +437,14 @@ static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v)
        ob->partype = PAROBJECT;
 
        WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
-       DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
 
        ED_undo_push(C, "Modifier convert to real");
 }
 
 static int modifier_can_delete(ModifierData *md)
 {
-       // deletion over the deflection panel
        // fluid particle modifier can't be deleted here
-
-       if(md->type==eModifierType_Fluidsim)
-               return 0;
-       if(md->type==eModifierType_Collision)
-               return 0;
-       if(md->type==eModifierType_Surface)
-               return 0;
        if(md->type == eModifierType_ParticleSystem)
                if(((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID)
                        return 0;
@@ -500,12 +458,12 @@ static uiLayout *draw_modifier(uiLayout *layout, Object *ob, ModifierData *md, i
        PointerRNA ptr;
        uiBut *but;
        uiBlock *block;
-       uiLayout *column, *row, *subrow, *result= NULL;
-       int isVirtual = md->mode&eModifierMode_Virtual;
+       uiLayout *column, *row, *result= NULL;
+       int isVirtual = md->mode & eModifierMode_Virtual;
        // XXX short color = md->error?TH_REDALERT:TH_BUT_NEUTRAL;
-       short width = 295, buttonWidth = width-120-10;
        char str[128];
 
+       /* create RNA pointer */
        RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr);
 
        column= uiLayoutColumn(layout, 1);
@@ -516,131 +474,112 @@ static uiLayout *draw_modifier(uiLayout *layout, Object *ob, ModifierData *md, i
                /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
 
        row= uiLayoutRow(uiLayoutBox(column), 0);
-       block= uiLayoutGetBlock(row);
+       uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_EXPAND);
 
-       subrow= uiLayoutRow(row, 0);
-       uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_LEFT);
+       block= uiLayoutGetBlock(row);
 
        //uiDefBut(block, ROUNDBOX, 0, "", x-10, y-4, width, 25, NULL, 7.0, 0.0, 
-       //               (!isVirtual && (md->mode&eModifierMode_Expanded))?3:15, 20, ""); 
+       //               (!isVirtual && (md->mode & eModifierMode_Expanded))?3:15, 20, ""); 
        /* XXX uiBlockSetCol(block, TH_AUTO); */
        
        /* open/close icon */
-       if (!isVirtual) {
+       if(!isVirtual) {
                uiBlockSetEmboss(block, UI_EMBOSSN);
                uiDefIconButBitI(block, ICONTOG, eModifierMode_Expanded, 0, ICON_TRIA_RIGHT, 0, 0, UI_UNIT_X, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, "Collapse/Expand Modifier");
        }
        
        /* modifier-type icon */
-       uiDefIconBut(block, BUT, 0, RNA_struct_ui_icon(ptr.type), 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Current Modifier Type");
+       uiItemL(row, "", RNA_struct_ui_icon(ptr.type));
        
        uiBlockSetEmboss(block, UI_EMBOSS);
        
-       if (isVirtual) {
+       if(isVirtual) {
+               /* virtual modifier */
                sprintf(str, "%s parent deform", md->name);
                uiDefBut(block, LABEL, 0, str, 0, 0, 185, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name"); 
 
                but = uiDefBut(block, BUT, 0, "Make Real", 0, 0, 80, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Convert virtual modifier to a real modifier");
                uiButSetFunc(but, modifiers_convertToReal, ob, md);
-       } else {
+       }
+       else {
+               /* real modifier */
                uiBlockBeginAlign(block);
-               uiDefBut(block, TEX, 0, "", 0, 0, buttonWidth-40, UI_UNIT_Y, md->name, 0.0, sizeof(md->name)-1, 0.0, 0.0, "Modifier name"); 
+               uiItemR(row, "", 0, &ptr, "name", 0);
 
                /* Softbody not allowed in this situation, enforce! */
-               if (((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) && (md->type!=eModifierType_Surface)) {
-                       uiDefIconButBitI(block, TOG, eModifierMode_Render, 0, ICON_SCENE, 0, 0, 19, UI_UNIT_Y,&md->mode, 0, 0, 1, 0, "Enable modifier during rendering");
-                       but= uiDefIconButBitI(block, TOG, eModifierMode_Realtime, 0, ICON_VIEW3D, 0, 0, 19, UI_UNIT_Y,&md->mode, 0, 0, 1, 0, "Enable modifier during interactive display");
-                       uiButSetFunc(but, modifiers_activate, ob, md);
-                       if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
-                               but= uiDefIconButBitI(block, TOG, eModifierMode_Editmode, 0, ICON_EDITMODE_HLT, 0, 0, 19, UI_UNIT_Y,&md->mode, 0, 0, 1, 0, "Enable modifier during Editmode (only if enabled for display)");
-                               uiButSetFunc(but, modifiers_activate, ob, md);
-                       }
+               if(((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) && (md->type!=eModifierType_Surface)) {
+                       uiItemR(row, "", ICON_SCENE, &ptr, "render", 0);
+                       uiItemR(row, "", ICON_RESTRICT_VIEW_OFF, &ptr, "realtime", 0);
+
+                       if(mti->flags & eModifierTypeFlag_SupportsEditmode)
+                               uiItemR(row, "", ICON_EDITMODE_HLT, &ptr, "editmode", 0);
                }
-               uiBlockEndAlign(block);
+               
 
                /* XXX uiBlockSetEmboss(block, UI_EMBOSSR); */
 
-               if (ob->type==OB_MESH && modifier_couldBeCage(md) && index<=lastCageIndex) {
-                       int icon; //, color;
-
-                       if (index==cageIndex) {
-                               // XXX color = TH_BUT_SETTING;
-                               icon = VICON_EDITMODE_HLT;
-                       } else if (index<cageIndex) {
-                               // XXX color = TH_BUT_NEUTRAL;
-                               icon = VICON_EDITMODE_DEHLT;
-                       } else {
-                               // XXX color = TH_BUT_NEUTRAL;
-                               icon = ICON_BLANK1;
-                       }
+               if(ob->type==OB_MESH && modifier_couldBeCage(md) && index<=lastCageIndex) {
                        /* XXX uiBlockSetCol(block, color); */
-                       but = uiDefIconBut(block, BUT, 0, icon, 0, 0, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Apply modifier to editing cage during Editmode");
+                       but = uiDefIconButBitI(block, TOG, eModifierMode_OnCage, 0, ICON_MESH_DATA, 0, 0, 16, 20, &md->mode, 0.0, 0.0, 0.0, 0.0, "Apply modifier to editing cage during Editmode");
+                       if(index < cageIndex)
+                               uiButSetFlag(but, UI_BUT_DISABLED);
                        uiButSetFunc(but, modifiers_setOnCage, ob, md);
+                       uiBlockEndAlign(block);
                        /* XXX uiBlockSetCol(block, TH_AUTO); */
                }
        }
 
-       subrow= uiLayoutRow(row, 0);
-       uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_RIGHT);
-
+       /* up/down/delete */
        if(!isVirtual) {
                /* XXX uiBlockSetCol(block, TH_BUT_ACTION); */
-
-               but = uiDefIconBut(block, BUT, 0, VICON_MOVE_UP, 0, 0, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Move modifier up in stack");
-               uiButSetFunc(but, modifiers_moveUp, ob, md);
-
-               but = uiDefIconBut(block, BUT, 0, VICON_MOVE_DOWN, 0, 0, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Move modifier down in stack");
-               uiButSetFunc(but, modifiers_moveDown, ob, md);
+               uiBlockBeginAlign(block);
+               uiItemO(row, "", VICON_MOVE_UP, "OBJECT_OT_modifier_move_up");
+               uiItemO(row, "", VICON_MOVE_DOWN, "OBJECT_OT_modifier_move_down");
+               uiBlockEndAlign(block);
                
                uiBlockSetEmboss(block, UI_EMBOSSN);
-               
-               if(modifier_can_delete(md)) {
-                       but = uiDefIconBut(block, BUT, 0, VICON_X, 0, 0, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Delete modifier");
-                       uiButSetFunc(but, modifiers_del, ob, md);
-               }
+
+               if(modifier_can_delete(md))
+                       uiItemO(row, "", VICON_X, "OBJECT_OT_modifier_remove");
+
                /* XXX uiBlockSetCol(block, TH_AUTO); */
        }
 
        uiBlockSetEmboss(block, UI_EMBOSS);
 
-       if(!isVirtual && (md->mode&eModifierMode_Expanded)) {
+       if(!isVirtual && (md->mode & eModifierMode_Expanded)) {
+               /* apply/convert/copy */
                uiLayout *box;
 
                box= uiLayoutBox(column);
                row= uiLayoutRow(box, 1);
 
-               if (!isVirtual && (md->type!=eModifierType_Collision) && (md->type!=eModifierType_Surface)) {
-                       uiBlockSetButLock(block, object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); /* only here obdata, the rest of modifiers is ob level */
+               if(!isVirtual && (md->type!=eModifierType_Collision) && (md->type!=eModifierType_Surface)) {
+                       /* only here obdata, the rest of modifiers is ob level */
+                       uiBlockSetButLock(block, object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
 
-                                               if (md->type==eModifierType_ParticleSystem) {
+                       if(md->type==eModifierType_ParticleSystem) {
                        ParticleSystem *psys= ((ParticleSystemModifierData *)md)->psys;
 
-                       if(!(G.f & G_PARTICLEEDIT)) {
-                                       if(ELEM3(psys->part->draw_as, PART_DRAW_PATH, PART_DRAW_GR, PART_DRAW_OB) && psys->pathcache) {
-                                               but = uiDefBut(block, BUT, 0, "Convert",        0,0,60,19, 0, 0, 0, 0, 0, "Convert the current particles to a mesh object");
-                                               uiButSetFunc(but, modifiers_convertParticles, ob, md);
-                                       }
-                               }
-                       }
-                       else{
-                               but = uiDefBut(block, BUT, 0, "Apply",  0,0,60,19, 0, 0, 0, 0, 0, "Apply the current modifier and remove from the stack");
-                               uiButSetFunc(but, modifiers_applyModifier, ob, md);
+                       if(!(ob->mode & OB_MODE_PARTICLE_EDIT))
+                                       if(ELEM3(psys->part->ren_as, PART_DRAW_PATH, PART_DRAW_GR, PART_DRAW_OB) && psys->pathcache)
+                                               uiItemO(row, "Convert", 0, "OBJECT_OT_modifier_convert");
                        }
+                       else
+                               uiItemO(row, "Apply", 0, "OBJECT_OT_modifier_apply");
                        
                        uiBlockClearButLock(block);
                        uiBlockSetButLock(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE);
 
-                       if (md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth)) {
-                               but = uiDefBut(block, BUT, 0, "Copy",   0,0,60,19, 0, 0, 0, 0, 0, "Duplicate the current modifier at the same position in the stack");
-                               uiButSetFunc(but, modifiers_copyModifier, ob, md);
-                       }
+                       if(!ELEM4(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem, eModifierType_Cloth))
+                               uiItemO(row, "Copy", 0, "OBJECT_OT_modifier_copy");
                }
 
                result= uiLayoutColumn(box, 0);
                block= uiLayoutFreeBlock(box);
        }
 
-       if (md->error) {
+       if(md->error) {
                row = uiLayoutRow(uiLayoutBox(column), 0);
 
                /* XXX uiBlockSetCol(block, color); */
@@ -682,7 +621,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, PointerRNA *ptr)
        for(i=0; vmd; i++, vmd=vmd->next) {
                if(md == vmd)
                        return draw_modifier(layout, ob, md, i, cageIndex, lastCageIndex);
-               else if(vmd->mode&eModifierMode_Virtual)
+               else if(vmd->mode & eModifierMode_Virtual)
                        i--;
        }
 
@@ -735,8 +674,10 @@ void do_constraint_panels(bContext *C, void *arg, int event)
        
        if(ob->pose) update_pose_constraint_flags(ob->pose);
        
-       if(ob->type==OB_ARMATURE) DAG_object_flush_update(scene, ob, OB_RECALC_DATA|OB_RECALC_OB);
-       else DAG_object_flush_update(scene, ob, OB_RECALC_OB);
+       if(ob->type==OB_ARMATURE) DAG_id_flush_update(&ob->id, OB_RECALC_DATA|OB_RECALC_OB);
+       else DAG_id_flush_update(&ob->id, OB_RECALC_OB);
+
+       WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob);
        
        // XXX allqueue(REDRAWVIEW3D, 0);
        // XXX allqueue(REDRAWBUTSOBJECT, 0);
@@ -748,44 +689,22 @@ static void constraint_active_func(bContext *C, void *ob_v, void *con_v)
        ED_object_constraint_set_active(ob_v, con_v);
 }
 
-static void del_constraint_func (bContext *C, void *ob_v, void *con_v)
-{
-       if(ED_object_constraint_delete(NULL, ob_v, con_v))
-               ED_undo_push(C, "Delete Constraint");
-}
-
-static void verify_constraint_name_func (bContext *C, void *con_v, void *name_v)
+static void verify_constraint_name_func (bContext *C, void *con_v, void *dummy)
 {
        Object *ob= CTX_data_active_object(C);
        bConstraint *con= con_v;
-       char oldname[32];       
        
        if (!con)
                return;
        
-       /* put on the stack */
-       BLI_strncpy(oldname, (char *)name_v, 32);
-       
-       ED_object_constraint_rename(ob, con, oldname);
+       ED_object_constraint_rename(ob, con, NULL);
        ED_object_constraint_set_active(ob, con);
        // XXX allqueue(REDRAWACTION, 0); 
 }
 
-static void constraint_moveUp(bContext *C, void *ob_v, void *con_v)
-{
-       if(ED_object_constraint_move_up(NULL, ob_v, con_v))
-               ED_undo_push(C, "Move Constraint");
-}
-
-static void constraint_moveDown(bContext *C, void *ob_v, void *con_v)
-{
-       if(ED_object_constraint_move_down(NULL, ob_v, con_v))
-               ED_undo_push(C, "Move Constraint");
-}
-
 /* some commonly used macros in the constraints drawing code */
 #define is_armature_target(target) (target && target->type==OB_ARMATURE)
-#define is_armature_owner(ob) ((ob->type == OB_ARMATURE) && (ob->flag & OB_POSEMODE))
+#define is_armature_owner(ob) ((ob->type == OB_ARMATURE) && (ob->mode & OB_MODE_POSE))
 #define is_geom_target(target) (target && (ELEM(target->type, OB_MESH, OB_LATTICE)) )
 
 /* Helper function for draw constraint - draws constraint space stuff 
@@ -844,6 +763,22 @@ static void draw_constraint_spaceselect (uiBlock *block, bConstraint *con, short
        }
 }
 
+static void test_obpoin_but(bContext *C, char *name, ID **idpp)
+{
+       ID *id;
+       
+       id= CTX_data_main(C)->object.first;
+       while(id) {
+               if( strcmp(name, id->name+2)==0 ) {
+                       *idpp= id;
+                       id_lib_extern(id);      /* checks lib data, sets correct flag for saving then */
+                       return;
+               }
+               id= id->next;
+       }
+       *idpp= NULL;
+}
+
 /* draw panel showing settings for a constraint */
 static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
 {
@@ -889,7 +824,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
        box= uiLayoutBox(col);
        row= uiLayoutRow(box, 0);
 
-       block= uiLayoutFreeBlock(box);
+       block= uiLayoutGetBlock(box);
 
        subrow= uiLayoutRow(row, 0);
        uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_LEFT);
@@ -904,27 +839,19 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
        uiDefIconButBitS(block, ICONTOG, CONSTRAINT_EXPAND, B_CONSTRAINT_TEST, ICON_TRIA_RIGHT, xco-10, yco, 20, 20, &con->flag, 0.0, 0.0, 0.0, 0.0, "Collapse/Expand Constraint");
        
        /* name */      
-       if ((con->flag & CONSTRAINT_EXPAND) && (proxy_protected==0)) {
-               /* XXX if (con->flag & CONSTRAINT_DISABLE)
-                       uiBlockSetCol(block, TH_REDALERT);*/
-               
-               uiBlockSetEmboss(block, UI_EMBOSS);
-               
-               uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, xco+10, yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
-               
+       uiBlockSetEmboss(block, UI_EMBOSS);
+       
+       /* XXX if (con->flag & CONSTRAINT_DISABLE)
+               uiBlockSetCol(block, TH_REDALERT);*/
+       
+       uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, xco+10, yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+       
+       if(proxy_protected == 0) {
                but = uiDefBut(block, TEX, B_CONSTRAINT_TEST, "", xco+120, yco, 85, 18, con->name, 0.0, 29.0, 0.0, 0.0, "Constraint name"); 
-               uiButSetFunc(but, verify_constraint_name_func, con, NULL);
-       }       
-       else {
-               uiBlockSetEmboss(block, UI_EMBOSSN);
-               
-               /* XXX if (con->flag & CONSTRAINT_DISABLE)
-                       uiBlockSetCol(block, TH_REDALERT);*/
-               
-               uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, xco+10, yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
-               
-               uiDefBut(block, LABEL, B_CONSTRAINT_TEST, con->name, xco+120, yco-1, 135, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+               uiButSetFunc(but, verify_constraint_name_func, con, con->name);
        }
+       else
+               uiDefBut(block, LABEL, B_CONSTRAINT_TEST, con->name, xco+120, yco-1, 135, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
 
        // XXX uiBlockSetCol(block, TH_AUTO);   
 
@@ -968,25 +895,20 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
                        uiBlockBeginAlign(block);
                                uiBlockSetEmboss(block, UI_EMBOSS);
                                
-                               if (show_upbut) {
-                                       but = uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_UP, xco+width-50, yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint up in constraint stack");
-                                       uiButSetFunc(but, constraint_moveUp, ob, con);
-                               }
+                               if (show_upbut)
+                                       uiDefIconButO(block, BUT, "CONSTRAINT_OT_move_up", WM_OP_INVOKE_DEFAULT, VICON_MOVE_UP, xco+width-50, yco, 16, 18, "Move constraint up in constraint stack");
                                
-                               if (show_downbut) {
-                                       but = uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_DOWN, xco+width-50+18, yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint down in constraint stack");
-                                       uiButSetFunc(but, constraint_moveDown, ob, con);
-                               }
+                               if (show_downbut)
+                                       uiDefIconButO(block, BUT, "CONSTRAINT_OT_move_down", WM_OP_INVOKE_DEFAULT, VICON_MOVE_DOWN, xco+width-50+18, yco, 16, 18, "Move constraint down in constraint stack");
                        uiBlockEndAlign(block);
                }
-               
-               
+       
                /* Close 'button' - emboss calls here disable drawing of 'button' behind X */
                uiBlockSetEmboss(block, UI_EMBOSSN);
-               
-               but = uiDefIconBut(block, BUT, B_CONSTRAINT_CHANGETARGET, ICON_X, xco+262, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete constraint");
-               uiButSetFunc(but, del_constraint_func, ob, con);
-               
+                       uiBlockBeginAlign(block);
+                       uiDefIconButBitS(block, ICONTOGN, CONSTRAINT_OFF, B_CONSTRAINT_TEST, ICON_CHECKBOX_DEHLT, xco+243, yco, 19, 19, &con->flag, 0.0, 0.0, 0.0, 0.0, "enable/disable constraint");
+                       uiDefIconButO(block, BUT, "CONSTRAINT_OT_delete", WM_OP_INVOKE_DEFAULT, ICON_X, xco+262, yco, 19, 19, "Delete constraint");
+                       uiBlockEndAlign(block);
                uiBlockSetEmboss(block, UI_EMBOSS);
        }
        
@@ -1053,11 +975,11 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
                                                        /* subtarget */
                                                        if (is_armature_target(ct->tar)) {
                                                                but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", xco+120, yco-(66+yoffset),150,18, &ct->subtarget, 0, 24, 0, 0, "Subtarget Bone");
-                                                               uiButSetCompleteFunc(but, autocomplete_bone, (void *)ct->tar);
+                                                               //uiButSetCompleteFunc(but, autocomplete_bone, (void *)ct->tar);
                                                        }
                                                        else if (is_geom_target(ct->tar)) {
                                                                but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", xco+120, yco-(66+yoffset),150,18, &ct->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
-                                                               uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ct->tar);
+                                                               //uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ct->tar);
                                                        }
                                                        else {
                                                                strcpy(ct->subtarget, "");
@@ -1083,95 +1005,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
                                draw_constraint_spaceselect(block, con, xco, yco-(73+theight), is_armature_owner(ob), -1);
                        }
                        break;
-#endif /* DISABLE_PYTHON */
-               /*case CONSTRAINT_TYPE_CHILDOF:
-                       {
-                               // Inverse options 
-                               uiBlockBeginAlign(block);
-                                       but=uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Set Offset", xco, yco-151, (width/2),18, NULL, 0, 24, 0, 0, "Calculate current Parent-Inverse Matrix (i.e. restore offset from parent)");
-                                       // XXX uiButSetFunc(but, childof_const_setinv, con, NULL);
-                                       
-                                       but=uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Clear Offset", xco+((width/2)+10), yco-151, (width/2),18, NULL, 0, 24, 0, 0, "Clear Parent-Inverse Matrix (i.e. clear offset from parent)");
-                                       // XXX uiButSetFunc(but, childof_const_clearinv, con, NULL);
-                               uiBlockEndAlign(block);
-                       }
-                       break; 
-               */
-               
-               /*case CONSTRAINT_TYPE_RIGIDBODYJOINT:
-                       {
-                               if (data->type==CONSTRAINT_RB_GENERIC6DOF) {
-                                       // Draw Pairs of LimitToggle+LimitValue 
-                                       uiBlockBeginAlign(block); 
-                                               uiDefButBitS(block, TOG, 1, B_CONSTRAINT_TEST, "LinMinX", xco, yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum x limit"); 
-                                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", xco+togButWidth, yco-offsetY, (textButWidth-5), 18, &(data->minLimit[0]), -extremeLin, extremeLin, 0.1,0.5,"min x limit"); 
-                                       uiBlockEndAlign(block);
-                                       
-                                       uiBlockBeginAlign(block); 
-                                               uiDefButBitS(block, TOG, 1, B_CONSTRAINT_TEST, "LinMaxX", xco+(width-(textButWidth-5)-togButWidth), yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum x limit"); 
-                                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", xco+(width-textButWidth-5), yco-offsetY, (textButWidth), 18, &(data->maxLimit[0]), -extremeLin, extremeLin, 0.1,0.5,"max x limit"); 
-                                       uiBlockEndAlign(block);
-                                       
-                                       offsetY += 20;
-                                       uiBlockBeginAlign(block); 
-                                               uiDefButBitS(block, TOG, 2, B_CONSTRAINT_TEST, "LinMinY", xco, yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum y limit"); 
-                                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", xco+togButWidth, yco-offsetY, (textButWidth-5), 18, &(data->minLimit[1]), -extremeLin, extremeLin, 0.1,0.5,"min y limit"); 
-                                       uiBlockEndAlign(block);
-                                       
-                                       uiBlockBeginAlign(block); 
-                                               uiDefButBitS(block, TOG, 2, B_CONSTRAINT_TEST, "LinMaxY", xco+(width-(textButWidth-5)-togButWidth), yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum y limit"); 
-                                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", xco+(width-textButWidth-5), yco-offsetY, (textButWidth), 18, &(data->maxLimit[1]), -extremeLin, extremeLin, 0.1,0.5,"max y limit"); 
-                                       uiBlockEndAlign(block);
-                                       
-                                       offsetY += 20;
-                                       uiBlockBeginAlign(block); 
-                                               uiDefButBitS(block, TOG, 4, B_CONSTRAINT_TEST, "LinMinZ", xco, yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum z limit"); 
-                                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", xco+togButWidth, yco-offsetY, (textButWidth-5), 18, &(data->minLimit[2]), -extremeLin, extremeLin, 0.1,0.5,"min z limit"); 
-                                       uiBlockEndAlign(block);
-                                       
-                                       uiBlockBeginAlign(block); 
-                                               uiDefButBitS(block, TOG, 4, B_CONSTRAINT_TEST, "LinMaxZ", xco+(width-(textButWidth-5)-togButWidth), yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum z limit"); 
-                                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", xco+(width-textButWidth-5), yco-offsetY, (textButWidth), 18, &(data->maxLimit[2]), -extremeLin, extremeLin, 0.1,0.5,"max z limit"); 
-                                       uiBlockEndAlign(block);
-                                       offsetY += 20;
-                               }
-                               if ((data->type==CONSTRAINT_RB_GENERIC6DOF) || (data->type==CONSTRAINT_RB_CONETWIST)) {
-                                       // Draw Pairs of LimitToggle+LimitValue /
-                                       uiBlockBeginAlign(block); 
-                                               uiDefButBitS(block, TOG, 8, B_CONSTRAINT_TEST, "AngMinX", xco, yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum x limit"); 
-                                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", xco+togButWidth, yco-offsetY, (textButWidth-5), 18, &(data->minLimit[3]), -extremeAngX, extremeAngX, 0.1,0.5,"min x limit"); 
-                                       uiBlockEndAlign(block);
-                                       uiBlockBeginAlign(block); 
-                                               uiDefButBitS(block, TOG, 8, B_CONSTRAINT_TEST, "AngMaxX", xco+(width-(textButWidth-5)-togButWidth), yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum x limit"); 
-                                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", xco+(width-textButWidth-5), yco-offsetY, (textButWidth), 18, &(data->maxLimit[3]), -extremeAngX, extremeAngX, 0.1,0.5,"max x limit"); 
-                                       uiBlockEndAlign(block);
-                                       
-                                       offsetY += 20;
-                                       uiBlockBeginAlign(block); 
-                                               uiDefButBitS(block, TOG, 16, B_CONSTRAINT_TEST, "AngMinY", xco, yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum y limit"); 
-                                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", xco+togButWidth, yco-offsetY, (textButWidth-5), 18, &(data->minLimit[4]), -extremeAngY, extremeAngY, 0.1,0.5,"min y limit"); 
-                                       uiBlockEndAlign(block);
-                                       
-                                       uiBlockBeginAlign(block); 
-                                               uiDefButBitS(block, TOG, 16, B_CONSTRAINT_TEST, "AngMaxY", xco+(width-(textButWidth-5)-togButWidth), yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum y limit"); 
-                                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", xco+(width-textButWidth-5), yco-offsetY, (textButWidth), 18, &(data->maxLimit[4]), -extremeAngY, extremeAngY, 0.1,0.5,"max y limit"); 
-                                       uiBlockEndAlign(block);
-                                       
-                                       offsetY += 20;
-                                       uiBlockBeginAlign(block); 
-                                               uiDefButBitS(block, TOG, 32, B_CONSTRAINT_TEST, "AngMinZ", xco, yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum z limit"); 
-                                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", xco+togButWidth, yco-offsetY, (textButWidth-5), 18, &(data->minLimit[5]), -extremeAngZ, extremeAngZ, 0.1,0.5,"min z limit"); 
-                                       uiBlockEndAlign(block);
-                                       
-                                       uiBlockBeginAlign(block); 
-                                               uiDefButBitS(block, TOG, 32, B_CONSTRAINT_TEST, "AngMaxZ", xco+(width-(textButWidth-5)-togButWidth), yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum z limit"); 
-                                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", xco+(width-textButWidth-5), yco-offsetY, (textButWidth), 18, &(data->maxLimit[5]), -extremeAngZ, extremeAngZ, 0.1,0.5,"max z limit"); 
-                                       uiBlockEndAlign(block);
-                               }
-                               
-                       }
-                       break;
-                       */
+#endif 
 
                case CONSTRAINT_TYPE_NULL:
                        {
@@ -1332,11 +1166,12 @@ uiLayout *uiTemplateGroup(uiLayout *layout, Object *ob, Group *group)
 
 /************************* Preview Template ***************************/
 
+#include "DNA_lamp_types.h"
 #include "DNA_material_types.h"
+#include "DNA_world_types.h"
 
 #define B_MATPRV 1
 
-
 static void do_preview_buttons(bContext *C, void *arg, int event)
 {
        switch(event) {
@@ -1346,32 +1181,55 @@ static void do_preview_buttons(bContext *C, void *arg, int event)
        }
 }
 
-void uiTemplatePreview(uiLayout *layout, ID *id)
+void uiTemplatePreview(uiLayout *layout, ID *id, ID *parent, MTex *slot)
 {
        uiLayout *row, *col;
        uiBlock *block;
-       Material *ma;
+       Material *ma= NULL;
+       ID *pid, *pparent;
+       short *pr_texture= NULL;
 
        if(id && !ELEM4(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA)) {
                printf("uiTemplatePreview: expected ID of type material, texture, lamp or world.\n");
                return;
        }
 
-       block= uiLayoutGetBlock(layout);
+       /* decide what to render */
+       pid= id;
+       pparent= NULL;
+
+       if(id && (GS(id->name) == ID_TE)) {
+               if(parent && (GS(parent->name) == ID_MA))
+                       pr_texture= &((Material*)parent)->pr_texture;
+               else if(parent && (GS(parent->name) == ID_WO))
+                       pr_texture= &((World*)parent)->pr_texture;
+               else if(parent && (GS(parent->name) == ID_LA))
+                       pr_texture= &((Lamp*)parent)->pr_texture;
+
+               if(pr_texture) {
+                       if(*pr_texture == TEX_PR_OTHER)
+                               pid= parent;
+                       else if(*pr_texture == TEX_PR_BOTH)
+                               pparent= parent;
+               }
+       }
 
+       /* layout */
+       block= uiLayoutGetBlock(layout);
        row= uiLayoutRow(layout, 0);
-
        col= uiLayoutColumn(row, 0);
        uiLayoutSetKeepAspect(col, 1);
        
-       uiDefBut(block, BUT_EXTRA, 0, "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6, id, 0.0, 0.0, 0, 0, "");
-       uiBlockSetDrawExtraFunc(block, ED_preview_draw);
-       
+       /* add preview */
+       uiDefBut(block, BUT_EXTRA, 0, "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6, pid, 0.0, 0.0, 0, 0, "");
+       uiBlockSetDrawExtraFunc(block, ED_preview_draw, pparent, slot);
        uiBlockSetHandleFunc(block, do_preview_buttons, NULL);
        
-       if(id) {
-               if(GS(id->name) == ID_MA) {
-                       ma= (Material*)id;
+       /* add buttons */
+       if(pid) {
+               if(GS(pid->name) == ID_MA || (pparent && GS(pparent->name) == ID_MA)) {
+                       if(GS(pid->name) == ID_MA) ma= (Material*)pid;
+                       else ma= (Material*)pparent;
 
                        uiLayoutColumn(row, 1);
 
@@ -1380,62 +1238,551 @@ void uiTemplatePreview(uiLayout *layout, ID *id)
                        uiDefIconButC(block, ROW, B_MATPRV, ICON_MATCUBE,   0, 0,UI_UNIT_X*1.5,UI_UNIT_Y, &(ma->pr_type), 10, MA_CUBE, 0, 0, "Preview type: Cube");
                        uiDefIconButC(block, ROW, B_MATPRV, ICON_MONKEY,    0, 0,UI_UNIT_X*1.5,UI_UNIT_Y, &(ma->pr_type), 10, MA_MONKEY, 0, 0, "Preview type: Monkey");
                        uiDefIconButC(block, ROW, B_MATPRV, ICON_HAIR,      0, 0,UI_UNIT_X*1.5,UI_UNIT_Y, &(ma->pr_type), 10, MA_HAIR, 0, 0, "Preview type: Hair strands");
-                       uiDefIconButC(block, ROW, B_MATPRV, ICON_MATSPHERE, 0, 0,UI_UNIT_X*1.5,UI_UNIT_Y, &(ma->pr_type), 10, MA_SPHERE_A, 0, 0, "Preview type: Large sphere with sky");
+                       uiDefIconButC(block, ROW, B_MATPRV, ICON_MAT_SPHERE_SKY, 0, 0,UI_UNIT_X*1.5,UI_UNIT_Y, &(ma->pr_type), 10, MA_SPHERE_A, 0, 0, "Preview type: Large sphere with sky");
+               }
+
+               if(pr_texture) {
+                       uiLayoutRow(layout, 1);
+
+                       uiDefButS(block, ROW, B_MATPRV, "Texture",  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_TEXTURE, 0, 0, "");
+                       if(GS(parent->name) == ID_MA)
+                               uiDefButS(block, ROW, B_MATPRV, "Material",  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
+                       else if(GS(parent->name) == ID_LA)
+                               uiDefButS(block, ROW, B_MATPRV, "Lamp",  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
+                       else if(GS(parent->name) == ID_WO)
+                               uiDefButS(block, ROW, B_MATPRV, "World",  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
+                       uiDefButS(block, ROW, B_MATPRV, "Both",  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_BOTH, 0, 0, "");
                }
        }
 }
 
 /********************** ColorRamp Template **************************/
 
-void uiTemplateColorRamp(uiLayout *layout, ColorBand *coba, int expand)
+#include "BKE_texture.h"
+
+typedef struct RNAUpdateCb {
+       PointerRNA ptr;
+       PropertyRNA *prop;
+} RNAUpdateCb;
+
+static void rna_update_cb(bContext *C, void *arg_cb, void *arg_unused)
 {
-       uiBlock *block;
-       rctf rect;
+       RNAUpdateCb *cb= (RNAUpdateCb*)arg_cb;
 
-       if(coba) {
-               rect.xmin= 0; rect.xmax= 200;
-               rect.ymin= 0; rect.ymax= 190;
-               
-               block= uiLayoutFreeBlock(layout);
-               colorband_buttons(block, coba, &rect, !expand);
-       }
+       /* we call update here on the pointer property, this way the
+          owner of the curve mapping can still define it's own update
+          and notifier, even if the CurveMapping struct is shared. */
+       RNA_property_update(C, &cb->ptr, cb->prop);
 }
 
-/********************* CurveMapping Template ************************/
+#define B_BANDCOL 1
 
-#include "DNA_color_types.h"
+static int vergcband(const void *a1, const void *a2)
+{
+       const CBData *x1=a1, *x2=a2;
+
+       if( x1->pos > x2->pos ) return 1;
+       else if( x1->pos < x2->pos) return -1;
+       return 0;
+}
 
-void uiTemplateCurveMapping(uiLayout *layout, CurveMapping *cumap, int type)
+static void colorband_pos_cb(bContext *C, void *cb_v, void *coba_v)
 {
-       uiBlock *block;
-       rctf rect;
+       ColorBand *coba= coba_v;
+       int a;
 
-       if(cumap) {
-               rect.xmin= 0; rect.xmax= 200;
-               rect.ymin= 0; rect.ymax= 190;
-               
-               block= uiLayoutFreeBlock(layout);
-               curvemap_buttons(block, cumap, type, 0, 0, &rect);
+       if(coba->tot<2) return;
+
+       for(a=0; a<coba->tot; a++) coba->data[a].cur= a;
+       qsort(coba->data, coba->tot, sizeof(CBData), vergcband);
+       for(a=0; a<coba->tot; a++) {
+               if(coba->data[a].cur==coba->cur) {
+                       coba->cur= a;
+                       break;
+               }
        }
+
+       rna_update_cb(C, cb_v, NULL);
 }
 
-/********************* Layer Buttons Template ************************/
+static void colorband_add_cb(bContext *C, void *cb_v, void *coba_v)
+{
+       ColorBand *coba= coba_v;
 
-// TODO:
-//     - option for showing extra info like whether layer has contents?
-//     - for now, grouping of layers is determined by dividing up the length of 
-//       the array of layer bitflags
+       if(coba->tot < MAXCOLORBAND-1) coba->tot++;
+       coba->cur= coba->tot-1;
 
-void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, char *propname)
-{
-       uiLayout *uRow, *uSplit, *uCol;
+       colorband_pos_cb(C, cb_v, coba_v);
+
+       ED_undo_push(C, "Add colorband");
+}
+
+static void colorband_del_cb(bContext *C, void *cb_v, void *coba_v)
+{
+       ColorBand *coba= coba_v;
+       int a;
+
+       if(coba->tot<2) return;
+
+       for(a=coba->cur; a<coba->tot; a++) {
+               coba->data[a]= coba->data[a+1];
+       }
+       if(coba->cur) coba->cur--;
+       coba->tot--;
+
+       ED_undo_push(C, "Delete colorband");
+
+       rna_update_cb(C, cb_v, NULL);
+}
+
+
+/* offset aligns from bottom, standard width 300, height 115 */
+static void colorband_buttons_large(uiBlock *block, ColorBand *coba, int xoffs, int yoffs, RNAUpdateCb *cb)
+{
+       
+       uiBut *bt;
+
+       if(coba==NULL) return;
+
+       bt= uiDefBut(block, BUT, 0,     "Add",                  0+xoffs,100+yoffs,50,20, 0, 0, 0, 0, 0, "Add a new color stop to the colorband");
+       uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
+
+       bt= uiDefBut(block, BUT, 0,     "Delete",               60+xoffs,100+yoffs,50,20, 0, 0, 0, 0, 0, "Delete the active position");
+       uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
+
+       uiDefButS(block, NUM, 0,                "",                             120+xoffs,100+yoffs,80, 20, &coba->cur, 0.0, (float)(MAX2(0, coba->tot-1)), 0, 0, "Choose active color stop");
+
+       bt= uiDefButS(block, MENU, 0,           "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4",
+                       210+xoffs, 100+yoffs, 90, 20,           &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops");
+       uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+       uiBlockEndAlign(block);
+
+       bt= uiDefBut(block, BUT_COLORBAND, 0, "",       xoffs,65+yoffs,300,30, coba, 0, 0, 0, 0, "");
+       uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+
+       if(coba->tot) {
+               CBData *cbd= coba->data + coba->cur;
+
+               bt= uiDefButF(block, NUM, 0, "Pos:",                    0+xoffs,40+yoffs,100, 20, &cbd->pos, 0.0, 1.0, 10, 0, "The position of the active color stop");
+               uiButSetNFunc(bt, colorband_pos_cb, MEM_dupallocN(cb), coba);
+               bt= uiDefButF(block, COL, 0,            "",                             110+xoffs,40+yoffs,80,20, &(cbd->r), 0, 0, 0, B_BANDCOL, "The color value for the active color stop");
+               uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+               bt= uiDefButF(block, NUMSLI, 0, "A ",                   200+xoffs,40+yoffs,100,20, &cbd->a, 0.0, 1.0, 10, 0, "The alpha value of the active color stop");
+               uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+       }
+
+}
+
+static void colorband_buttons_small(uiBlock *block, ColorBand *coba, rctf *butr, RNAUpdateCb *cb)
+{
+       uiBut *bt;
+       float unit= (butr->xmax-butr->xmin)/14.0f;
+       float xs= butr->xmin;
+
+
+       bt= uiDefBut(block, BUT, 0,     "Add",                  xs,butr->ymin+20.0f,2.0f*unit,20,       NULL, 0, 0, 0, 0, "Add a new color stop to the colorband");
+       uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
+       bt= uiDefBut(block, BUT, 0,     "Delete",               xs+2.0f*unit,butr->ymin+20.0f,2.0f*unit,20,     NULL, 0, 0, 0, 0, "Delete the active position");
+       uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
+
+       if(coba->tot) {
+               CBData *cbd= coba->data + coba->cur;
+               bt= uiDefButF(block, COL, 0,            "",                     xs+4.0f*unit,butr->ymin+20.0f,2.0f*unit,20,                             &(cbd->r), 0, 0, 0, B_BANDCOL, "The color value for the active color stop");
+               uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+               bt= uiDefButF(block, NUMSLI, 0,         "A:",           xs+6.0f*unit,butr->ymin+20.0f,4.0f*unit,20,     &(cbd->a), 0.0f, 1.0f, 10, 2, "The alpha value of the active color stop");
+               uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+       }
+
+       bt= uiDefButS(block, MENU, 0,           "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4",
+                       xs+10.0f*unit, butr->ymin+20.0f, unit*4, 20,            &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops");
+       uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+
+       bt= uiDefBut(block, BUT_COLORBAND, 0, "",               xs,butr->ymin,butr->xmax-butr->xmin,20.0f, coba, 0, 0, 0, 0, "");
+       uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+
+       uiBlockEndAlign(block);
+}
+
+static void colorband_buttons_layout(uiBlock *block, ColorBand *coba, rctf *butr, int small, RNAUpdateCb *cb)
+{
+       if(small)
+               colorband_buttons_small(block, coba, butr, cb);
+       else
+               colorband_buttons_large(block, coba, 0, 0, cb);
+}
+
+void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, char *propname, int expand)
+{
+       PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
+       PointerRNA cptr;
+       RNAUpdateCb *cb;
+       uiBlock *block;
+       rctf rect;
+
+       if(!prop || RNA_property_type(prop) != PROP_POINTER)
+               return;
+
+       cptr= RNA_property_pointer_get(ptr, prop);
+       if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_ColorRamp))
+               return;
+
+       cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
+       cb->ptr= *ptr;
+       cb->prop= prop;
+
+       rect.xmin= 0; rect.xmax= 200;
+       rect.ymin= 0; rect.ymax= 190;
+
+       block= uiLayoutFreeBlock(layout);
+       colorband_buttons_layout(block, cptr.data, &rect, !expand, cb);
+
+       MEM_freeN(cb);
+}
+
+/********************* CurveMapping Template ************************/
+
+#include "DNA_color_types.h"
+#include "BKE_colortools.h"
+
+static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *unused)
+{
+       CurveMapping *cumap = cumap_v;
+       float d;
+
+       /* we allow 20 times zoom */
+       if( (cumap->curr.xmax - cumap->curr.xmin) > 0.04f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
+               d= 0.1154f*(cumap->curr.xmax - cumap->curr.xmin);
+               cumap->curr.xmin+= d;
+               cumap->curr.xmax-= d;
+               d= 0.1154f*(cumap->curr.ymax - cumap->curr.ymin);
+               cumap->curr.ymin+= d;
+               cumap->curr.ymax-= d;
+       }
+
+       ED_region_tag_redraw(CTX_wm_region(C));
+}
+
+static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *unused)
+{
+       CurveMapping *cumap = cumap_v;
+       float d, d1;
+
+       /* we allow 20 times zoom, but dont view outside clip */
+       if( (cumap->curr.xmax - cumap->curr.xmin) < 20.0f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
+               d= d1= 0.15f*(cumap->curr.xmax - cumap->curr.xmin);
+
+               if(cumap->flag & CUMA_DO_CLIP) 
+                       if(cumap->curr.xmin-d < cumap->clipr.xmin)
+                               d1= cumap->curr.xmin - cumap->clipr.xmin;
+               cumap->curr.xmin-= d1;
+
+               d1= d;
+               if(cumap->flag & CUMA_DO_CLIP) 
+                       if(cumap->curr.xmax+d > cumap->clipr.xmax)
+                               d1= -cumap->curr.xmax + cumap->clipr.xmax;
+               cumap->curr.xmax+= d1;
+
+               d= d1= 0.15f*(cumap->curr.ymax - cumap->curr.ymin);
+
+               if(cumap->flag & CUMA_DO_CLIP) 
+                       if(cumap->curr.ymin-d < cumap->clipr.ymin)
+                               d1= cumap->curr.ymin - cumap->clipr.ymin;
+               cumap->curr.ymin-= d1;
+
+               d1= d;
+               if(cumap->flag & CUMA_DO_CLIP) 
+                       if(cumap->curr.ymax+d > cumap->clipr.ymax)
+                               d1= -cumap->curr.ymax + cumap->clipr.ymax;
+               cumap->curr.ymax+= d1;
+       }
+
+       ED_region_tag_redraw(CTX_wm_region(C));
+}
+
+static void curvemap_buttons_setclip(bContext *C, void *cumap_v, void *unused)
+{
+       CurveMapping *cumap = cumap_v;
+
+       curvemapping_changed(cumap, 0);
+}      
+
+static void curvemap_buttons_delete(bContext *C, void *cb_v, void *cumap_v)
+{
+       CurveMapping *cumap = cumap_v;
+
+       curvemap_remove(cumap->cm+cumap->cur, SELECT);
+       curvemapping_changed(cumap, 0);
+
+       rna_update_cb(C, cb_v, NULL);
+}
+
+/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
+static uiBlock *curvemap_clipping_func(bContext *C, struct ARegion *ar, void *cumap_v)
+{
+       CurveMapping *cumap = cumap_v;
+       uiBlock *block;
+       uiBut *bt;
+
+       block= uiBeginBlock(C, ar, "curvemap_clipping_func", UI_EMBOSS);
+
+       /* use this for a fake extra empy space around the buttons */
+       uiDefBut(block, LABEL, 0, "",                   -4, 16, 128, 106, NULL, 0, 0, 0, 0, "");
+
+       bt= uiDefButBitI(block, TOG, CUMA_DO_CLIP, 1, "Use Clipping",    
+                       0,100,120,18, &cumap->flag, 0.0, 0.0, 10, 0, "");
+       uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL);
+
+       uiBlockBeginAlign(block);
+       uiDefButF(block, NUM, 0, "Min X ",       0,74,120,18, &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 0, "");
+       uiDefButF(block, NUM, 0, "Min Y ",       0,56,120,18, &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 0, "");
+       uiDefButF(block, NUM, 0, "Max X ",       0,38,120,18, &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 0, "");
+       uiDefButF(block, NUM, 0, "Max Y ",       0,20,120,18, &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 0, "");
+
+       uiBlockSetDirection(block, UI_RIGHT);
+
+       uiEndBlock(C, block);
+       return block;
+}
+
+static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event)
+{
+       CurveMapping *cumap = cumap_v;
+       CurveMap *cuma= cumap->cm+cumap->cur;
+
+       switch(event) {
+               case 0:
+                       curvemap_reset(cuma, &cumap->clipr);
+                       curvemapping_changed(cumap, 0);
+                       break;
+               case 1:
+                       cumap->curr= cumap->clipr;
+                       break;
+               case 2: /* set vector */
+                       curvemap_sethandle(cuma, 1);
+                       curvemapping_changed(cumap, 0);
+                       break;
+               case 3: /* set auto */
+                       curvemap_sethandle(cuma, 0);
+                       curvemapping_changed(cumap, 0);
+                       break;
+               case 4: /* extend horiz */
+                       cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
+                       curvemapping_changed(cumap, 0);
+                       break;
+               case 5: /* extend extrapolate */
+                       cuma->flag |= CUMA_EXTEND_EXTRAPOLATE;
+                       curvemapping_changed(cumap, 0);
+                       break;
+       }
+       ED_region_tag_redraw(CTX_wm_region(C));
+}
+
+static uiBlock *curvemap_tools_func(bContext *C, struct ARegion *ar, void *cumap_v)
+{
+       uiBlock *block;
+       short yco= 0, menuwidth=120;
+
+       block= uiBeginBlock(C, ar, "curvemap_tools_func", UI_EMBOSS);
+       uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
+
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset View",                             0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector Handle",                  0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Handle",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Horizontal",              0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Extrapolated",    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Curve",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
+
+       uiBlockSetDirection(block, UI_RIGHT);
+       uiTextBoundsBlock(block, 50);
+
+       uiEndBlock(C, block);
+       return block;
+}
+
+static void curvemap_buttons_redraw(bContext *C, void *arg1, void *arg2)
+{
+       ED_region_tag_redraw(CTX_wm_region(C));
+}
+
+static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v)
+{
+       CurveMapping *cumap = cumap_v;
+       int a;
+       
+       for(a=0; a<CM_TOT; a++)
+               curvemap_reset(cumap->cm+a, &cumap->clipr);
+       
+       cumap->black[0]=cumap->black[1]=cumap->black[2]= 0.0f;
+       cumap->white[0]=cumap->white[1]=cumap->white[2]= 1.0f;
+       curvemapping_set_black_white(cumap, NULL, NULL);
+       
+       curvemapping_changed(cumap, 0);
+
+       rna_update_cb(C, cb_v, NULL);
+}
+
+/* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */
+static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, RNAUpdateCb *cb)
+{
+       CurveMapping *cumap= ptr->data;
+       uiLayout *row, *sub, *split;
+       uiBlock *block;
+       uiBut *bt;
+       float dx= UI_UNIT_X;
+       int icon, size;
+
+       block= uiLayoutGetBlock(layout);
+
+       /* curve chooser */
+       row= uiLayoutRow(layout, 0);
+
+       if(labeltype=='v') {
+               /* vector */
+               sub= uiLayoutRow(row, 1);
+               uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
+
+               if(cumap->cm[0].curve) {
+                       bt= uiDefButI(block, ROW, 0, "X", 0, 0, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
+                       uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
+               }
+               if(cumap->cm[1].curve) {
+                       bt= uiDefButI(block, ROW, 0, "Y", 0, 0, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
+                       uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
+               }
+               if(cumap->cm[2].curve) {
+                       bt= uiDefButI(block, ROW, 0, "Z", 0, 0, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
+                       uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
+               }
+       }
+       else if(labeltype=='c') {
+               /* color */
+               sub= uiLayoutRow(row, 1);
+               uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
+
+               if(cumap->cm[3].curve) {
+                       bt= uiDefButI(block, ROW, 0, "C", 0, 0, dx, 16, &cumap->cur, 0.0, 3.0, 0.0, 0.0, "");
+                       uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
+               }
+               if(cumap->cm[0].curve) {
+                       bt= uiDefButI(block, ROW, 0, "R", 0, 0, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
+                       uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
+               }
+               if(cumap->cm[1].curve) {
+                       bt= uiDefButI(block, ROW, 0, "G", 0, 0, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
+                       uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
+               }
+               if(cumap->cm[2].curve) {
+                       bt= uiDefButI(block, ROW, 0, "B", 0, 0, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
+                       uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
+               }
+       }
+       else
+               uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
+
+       /* operation buttons */
+       sub= uiLayoutRow(row, 1);
+
+       uiBlockSetEmboss(block, UI_EMBOSSN);
+
+       bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMIN, 0, 0, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom in");
+       uiButSetFunc(bt, curvemap_buttons_zoom_in, cumap, NULL);
+
+       bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMOUT, 0, 0, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom out");
+       uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL);
+
+       bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, 18, "Tools");
+       uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+
+       if(cumap->flag & CUMA_DO_CLIP) icon= ICON_CLIPUV_HLT; else icon= ICON_CLIPUV_DEHLT;
+       bt= uiDefIconBlockBut(block, curvemap_clipping_func, cumap, 0, icon, 0, 0, dx, 18, "Clipping Options");
+       uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+
+       bt= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, dx, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Delete points");
+       uiButSetNFunc(bt, curvemap_buttons_delete, MEM_dupallocN(cb), cumap);
+
+       uiBlockSetEmboss(block, UI_EMBOSS);
+
+       uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL);
+
+       /* curve itself */
+       size= uiLayoutGetWidth(layout);
+       row= uiLayoutRow(layout, 0);
+       uiDefBut(block, BUT_CURVE, 0, "", 0, 0, size, MIN2(size, 200), cumap, 0.0f, 1.0f, 0, 0, "");
+
+       /* black/white levels */
+       if(levels) {
+               split= uiLayoutSplit(layout, 0);
+               uiItemR(uiLayoutColumn(split, 0), NULL, 0, ptr, "black_level", UI_ITEM_R_EXPAND);
+               uiItemR(uiLayoutColumn(split, 0), NULL, 0, ptr, "white_level", UI_ITEM_R_EXPAND);
+
+               uiLayoutRow(layout, 0);
+               bt=uiDefBut(block, BUT, 0, "Reset",     0, 0, UI_UNIT_X*10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Reset Black/White point and curves");
+               uiButSetNFunc(bt, curvemap_buttons_reset, MEM_dupallocN(cb), cumap);
+       }
+
+       uiBlockSetNFunc(block, NULL, NULL, NULL);
+}
+
+void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, char *propname, int type, int levels)
+{
+       RNAUpdateCb *cb;
+       PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
+       PointerRNA cptr;
+
+       if(!prop || RNA_property_type(prop) != PROP_POINTER)
+               return;
+
+       cptr= RNA_property_pointer_get(ptr, prop);
+       if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_CurveMapping))
+               return;
+
+       cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
+       cb->ptr= *ptr;
+       cb->prop= prop;
+
+       curvemap_buttons_layout(layout, &cptr, type, levels, cb);
+
+       MEM_freeN(cb);
+}
+
+/********************* TriColor (ThemeWireColorSet) Template ************************/
+
+void uiTemplateTriColorSet(uiLayout *layout, PointerRNA *ptr, char *propname)
+{
+       PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
+       uiLayout *row;
+       PointerRNA csPtr;
+
+       if (!prop) {
+               printf("uiTemplateTriColorSet: property not found: %s\n", propname);
+               return;
+       }
+       
+       /* we lay out the data in a row as 3 color swatches */
+       row= uiLayoutRow(layout, 1);
+       
+       /* nselected, selected, active color swatches */
+       csPtr= RNA_property_pointer_get(ptr, prop);
+       
+       uiItemR(row, "", 0, &csPtr, "normal", 0);
+       uiItemR(row, "", 0, &csPtr, "selected", 0);
+       uiItemR(row, "", 0, &csPtr, "active", 0);
+}
+
+/********************* Layer Buttons Template ************************/
+
+// TODO:
+//     - option for showing extra info like whether layer has contents?
+//     - for now, grouping of layers is determined by dividing up the length of 
+//       the array of layer bitflags
+
+void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, char *propname)
+{
+       uiLayout *uRow, *uSplit, *uCol;
        PropertyRNA *prop;
        int groups, cols, layers;
        int group, col, layer, row;
        
-       if (!ptr->data)
-               return;
-       
        prop= RNA_struct_find_property(ptr, propname);
        if (!prop) {
                printf("uiTemplateLayer: layers property not found: %s\n", propname);
@@ -1448,12 +1795,15 @@ void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, char *propname)
         *        the 'remainder' is added to this, as it will be ok to have first row slightly wider if need be
         *      - for now, only split into groups if if group will have at least 5 items
         */
-       layers= RNA_property_array_length(prop);
+       layers= RNA_property_array_length(ptr, prop);
        cols= (layers / 2) + (layers % 2);
        groups= ((cols / 2) < 5) ? (1) : (cols / 2);
        
        /* layers are laid out going across rows, with the columns being divided into groups */
-       uSplit= uiLayoutSplit(layout, (1.0f/(float)groups));
+       if (groups > 1)
+               uSplit= uiLayoutSplit(layout, (1.0f/(float)groups));
+       else    
+               uSplit= layout;
        
        for (group= 0; group < groups; group++) {
                uCol= uiLayoutColumn(uSplit, 1);
@@ -1465,7 +1815,7 @@ void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, char *propname)
                        /* add layers as toggle buts */
                        for (col= 0; (col < cols) && (layer < layers); col++, layer++) {
                                int icon=0; // XXX - add some way of setting this...
-                               uiItemFullR(uRow, "", icon, ptr, prop, layer, 0, 0, 0, 1);
+                               uiItemFullR(uRow, "", icon, ptr, prop, layer, 0, UI_ITEM_R_TOGGLE);
                        }
                }
        }
@@ -1475,204 +1825,322 @@ void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, char *propname)
 /************************* List Template **************************/
 
 #if 0
-typedef struct ListItem {
-       PointerRNA ptr;
-       PropertyRNA *prop;
-       PropertyRNA *activeprop;
-
-       PointerRNA activeptr;
-       int activei;
-
-       int selected;
-} ListItem;
-
-static void list_item_cb(bContext *C, void *arg_item, void *arg_unused)
+static void list_item_add(ListBase *lb, ListBase *itemlb, uiLayout *layout, PointerRNA *data)
 {
-       ListItem *item= (ListItem*)arg_item;
-       PropertyType activetype;
-       char *activename;
-
-       if(item->selected) {
-               activetype= RNA_property_type(item->activeprop);
-
-               if(activetype == PROP_POINTER)
-                       RNA_property_pointer_set(&item->ptr, item->activeprop, item->activeptr);
-               else if(activetype == PROP_INT)
-                       RNA_property_int_set(&item->ptr, item->activeprop, item->activei);
-               else if(activetype == PROP_STRING) {
-                       activename= RNA_struct_name_get_alloc(&item->activeptr, NULL, 0);
-                       RNA_property_string_set(&item->ptr, item->activeprop, activename);
-                       MEM_freeN(activename);
-               }
-       }
+       CollectionPointerLink *link;
+       uiListItem *item;
+
+       /* add to list to store in box */
+       item= MEM_callocN(sizeof(uiListItem), "uiListItem");
+       item->layout= layout;
+       item->data= *data;
+       BLI_addtail(itemlb, item);
+
+       /* add to list to return from function */
+       link= MEM_callocN(sizeof(CollectionPointerLink), "uiTemplateList return");
+       RNA_pointer_create(NULL, &RNA_UIListItem, item, &link->ptr);
+       BLI_addtail(lb, link);
 }
 #endif
 
-ListBase uiTemplateList(uiLayout *layout, PointerRNA *ptr, char *propname, char *activepropname, int rows, int columns, int compact)
+ListBase uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, PointerRNA *activeptr, char *activepropname, int rows, int listtype)
 {
-       CollectionPointerLink *link;
-       PropertyRNA *prop, *activeprop;
+       //Scene *scene= CTX_data_scene(C);
+       PropertyRNA *prop= NULL, *activeprop;
        PropertyType type, activetype;
-       PointerRNA activeptr;
-       uiLayout *box, *row, *col;
+       StructRNA *ptype;
+       uiLayout *box, *row, *col, *subrow;
        uiBlock *block;
        uiBut *but;
-       ListBase lb;
-       char *name, *activename= NULL, str[32];
-       int i= 1, activei= 0, len, items, found;
-       static int scroll = 1;
+       Panel *pa;
+       ListBase lb, *itemlb;
+       char *name, str[32];
+       int icon=0, i= 0, activei= 0, len= 0, items, found, min, max;
 
        lb.first= lb.last= NULL;
        
        /* validate arguments */
-       if(!ptr->data)
+       block= uiLayoutGetBlock(layout);
+       pa= block->panel;
+
+       if(!pa) {
+               printf("uiTemplateList: only works inside a panel.\n");
                return lb;
-       
-       prop= RNA_struct_find_property(ptr, propname);
-       if(!prop) {
-               printf("uiTemplateList: property not found: %s\n", propname);
+       }
+
+       if(!activeptr->data)
                return lb;
+       
+       if(ptr->data) {
+               prop= RNA_struct_find_property(ptr, propname);
+               if(!prop) {
+                       printf("uiTemplateList: property not found: %s\n", propname);
+                       return lb;
+               }
        }
 
-       activeprop= RNA_struct_find_property(ptr, activepropname);
+       activeprop= RNA_struct_find_property(activeptr, activepropname);
        if(!activeprop) {
                printf("uiTemplateList: property not found: %s\n", activepropname);
                return lb;
        }
 
-       type= RNA_property_type(prop);
-       if(type != PROP_COLLECTION) {
-               printf("uiTemplateList: expected collection property.\n");
-               return lb;
+       if(prop) {
+               type= RNA_property_type(prop);
+               if(type != PROP_COLLECTION) {
+                       printf("uiTemplateList: expected collection property.\n");
+                       return lb;
+               }
        }
 
        activetype= RNA_property_type(activeprop);
-       if(!ELEM3(activetype, PROP_POINTER, PROP_INT, PROP_STRING)) {
-               printf("uiTemplateList: expected pointer, integer or string property.\n");
+       if(activetype != PROP_INT) {
+               printf("uiTemplateList: expected integer property.\n");
                return lb;
        }
 
+       /* get icon */
+       if(ptr->data && prop) {
+               ptype= RNA_property_pointer_type(ptr, prop);
+               icon= RNA_struct_ui_icon(ptype);
+       }
+
        /* get active data */
-       if(activetype == PROP_POINTER)
-               activeptr= RNA_property_pointer_get(ptr, activeprop);
-       else if(activetype == PROP_INT)
-               activei= RNA_property_int_get(ptr, activeprop);
-       else if(activetype == PROP_STRING)
-               activename= RNA_property_string_get_alloc(ptr, activeprop, NULL, 0);
+       activei= RNA_property_int_get(activeptr, activeprop);
 
-       block= uiLayoutGetBlock(layout);
+       if(listtype == 'i') {
+               box= uiLayoutListBox(layout);
+               col= uiLayoutColumn(box, 1);
+               row= uiLayoutRow(col, 0);
+
+               itemlb= uiLayoutBoxGetList(box);
+
+               if(ptr->data && prop) {
+                       /* create list items */
+                       RNA_PROP_BEGIN(ptr, itemptr, prop) {
+                               /* create button */
+                               if(i == 9)
+                                       row= uiLayoutRow(col, 0);
+
+                               if(RNA_struct_is_a(itemptr.type, &RNA_TextureSlot)) {
+#if 0
+                                       MTex *mtex= itemptr.data;
 
-       if(compact) {
+                                       if(mtex && mtex->tex)
+                                               icon= ui_id_icon_get(scene, &mtex->tex->id);
+#endif
+                               }
+
+                               uiDefIconButR(block, LISTROW, 0, icon, 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, "");
+
+                               //list_item_add(&lb, itemlb, uiLayoutRow(row, 1), &itemptr);
+
+                               i++;
+                       }
+                       RNA_PROP_END;
+               }
+       }
+       else if(listtype == 'c') {
                /* compact layout */
                found= 0;
 
                row= uiLayoutRow(layout, 1);
 
-               RNA_PROP_BEGIN(ptr, itemptr, prop) {
-                       if(activetype == PROP_POINTER)
-                               found= (activeptr.data == itemptr.data);
-                       else if(activetype == PROP_INT)
+               if(ptr->data && prop) {
+                       /* create list items */
+                       RNA_PROP_BEGIN(ptr, itemptr, prop) {
                                found= (activei == i);
-                       else if(activetype == PROP_STRING)
-                               found= (strcmp(activename, name) == 0);
-
-                       if(found) {
-                               name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
-                               if(name) {
-                                       uiItemL(row, name, RNA_struct_ui_icon(itemptr.type));
-                                       MEM_freeN(name);
+
+                               if(found) {
+                                       /* create button */
+                                       name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
+                                       uiItemL(row, (name)? name: "", icon);
+
+                                       if(name)
+                                               MEM_freeN(name);
+
+                                       /* add to list to return */
+                                       //list_item_add(&lb, itemlb, uiLayoutRow(row, 1), &itemptr);
                                }
 
-                               link= MEM_callocN(sizeof(CollectionPointerLink), "uiTemplateList return");
-                               link->ptr= itemptr;
-                               BLI_addtail(&lb, link);
+                               i++;
                        }
-
-                       i++;
+                       RNA_PROP_END;
                }
-               RNA_PROP_END;
 
-               if(i == 1)
+               /* if not found, add in dummy button */
+               if(i == 0)
                        uiItemL(row, "", 0);
 
-               sprintf(str, "%d :", i-1);
-               but= uiDefIconTextButR(block, NUM, 0, 0, str, 0,0,UI_UNIT_X*5,UI_UNIT_Y, ptr, activepropname, 0, 0, 0, 0, 0, "");
-               if(i == 1)
+               /* next/prev button */
+               sprintf(str, "%d :", i);
+               but= uiDefIconTextButR(block, NUM, 0, 0, str, 0,0,UI_UNIT_X*5,UI_UNIT_Y, activeptr, activepropname, 0, 0, 0, 0, 0, "");
+               if(i == 0)
                        uiButSetFlag(but, UI_BUT_DISABLED);
        }
        else {
+               /* default rows */
                if(rows == 0)
                        rows= 5;
-               if(columns == 0)
-                       columns= 1;
-
-               items= rows*columns;
 
-               box= uiLayoutBox(layout);
+               /* layout */
+               box= uiLayoutListBox(layout);
                row= uiLayoutRow(box, 0);
                col = uiLayoutColumn(row, 1);
 
-               uiBlockSetEmboss(block, UI_EMBOSSN);
+               /* init numbers */
+               RNA_property_int_range(activeptr, activeprop, &min, &max);
 
-               len= RNA_property_collection_length(ptr, prop);
-               scroll= MIN2(scroll, len-items+1);
-               scroll= MAX2(scroll, 1);
+               if(prop)
+                       len= RNA_property_collection_length(ptr, prop);
+               items= CLAMPIS(len, rows, 5);
 
-               RNA_PROP_BEGIN(ptr, itemptr, prop) {
-                       if(i >= scroll && i<scroll+items) {
-                               name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
+               pa->list_scroll= MIN2(pa->list_scroll, len-items);
+               pa->list_scroll= MAX2(pa->list_scroll, 0);
 
-                               if(name) {
-#if 0
-                                       ListItem *item= MEM_callocN(sizeof(ListItem), "uiTemplateList ListItem");
-
-                                       item->ptr= *ptr;
-                                       item->prop= prop;
-                                       item->activeprop= activeprop;
-                                       item->activeptr= itemptr;
-                                       item->activei= i;
-
-                                       if(activetype == PROP_POINTER)
-                                               item->selected= (activeptr.data == itemptr.data)? i: -1;
-                                       else if(activetype == PROP_INT)
-                                               item->selected= (activei == i)? i: -1;
-                                       else if(activetype == PROP_STRING)
-                                               item->selected= (strcmp(activename, name) == 0)? i: -1;
-#endif
+               itemlb= uiLayoutBoxGetList(box);
+
+               if(ptr->data && prop) {
+                       /* create list items */
+                       RNA_PROP_BEGIN(ptr, itemptr, prop) {
+                               if(i >= pa->list_scroll && i<pa->list_scroll+items) {
+                                       name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
 
-                                       //but= uiDefIconTextButI(block, ROW, 0, RNA_struct_ui_icon(itemptr.type), name, 0,0,UI_UNIT_X*10,UI_UNIT_Y, &item->selected, 0, i, 0, 0, "");
-                                       but= uiDefIconTextButR(block, ROW, 0, RNA_struct_ui_icon(itemptr.type), name, 0,0,UI_UNIT_X*10,UI_UNIT_Y, ptr, activepropname, 0/*&item->selected*/, 0, i, 0, 0, "");
+                                       subrow= uiLayoutRow(col, 0);
+
+                                       /* create button */
+                                       if(!icon || icon == ICON_DOT)
+                                               but= uiDefButR(block, LISTROW, 0, (name)? name: "", 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, "");
+                                       else
+                                               but= uiDefIconTextButR(block, LISTROW, 0, icon, (name)? name: "", 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, "");
                                        uiButSetFlag(but, UI_ICON_LEFT|UI_TEXT_LEFT);
-                                       //uiButSetNFunc(but, list_item_cb, item, NULL);
 
-                                       MEM_freeN(name);
+                                       /* XXX hardcoded */
+                                       if(itemptr.type == &RNA_MeshTextureFaceLayer || itemptr.type == &RNA_MeshColorLayer) {
+                                               uiBlockSetEmboss(block, UI_EMBOSSN);
+                                               uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, &itemptr, "active_render", 0, 0, 0, 0, 0, NULL);
+                                               uiBlockSetEmboss(block, UI_EMBOSS);
+                                       }
+
+                                       if(name)
+                                               MEM_freeN(name);
 
-                                       link= MEM_callocN(sizeof(CollectionPointerLink), "uiTemplateList return");
-                                       link->ptr= itemptr;
-                                       BLI_addtail(&lb, link);
+                                       /* add to list to return */
+                                       //list_item_add(&lb, itemlb, subrow, &itemptr);
                                }
-                       }
 
-                       i++;
+                               i++;
+                       }
+                       RNA_PROP_END;
                }
-               RNA_PROP_END;
 
-               while(i < scroll+items) {
-                       if(i >= scroll)
+               /* add dummy buttons to fill space */
+               while(i < pa->list_scroll+items) {
+                       if(i >= pa->list_scroll)
                                uiItemL(col, "", 0);
                        i++;
                }
 
-               uiBlockSetEmboss(block, UI_EMBOSS);
-
+               /* add scrollbar */
                if(len > items) {
                        col= uiLayoutColumn(row, 0);
-                       uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*0.75,UI_UNIT_Y*items, &scroll, 1, len-items+1, items, 0, "");
+                       uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*0.75,UI_UNIT_Y*items, &pa->list_scroll, 0, len-items, items, 0, "");
                }
-
-               //uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*15,UI_UNIT_Y*0.75, &scroll, 1, 16-5, 5, 0, "");
        }
 
+       /* return items in list */
        return lb;
 }
 
+/************************* Operator Search Template **************************/
+
+static void operator_call_cb(bContext *C, void *arg1, void *arg2)
+{
+       wmOperatorType *ot= arg2;
+       
+       if(ot)
+               WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, NULL);
+}
+
+static void operator_search_cb(const bContext *C, void *arg, char *str, uiSearchItems *items)
+{
+       wmOperatorType *ot = WM_operatortype_first();
+       
+       for(; ot; ot= ot->next) {
+               
+               if(BLI_strcasestr(ot->name, str)) {
+                       if(WM_operator_poll((bContext*)C, ot)) {
+                               char name[256];
+                               int len= strlen(ot->name);
+                               
+                               /* display name for menu, can hold hotkey */
+                               BLI_strncpy(name, ot->name, 256);
+                               
+                               /* check for hotkey */
+                               if(len < 256-6) {
+                                       if(WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, &name[len+1], 256-len-1))
+                                               name[len]= '|';
+                               }
+                               
+                               if(0==uiSearchItemAdd(items, name, ot, 0))
+                                       break;
+                       }
+               }
+       }
+}
+
+void uiTemplateOperatorSearch(uiLayout *layout)
+{
+       uiBlock *block;
+       uiBut *but;
+       static char search[256]= "";
+               
+       block= uiLayoutGetBlock(layout);
+       uiBlockSetCurLayout(block, layout);
+
+       but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X*6, UI_UNIT_Y, "");
+       uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL);
+}
+
+/************************* Running Jobs Template **************************/
+
+#define B_STOPRENDER   1
+#define B_STOPCAST             2
+#define B_STOPANIM             3
+
+static void do_running_jobs(bContext *C, void *arg, int event)
+{
+       switch(event) {
+               case B_STOPRENDER:
+                       G.afbreek= 1;
+                       break;
+               case B_STOPCAST:
+                       WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C));
+                       break;
+               case B_STOPANIM:
+                       WM_operator_name_call(C, "SCREEN_OT_animation_play", WM_OP_INVOKE_SCREEN, NULL);
+                       break;
+       }
+}
+
+void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
+{
+       bScreen *screen= CTX_wm_screen(C);
+       Scene *scene= CTX_data_scene(C);
+       wmWindowManager *wm= CTX_wm_manager(C);
+       uiBlock *block;
+
+       block= uiLayoutGetBlock(layout);
+       uiBlockSetCurLayout(block, layout);
+
+       uiBlockSetHandleFunc(block, do_running_jobs, NULL);
+
+       if(WM_jobs_test(wm, scene))
+               uiDefIconTextBut(block, BUT, B_STOPRENDER, ICON_REC, "Render", 0,0,75,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop rendering");
+       if(WM_jobs_test(wm, screen))
+               uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_REC, "Capture", 0,0,85,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop screencast");
+       if(screen->animtimer)
+               uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_REC, "Anim Player", 0,0,85,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop animation playback");
+}
+
+