Merge branch 'master' of http://git.roojs.com/roojs1
[roojs1] / roojs-debug.js
index 67a6f54..a228ec5 100644 (file)
@@ -505,15 +505,18 @@ Roo.factory(conf, Roo.data);
             return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
         },
 
-        // internal
-        callback : function(cb, scope, args, delay){
-            if(typeof cb == "function"){
-                if(delay){
-                    cb.defer(delay, scope, args || []);
-                }else{
-                    cb.apply(scope, args || []);
-                }
+        // internal (non-delayed, will get a return value..)
+        callback : function(cb, scope, args, delay)
+               {
+            if(typeof cb != "function"){
+                               return false;
+                       }
+                       if(delay){
+                               cb.defer(delay, scope, args || []);
+                               return false
             }
+                       return cb.apply(scope, args || []);
+
         },
 
         /**
@@ -1205,12 +1208,35 @@ document.write(dt.format(Date.patterns.ShortDate));
 /**
  Returns the number of milliseconds between this date and date
  @param {Date} date (optional) Defaults to now
- @return {Number} The diff in milliseconds
+ @param {String} interval (optional) Default Date.MILLI, A valid date interval enum value (eg. Date.DAY) 
+ @return {Number} The diff in milliseconds or units of interval
  @member Date getElapsed
  */
-Date.prototype.getElapsed = function(date) {
-       return Math.abs((date || new Date()).getTime()-this.getTime());
+Date.prototype.getElapsed = function(date, interval)
+{
+    date = date ||  new Date();
+    var ret = Math.abs(date.getTime()-this.getTime());
+    switch (interval) {
+       
+        case  Date.SECOND:
+            return Math.floor(ret / (1000));
+        case  Date.MINUTE:
+            return Math.floor(ret / (1000*60));
+        case  Date.HOUR:
+            return Math.floor(ret / (1000*60*60));
+        case  Date.DAY:
+            return Math.floor(ret / (1000*60*60*24));
+        case  Date.MONTH: // this does not give exact number...??
+            return ((date.format("Y") - this.format("Y")) * 12) + (date.format("m") - this.format("m"));
+        case  Date.YEAR: // this does not give exact number...??
+            return (date.format("Y") - this.format("Y"));
+       
+        case  Date.MILLI:
+        default:
+            return ret;
+    }
 };
 // was in date file..
 
 
@@ -2679,7 +2705,10 @@ Roo.lib.Event = function() {
          * @param {DomForm} form element
          * @return {String} urlencode form output.
          */
-        serializeForm : function(form) {
+        serializeForm : function(form, include_disabled) {
+            
+            include_disabled = typeof(include_disabled) == 'undefined' ? false : include_disabled;
+
             if(typeof form == 'string') {
                 form = (document.getElementById(form) || document.forms[form]);
             }
@@ -2687,7 +2716,7 @@ Roo.lib.Event = function() {
             var el, name, val, disabled, data = '', hasSubmit = false;
             for (var i = 0; i < form.elements.length; i++) {
                 el = form.elements[i];
-                disabled = form.elements[i].disabled;
+                disabled = include_disabled ? false : form.elements[i].disabled;
                 name = form.elements[i].name;
                 val = form.elements[i].value;
 
@@ -5490,7 +5519,7 @@ Roo.DomHelper = function(){
         if (typeof(o) == 'string') {
             return parentNode.appendChild(document.createTextNode(o));
         }
-        o.tag = o.tag || div;
+        o.tag = o.tag || 'div';
         if (o.ns && Roo.isIE) {
             ns = false;
             o.tag = o.ns + ':' + o.tag;
@@ -16607,8 +16636,8 @@ Roo.extend(Roo.state.Provider, Roo.util.Observable, {
 init : function(){
    Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
    ...
-   // supposed you have a {@link Roo.BorderLayout}
-   var layout = new Roo.BorderLayout(...);
+   // supposed you have a {@link Roo.layout.Border}
+   var layout = new Roo.layout.Border(...);
    layout.restoreState();
    // or a {Roo.BasicDialog}
    var dialog = new Roo.BasicDialog(...);
@@ -16969,6 +16998,13 @@ Roo.extend(Roo.Component, Roo.util.Observable, {
      */
     actionMode : "el",
 
+        /**
+     * @cfg {String} style
+     * css styles to add to component
+     * eg. text-align:right;
+     */
+    style : false,
+       
     /** @private */
     getActionEl : function(){
         return this[this.actionMode];
@@ -18032,7 +18068,7 @@ Roo.extend(Roo.Layer, Roo.Element, {
  *
  * Each sub module is expected to have a parent pointing to the class name of it's parent module.
  *
- * When the top level is false, a 'Roo.BorderLayout' is created and the element is flagged as 'topModule'
+ * When the top level is false, a 'Roo.layout.Border' is created and the element is flagged as 'topModule'
  * - if mulitple topModules exist, the last one is defined as the top module.
  *
  * Embeded Roo
@@ -18251,7 +18287,7 @@ Roo.extend(Roo.XComponent, Roo.util.Observable, {
             
             el = el ? Roo.get(el) : false;     
             
-            if (typeof(Roo.BorderLayout) == 'undefined' ) {
+            if (typeof(Roo.layout.Border) == 'undefined' ) {
                 
                 this.parent =  {
                     el : new Roo.bootstrap.layout.Border({
@@ -18274,7 +18310,7 @@ Roo.extend(Roo.XComponent, Roo.util.Observable, {
             
                 // it's a top level one..
                 this.parent =  {
-                    el : new Roo.BorderLayout(el || document.body, {
+                    el : new Roo.layout.Border(el || document.body, {
                         center: {
                             titlebar: false,
                             autoScroll:false,
@@ -24950,8 +24986,8 @@ Roo.data.Store = function(config){
          * If you return Json { data: [] , success: false, .... } then this will be thrown with the following args
          * 
          * @param {Proxy} 
-         * @param {Object} return from JsonData.reader() - success, totalRecords, records
-         * @param {Object} load options 
+         * @param {Object} ret return data from JsonData.reader() - success, totalRecords, records
+         * @param {Object} opts - load Options
          * @param {Object} jsonData from your request (normally this contains the Exception)
          */
         loadexception : true
@@ -25863,14 +25899,16 @@ Roo.extend(Roo.data.DataProxy, Roo.util.Observable);
  */
 /**
  * @class Roo.data.MemoryProxy
+ * @extends Roo.data.DataProxy
  * An implementation of Roo.data.DataProxy that simply passes the data specified in its constructor
  * to the Reader when its load method is called.
  * @constructor
- * @param {Object} data The data object which the Reader uses to construct a block of Roo.data.Records.
+ * @param {Object} config  A config object containing the objects needed for the Store to access data,
  */
-Roo.data.MemoryProxy = function(data){
-    if (data.data) {
-        data = data.data;
+Roo.data.MemoryProxy = function(config){
+    var data = config;
+    if (typeof(config) != 'undefined' && typeof(config.data) != 'undefined') {
+        data = config.data;
     }
     Roo.data.MemoryProxy.superclass.constructor.call(this);
     this.data = data;
@@ -25878,6 +25916,9 @@ Roo.data.MemoryProxy = function(data){
 
 Roo.extend(Roo.data.MemoryProxy, Roo.data.DataProxy, {
     
+    /**
+     *  @cfg {Object} data The data object which the Reader uses to construct a block of Roo.data.Records.
+     */
     /**
      * Load data from the requested source (in this case an in-memory
      * data object passed to the constructor), read the data object into
@@ -25952,24 +25993,24 @@ Roo.extend(Roo.data.HttpProxy, Roo.data.DataProxy, {
     // thse are take from connection...
     
     /**
-     * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
+     * @cfg {String} url  The default URL to be used for requests to the server. (defaults to undefined)
      */
     /**
-     * @cfg {Object} extraParams (Optional) An object containing properties which are used as
+     * @cfg {Object} extraParams  An object containing properties which are used as
      * extra parameters to each request made by this object. (defaults to undefined)
      */
     /**
-     * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
+     * @cfg {Object} defaultHeaders   An object containing request headers which are added
      *  to each request made by this object. (defaults to undefined)
      */
     /**
-     * @cfg {String} method (Optional) The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
+     * @cfg {String} method (GET|POST)  The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
      */
     /**
-     * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
+     * @cfg {Number} timeout The timeout in milliseconds to be used for requests. (defaults to 30000)
      */
      /**
-     * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
+     * @cfg {Boolean} autoAbort Whether this request should abort any pending requests. (defaults to false)
      * @type Boolean
      */
   
@@ -29931,7 +29972,1902 @@ Roo.extend(Roo.DatePicker, Roo.Component, {
         
         
     }
-});        /*
+});Roo.panel = {};
+/*
+* Licence: LGPL
+*/
+
+/**
+ * @class Roo.panel.Cropbox
+ * @extends Roo.BoxComponent
+ * Panel Cropbox class
+ * @cfg {String} emptyText show when image has been loaded
+ * @cfg {String} rotateNotify show when image too small to rotate
+ * @cfg {Number} errorTimeout default 3000
+ * @cfg {Number} minWidth default 300
+ * @cfg {Number} minHeight default 300
+ * @cfg {Number} outputMaxWidth default 1200
+ * @cfg {Number} windowSize default 300
+ * @cfg {Array} buttons default ['rotateLeft', 'pictureBtn', 'rotateRight']
+ * @cfg {Boolean} isDocument (true|false) default false
+ * @cfg {String} url action url
+ * @cfg {String} paramName default 'imageUpload'
+ * @cfg {String} method default POST
+ * @cfg {Boolean} loadMask (true|false) default true
+ * @cfg {Boolean} loadingText default 'Loading...'
+ * 
+ * @constructor
+ * Create a new Cropbox
+ * @param {Object} config The config object
+ */
+
+ Roo.panel.Cropbox = function(config){
+    Roo.panel.Cropbox.superclass.constructor.call(this, config);
+    
+    this.addEvents({
+        /**
+         * @event beforeselectfile
+         * Fire before select file
+         * @param {Roo.panel.Cropbox} this
+         */
+        "beforeselectfile" : true,
+        /**
+         * @event initial
+         * Fire after initEvent
+         * @param {Roo.panel.Cropbox} this
+         */
+        "initial" : true,
+        /**
+         * @event crop
+         * Fire after initEvent
+         * @param {Roo.panel.Cropbox} this
+         * @param {String} data
+         */
+        "crop" : true,
+        /**
+         * @event prepare
+         * Fire when preparing the file data
+         * @param {Roo.panel.Cropbox} this
+         * @param {Object} file
+         */
+        "prepare" : true,
+        /**
+         * @event exception
+         * Fire when get exception
+         * @param {Roo.panel.Cropbox} this
+         * @param {XMLHttpRequest} xhr
+         */
+        "exception" : true,
+        /**
+         * @event beforeloadcanvas
+         * Fire before load the canvas
+         * @param {Roo.panel.Cropbox} this
+         * @param {String} src
+         */
+        "beforeloadcanvas" : true,
+        /**
+         * @event trash
+         * Fire when trash image
+         * @param {Roo.panel.Cropbox} this
+         */
+        "trash" : true,
+        /**
+         * @event download
+         * Fire when download the image
+         * @param {Roo.panel.Cropbox} this
+         */
+        "download" : true,
+        /**
+         * @event footerbuttonclick
+         * Fire when footerbuttonclick
+         * @param {Roo.panel.Cropbox} this
+         * @param {String} type
+         */
+        "footerbuttonclick" : true,
+        /**
+         * @event resize
+         * Fire when resize
+         * @param {Roo.panel.Cropbox} this
+         */
+        "resize" : true,
+        /**
+         * @event rotate
+         * Fire when rotate the image
+         * @param {Roo.panel.Cropbox} this
+         * @param {String} pos
+         */
+        "rotate" : true,
+        /**
+         * @event inspect
+         * Fire when inspect the file
+         * @param {Roo.panel.Cropbox} this
+         * @param {Object} file
+         */
+        "inspect" : true,
+        /**
+         * @event upload
+         * Fire when xhr upload the file
+         * @param {Roo.panel.Cropbox} this
+         * @param {Object} data
+         */
+        "upload" : true,
+        /**
+         * @event arrange
+         * Fire when arrange the file data
+         * @param {Roo.panel.Cropbox} this
+         * @param {Object} formData
+         */
+        "arrange" : true,
+        /**
+         * @event loadcanvas
+         * Fire after load the canvas
+         * @param {Roo.panel.Cropbox}
+         * @param {Object} imgEl
+         */
+        "loadcanvas" : true
+    });
+    
+    this.buttons = this.buttons || Roo.panel.Cropbox.footer.STANDARD;
+};
+
+Roo.extend(Roo.panel.Cropbox, Roo.Component,  {
+    
+    emptyText : 'Click to upload image',
+    rotateNotify : 'Image is too small to rotate',
+    errorTimeout : 3000,
+    scale : 0,
+    baseScale : 1,
+    rotate : 0,
+    dragable : false,
+    pinching : false,
+    mouseX : 0,
+    mouseY : 0,
+    cropData : false,
+    minWidth : 300,
+    minHeight : 300,
+    outputMaxWidth : 1200,
+    windowSize : 300,
+    file : false,
+    exif : {},
+    baseRotate : 1,
+    cropType : 'image/jpeg',
+    buttons : false,
+    canvasLoaded : false,
+    isDocument : false,
+    method : 'POST',
+    paramName : 'imageUpload',
+    loadMask : true,
+    loadingText : 'Loading...',
+    maskEl : false,
+    
+    getAutoCreate : function()
+    {
+        var cfg = {
+            tag : 'div',
+            cls : 'roo-upload-cropbox',
+            cn : [
+                {
+                    tag : 'input',
+                    cls : 'roo-upload-cropbox-selector',
+                    type : 'file'
+                },
+                {
+                    tag : 'div',
+                    cls : 'roo-upload-cropbox-body',
+                    style : 'cursor:pointer',
+                    cn : [
+                        {
+                            tag : 'div',
+                            cls : 'roo-upload-cropbox-preview'
+                        },
+                        {
+                            tag : 'div',
+                            cls : 'roo-upload-cropbox-thumb'
+                        },
+                        {
+                            tag : 'div',
+                            cls : 'roo-upload-cropbox-empty-notify',
+                            html : this.emptyText
+                        },
+                        {
+                            tag : 'div',
+                            cls : 'roo-upload-cropbox-error-notify alert alert-danger',
+                            html : this.rotateNotify
+                        }
+                    ]
+                },
+                {
+                    tag : 'div',
+                    cls : 'roo-upload-cropbox-footer',
+                    cn : {
+                        tag : 'div',
+                        cls : 'btn-group btn-group-justified roo-upload-cropbox-btn-group',
+                        cn : []
+                    }
+                }
+            ]
+        };
+        
+        return cfg;
+    },
+    
+    onRender : function(ct, position)
+    {
+        Roo.panel.Cropbox.superclass.onRender.call(this, ct, position);
+
+        if(this.el){
+            if (this.el.attr('xtype')) {
+                this.el.attr('xtypex', this.el.attr('xtype'));
+                this.el.dom.removeAttribute('xtype');
+                
+                this.initEvents();
+            }
+        }
+        else {
+            var cfg = Roo.apply({},  this.getAutoCreate());
+        
+            cfg.id = this.id || Roo.id();
+            
+            if (this.cls) {
+                cfg.cls = (typeof(cfg.cls) == 'undefined' ? this.cls : cfg.cls) + ' ' + this.cls;
+            }
+            
+            if (this.style) { // fixme needs to support more complex style data.
+                cfg.style = (typeof(cfg.style) == 'undefined' ? this.style : cfg.style) + '; ' + this.style;
+            }
+            
+            this.el = ct.createChild(cfg, position);
+            
+            this.initEvents();
+        }
+        
+        if (this.buttons.length) {
+            
+            Roo.each(this.buttons, function(bb) {
+                
+                var btn = this.el.select('.roo-upload-cropbox-footer div.roo-upload-cropbox-btn-group').first().createChild(bb);
+                
+                btn.on('click', this.onFooterButtonClick.createDelegate(this, [bb.action], true));
+                
+            }, this);
+        }
+        
+        if(this.loadMask){
+            this.maskEl = this.el;
+        }
+    },
+    
+    initEvents : function()
+    {
+        this.urlAPI = (window.createObjectURL && window) || 
+                                (window.URL && URL.revokeObjectURL && URL) || 
+                                (window.webkitURL && webkitURL);
+                        
+        this.bodyEl = this.el.select('.roo-upload-cropbox-body', true).first();
+        this.bodyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.selectorEl = this.el.select('.roo-upload-cropbox-selector', true).first();
+        this.selectorEl.hide();
+        
+        this.previewEl = this.el.select('.roo-upload-cropbox-preview', true).first();
+        this.previewEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.thumbEl = this.el.select('.roo-upload-cropbox-thumb', true).first();
+        this.thumbEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.thumbEl.hide();
+        
+        this.notifyEl = this.el.select('.roo-upload-cropbox-empty-notify', true).first();
+        this.notifyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.errorEl = this.el.select('.roo-upload-cropbox-error-notify', true).first();
+        this.errorEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.errorEl.hide();
+        
+        this.footerEl = this.el.select('.roo-upload-cropbox-footer', true).first();
+        this.footerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.footerEl.hide();
+        
+        this.setThumbBoxSize();
+        
+        this.bind();
+        
+        this.resize();
+        
+        this.fireEvent('initial', this);
+    },
+
+    bind : function()
+    {
+        var _this = this;
+        
+        window.addEventListener("resize", function() { _this.resize(); } );
+        
+        this.bodyEl.on('click', this.beforeSelectFile, this);
+        
+        if(Roo.isTouch){
+            this.bodyEl.on('touchstart', this.onTouchStart, this);
+            this.bodyEl.on('touchmove', this.onTouchMove, this);
+            this.bodyEl.on('touchend', this.onTouchEnd, this);
+        }
+        
+        if(!Roo.isTouch){
+            this.bodyEl.on('mousedown', this.onMouseDown, this);
+            this.bodyEl.on('mousemove', this.onMouseMove, this);
+            var mousewheel = (/Firefox/i.test(navigator.userAgent))? 'DOMMouseScroll' : 'mousewheel';
+            this.bodyEl.on(mousewheel, this.onMouseWheel, this);
+            Roo.get(document).on('mouseup', this.onMouseUp, this);
+        }
+        
+        this.selectorEl.on('change', this.onFileSelected, this);
+    },
+    
+    reset : function()
+    {    
+        this.scale = 0;
+        this.baseScale = 1;
+        this.rotate = 0;
+        this.baseRotate = 1;
+        this.dragable = false;
+        this.pinching = false;
+        this.mouseX = 0;
+        this.mouseY = 0;
+        this.cropData = false;
+        this.notifyEl.dom.innerHTML = this.emptyText;
+        
+        // this.selectorEl.dom.value = '';
+        
+    },
+    
+    resize : function()
+    {
+        if(this.fireEvent('resize', this) != false){
+            this.setThumbBoxPosition();
+            this.setCanvasPosition();
+        }
+    },
+    
+    onFooterButtonClick : function(e, el, o, type)
+    {
+        switch (type) {
+            case 'rotate-left' :
+                this.onRotateLeft(e);
+                break;
+            case 'rotate-right' :
+                this.onRotateRight(e);
+                break;
+            case 'picture' :
+                this.beforeSelectFile(e);
+                break;
+            case 'trash' :
+                this.trash(e);
+                break;
+            case 'crop' :
+                this.crop(e);
+                break;
+            case 'download' :
+                this.download(e);
+                break;
+            case 'center' :
+                this.center(e);
+                break;
+            default :
+                break;
+        }
+        
+        this.fireEvent('footerbuttonclick', this, type);
+    },
+    
+    beforeSelectFile : function(e)
+    {
+        e.preventDefault();
+        
+        if(this.fireEvent('beforeselectfile', this) != false){
+            this.selectorEl.dom.click();
+        }
+    },
+    
+    onFileSelected : function(e)
+    {
+        e.preventDefault();
+        
+        if(typeof(this.selectorEl.dom.files) == 'undefined' || !this.selectorEl.dom.files.length){
+            return;
+        }
+        
+        var file = this.selectorEl.dom.files[0];
+        
+        if(this.fireEvent('inspect', this, file) != false){
+            this.prepare(file);
+        }
+        
+    },
+    
+    trash : function(e)
+    {
+        this.fireEvent('trash', this);
+    },
+    
+    download : function(e)
+    {
+        this.fireEvent('download', this);
+    },
+
+    center : function(e)
+    {
+        this.setCanvasPosition();
+    },
+    
+    loadCanvas : function(src)
+    {   
+        if(this.fireEvent('beforeloadcanvas', this, src) != false){
+            
+            this.reset();
+            
+            this.imageEl = document.createElement('img');
+            
+            var _this = this;
+            
+            this.imageEl.addEventListener("load", function(){ _this.onLoadCanvas(); });
+            
+            this.imageEl.src = src;
+        }
+    },
+    
+    onLoadCanvas : function()
+    {   
+        this.imageEl.OriginWidth = this.imageEl.naturalWidth || this.imageEl.width;
+        this.imageEl.OriginHeight = this.imageEl.naturalHeight || this.imageEl.height;
+
+        if(this.fireEvent('loadcanvas', this, this.imageEl) != false){
+        
+            this.bodyEl.un('click', this.beforeSelectFile, this);
+            
+            this.notifyEl.hide();
+            this.thumbEl.show();
+            this.footerEl.show();
+            
+            this.baseRotateLevel();
+            
+            if(this.isDocument){
+                this.setThumbBoxSize();
+            }
+            
+            this.setThumbBoxPosition();
+            
+            this.baseScaleLevel();
+            
+            this.draw();
+            
+            this.resize();
+            
+            this.canvasLoaded = true;
+        
+        }
+        
+        if(this.loadMask){
+            this.maskEl.unmask();
+        }
+        
+    },
+    
+    setCanvasPosition : function(center = true)
+    {   
+        if(!this.canvasEl){
+            return;
+        }
+
+        var newCenterLeft = Math.ceil((this.bodyEl.getWidth() - this.canvasEl.width) / 2);
+        var newCenterTop = Math.ceil((this.bodyEl.getHeight() - this.canvasEl.height) / 2);
+
+        if(center) {
+            this.previewEl.setLeft(newCenterLeft);
+            this.previewEl.setTop(newCenterTop);
+
+            return;
+        }
+        
+        var oldScaleLevel = this.baseScale * Math.pow(1.02, this.startScale);
+        var oldCanvasWidth = Math.floor(this.imageEl.OriginWidth * oldScaleLevel);
+        var oldCanvasHeight = Math.floor(this.imageEl.OriginHeight * oldScaleLevel);
+
+        var oldCenterLeft = Math.ceil((this.bodyEl.getWidth() - oldCanvasWidth) / 2);
+        var oldCenterTop = Math.ceil((this.bodyEl.getHeight() - oldCanvasHeight) / 2);
+
+        var leftDiff = newCenterLeft - oldCenterLeft;
+        var topDiff = newCenterTop - oldCenterTop;
+
+        var newPreviewLeft = this.previewEl.getLeft(true) + leftDiff;
+        var newPreviewTop = this.previewEl.getTop(true) + topDiff;
+
+        this.previewEl.setLeft(newPreviewLeft);
+        this.previewEl.setTop(newPreviewTop);
+        
+    },
+    
+    onMouseDown : function(e)
+    {   
+        e.stopEvent();
+        
+        this.dragable = true;
+        this.pinching = false;
+        
+        if(this.isDocument && (this.canvasEl.width < this.thumbEl.getWidth() || this.canvasEl.height < this.thumbEl.getHeight())){
+            this.dragable = false;
+            return;
+        }
+        
+        this.mouseX = Roo.isTouch ? e.browserEvent.touches[0].pageX : e.getPageX();
+        this.mouseY = Roo.isTouch ? e.browserEvent.touches[0].pageY : e.getPageY();
+        
+    },
+    
+    onMouseMove : function(e)
+    {   
+        e.stopEvent();
+        
+        if(!this.canvasLoaded){
+            return;
+        }
+        
+        if (!this.dragable){
+            return;
+        }
+
+        var maxPaddingLeft = this.canvasEl.width / 0.9 * 0.05;
+        var maxPaddingTop = maxPaddingLeft * this.minHeight / this.minWidth;
+
+        if ((this.imageEl.OriginWidth / this.imageEl.OriginHeight <= this.minWidth / this.minHeight)) {
+            maxPaddingLeft = (this.canvasEl.height * this.minWidth / this.minHeight - this.canvasEl.width) / 2 + maxPaddingLeft;
+        }
+
+        if ((this.imageEl.OriginWidth / this.imageEl.OriginHeight >= this.minWidth / this.minHeight)) {
+            maxPaddingTop = (this.canvasEl.width * this.minHeight / this.minWidth - this.canvasEl.height) / 2 + maxPaddingTop;
+        }
+        
+        var minX = Math.ceil(this.thumbEl.getLeft(true) + this.thumbEl.getWidth() - this.canvasEl.width - maxPaddingLeft);
+        var minY = Math.ceil(this.thumbEl.getTop(true) + this.thumbEl.getHeight() - this.canvasEl.height - maxPaddingTop);
+        
+        var maxX = Math.ceil(this.thumbEl.getLeft(true) + maxPaddingLeft);
+        var maxY = Math.ceil(this.thumbEl.getTop(true) +  maxPaddingTop);
+
+        if(minX > maxX) {
+            var tempX = minX;
+            minX = maxX;
+            maxX = tempX;
+        }
+
+        if(minY > maxY) {
+            var tempY = minY;
+            minY = maxY;
+            maxY = tempY;
+        }
+
+        var x = Roo.isTouch ? e.browserEvent.touches[0].pageX : e.getPageX();
+        var y = Roo.isTouch ? e.browserEvent.touches[0].pageY : e.getPageY();
+        
+        x = x - this.mouseX;
+        y = y - this.mouseY;
+
+        var bgX = Math.ceil(x + this.previewEl.getLeft(true));
+        var bgY = Math.ceil(y + this.previewEl.getTop(true));
+        
+        bgX = (bgX < minX) ? minX : ((bgX > maxX) ? maxX : bgX);
+        bgY = (bgY < minY) ? minY : ((bgY > maxY) ? maxY : bgY);
+        
+        this.previewEl.setLeft(bgX);
+        this.previewEl.setTop(bgY);
+        
+        this.mouseX = Roo.isTouch ? e.browserEvent.touches[0].pageX : e.getPageX();
+        this.mouseY = Roo.isTouch ? e.browserEvent.touches[0].pageY : e.getPageY();
+    },
+    
+    onMouseUp : function(e)
+    {   
+        e.stopEvent();
+        
+        this.dragable = false;
+    },
+    
+    onMouseWheel : function(e)
+    {   
+        e.stopEvent();
+        
+        this.startScale = this.scale;
+        this.scale = (e.getWheelDelta() > 0) ? (this.scale + 1) : (this.scale - 1);
+        
+        if(!this.zoomable()){
+            this.scale = this.startScale;
+            return;
+        }
+
+        
+        this.draw();
+        
+        return;
+    },
+    
+    zoomable : function()
+    {
+        var minScale = this.thumbEl.getWidth() / this.minWidth;
+        
+        if(this.minWidth < this.minHeight){
+            minScale = this.thumbEl.getHeight() / this.minHeight;
+        }
+        
+        var width = Math.ceil(this.imageEl.OriginWidth * this.getScaleLevel() / minScale);
+        var height = Math.ceil(this.imageEl.OriginHeight * this.getScaleLevel() / minScale);
+        var maxWidth = this.imageEl.OriginWidth;
+        var maxHeight = this.imageEl.OriginHeight;
+
+
+        var newCanvasWidth = Math.floor(this.imageEl.OriginWidth * this.getScaleLevel());
+        var newCanvasHeight = Math.floor(this.imageEl.OriginHeight * this.getScaleLevel());
+
+        var oldCenterLeft = Math.ceil((this.bodyEl.getWidth() - this.canvasEl.width) / 2);
+        var oldCenterTop = Math.ceil((this.bodyEl.getHeight() - this.canvasEl.height) / 2);
+
+        var newCenterLeft = Math.ceil((this.bodyEl.getWidth() - newCanvasWidth) / 2);
+        var newCenterTop = Math.ceil((this.bodyEl.getHeight() - newCanvasHeight) / 2);
+
+        var leftDiff = newCenterLeft - oldCenterLeft;
+        var topDiff = newCenterTop - oldCenterTop;
+
+        var newPreviewLeft = this.previewEl.getLeft(true) + leftDiff;
+        var newPreviewTop = this.previewEl.getTop(true) + topDiff;
+
+        var paddingLeft = newPreviewLeft - this.thumbEl.getLeft(true);
+        var paddingTop = newPreviewTop - this.thumbEl.getTop(true);
+
+        var paddingRight = this.thumbEl.getLeft(true) + this.thumbEl.getWidth() - newCanvasWidth - newPreviewLeft;
+        var paddingBottom = this.thumbEl.getTop(true) + this.thumbEl.getHeight() - newCanvasHeight - newPreviewTop;
+
+        var maxPaddingLeft = newCanvasWidth / 0.9 * 0.05;
+        var maxPaddingTop = maxPaddingLeft * this.minHeight / this.minWidth;
+
+        if ((this.imageEl.OriginWidth / this.imageEl.OriginHeight <= this.minWidth / this.minHeight)) {
+            maxPaddingLeft = (newCanvasHeight * this.minWidth / this.minHeight - newCanvasWidth) / 2 + maxPaddingLeft;
+        }
+
+        if ((this.imageEl.OriginWidth / this.imageEl.OriginHeight >= this.minWidth / this.minHeight)) {
+            maxPaddingTop = (newCanvasWidth * this.minHeight / this.minWidth - newCanvasHeight) / 2 + maxPaddingTop;
+        }
+        
+        if(
+                this.isDocument &&
+                (this.rotate == 0 || this.rotate == 180) && 
+                (
+                    width > this.imageEl.OriginWidth || 
+                    height > this.imageEl.OriginHeight ||
+                    (width < this.minWidth && height < this.minHeight)
+                )
+        ){
+            return false;
+        }
+        
+        if(
+                this.isDocument &&
+                (this.rotate == 90 || this.rotate == 270) && 
+                (
+                    width > this.imageEl.OriginWidth || 
+                    height > this.imageEl.OriginHeight ||
+                    (width < this.minHeight && height < this.minWidth)
+                )
+        ){
+            return false;
+        }
+        
+        if(
+                !this.isDocument &&
+                (this.rotate == 0 || this.rotate == 180) && 
+                (
+                    // for zoom out
+                    paddingLeft > maxPaddingLeft ||
+                    paddingRight > maxPaddingLeft ||
+                    paddingTop > maxPaddingTop ||
+                    paddingBottom > maxPaddingTop ||
+                    // for zoom in
+                    width > maxWidth ||
+                    height > maxHeight
+                )
+        ){
+            return false;
+        }
+        
+        if(
+                !this.isDocument &&
+                (this.rotate == 90 || this.rotate == 270) && 
+                (
+                    width < this.minHeight || 
+                    width > this.imageEl.OriginWidth || 
+                    height < this.minWidth || 
+                    height > this.imageEl.OriginHeight
+                )
+        ){
+            return false;
+        }
+        
+        return true;
+        
+    },
+    
+    onRotateLeft : function(e)
+    {   
+        if(!this.isDocument && (this.canvasEl.height < this.thumbEl.getWidth() || this.canvasEl.width < this.thumbEl.getHeight())){
+            
+            var minScale = this.thumbEl.getWidth() / this.minWidth;
+            
+            var bw = Math.ceil(this.canvasEl.width / this.getScaleLevel());
+            var bh = Math.ceil(this.canvasEl.height / this.getScaleLevel());
+            
+            this.startScale = this.scale;
+            
+            while (this.getScaleLevel() < minScale){
+            
+                this.scale = this.scale + 1;
+                
+                if(!this.zoomable()){
+                    break;
+                }
+                
+                if(
+                        Math.ceil(bw * this.getScaleLevel()) < this.thumbEl.getHeight() ||
+                        Math.ceil(bh * this.getScaleLevel()) < this.thumbEl.getWidth()
+                ){
+                    continue;
+                }
+                
+                this.rotate = (this.rotate < 90) ? 270 : this.rotate - 90;
+
+                this.draw();
+                
+                return;
+            }
+            
+            this.scale = this.startScale;
+            
+            this.onRotateFail();
+            
+            return false;
+        }
+        
+        this.rotate = (this.rotate < 90) ? 270 : this.rotate - 90;
+
+        if(this.isDocument){
+            this.setThumbBoxSize();
+            this.setThumbBoxPosition();
+            this.setCanvasPosition();
+        }
+        
+        this.draw();
+        
+        this.fireEvent('rotate', this, 'left');
+        
+    },
+    
+    onRotateRight : function(e)
+    {
+        if(!this.isDocument && (this.canvasEl.height < this.thumbEl.getWidth() || this.canvasEl.width < this.thumbEl.getHeight())){
+            
+            var minScale = this.thumbEl.getWidth() / this.minWidth;
+        
+            var bw = Math.ceil(this.canvasEl.width / this.getScaleLevel());
+            var bh = Math.ceil(this.canvasEl.height / this.getScaleLevel());
+            
+            this.startScale = this.scale;
+            
+            while (this.getScaleLevel() < minScale){
+            
+                this.scale = this.scale + 1;
+                
+                if(!this.zoomable()){
+                    break;
+                }
+                
+                if(
+                        Math.ceil(bw * this.getScaleLevel()) < this.thumbEl.getHeight() ||
+                        Math.ceil(bh * this.getScaleLevel()) < this.thumbEl.getWidth()
+                ){
+                    continue;
+                }
+                
+                this.rotate = (this.rotate > 180) ? 0 : this.rotate + 90;
+
+                this.draw();
+                
+                return;
+            }
+            
+            this.scale = this.startScale;
+            
+            this.onRotateFail();
+            
+            return false;
+        }
+        
+        this.rotate = (this.rotate > 180) ? 0 : this.rotate + 90;
+
+        if(this.isDocument){
+            this.setThumbBoxSize();
+            this.setThumbBoxPosition();
+            this.setCanvasPosition();
+        }
+        
+        this.draw();
+        
+        this.fireEvent('rotate', this, 'right');
+    },
+    
+    onRotateFail : function()
+    {
+        this.errorEl.show(true);
+        
+        var _this = this;
+        
+        (function() { _this.errorEl.hide(true); }).defer(this.errorTimeout);
+    },
+    
+    draw : function()
+    {
+        this.previewEl.dom.innerHTML = '';
+        
+        var canvasEl = document.createElement("canvas");
+        
+        var contextEl = canvasEl.getContext("2d");
+        
+        canvasEl.width = this.imageEl.OriginWidth * this.getScaleLevel();
+        canvasEl.height = this.imageEl.OriginWidth * this.getScaleLevel();
+        var center = this.imageEl.OriginWidth / 2;
+        
+        if(this.imageEl.OriginWidth < this.imageEl.OriginHeight){
+            canvasEl.width = this.imageEl.OriginHeight * this.getScaleLevel();
+            canvasEl.height = this.imageEl.OriginHeight * this.getScaleLevel();
+            center = this.imageEl.OriginHeight / 2;
+        }
+        
+        contextEl.scale(this.getScaleLevel(), this.getScaleLevel());
+        
+        contextEl.translate(center, center);
+        contextEl.rotate(this.rotate * Math.PI / 180);
+
+        contextEl.drawImage(this.imageEl, 0, 0, this.imageEl.OriginWidth, this.imageEl.OriginHeight, center * -1, center * -1, this.imageEl.OriginWidth, this.imageEl.OriginHeight);
+        
+        this.canvasEl = document.createElement("canvas");
+        
+        this.contextEl = this.canvasEl.getContext("2d");
+        
+        switch (this.rotate) {
+            case 0 :
+                
+                this.canvasEl.width = this.imageEl.OriginWidth * this.getScaleLevel();
+                this.canvasEl.height = this.imageEl.OriginHeight * this.getScaleLevel();
+                
+                this.contextEl.drawImage(canvasEl, 0, 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                
+                break;
+            case 90 : 
+                
+                this.canvasEl.width = this.imageEl.OriginHeight * this.getScaleLevel();
+                this.canvasEl.height = this.imageEl.OriginWidth * this.getScaleLevel();
+                
+                if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+                    this.contextEl.drawImage(canvasEl, Math.abs(this.canvasEl.width - this.canvasEl.height), 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                    break;
+                }
+                
+                this.contextEl.drawImage(canvasEl, 0, 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                
+                break;
+            case 180 :
+                
+                this.canvasEl.width = this.imageEl.OriginWidth * this.getScaleLevel();
+                this.canvasEl.height = this.imageEl.OriginHeight * this.getScaleLevel();
+                
+                if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+                    this.contextEl.drawImage(canvasEl, 0, Math.abs(this.canvasEl.width - this.canvasEl.height), this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                    break;
+                }
+                
+                this.contextEl.drawImage(canvasEl, Math.abs(this.canvasEl.width - this.canvasEl.height), 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                
+                break;
+            case 270 :
+                
+                this.canvasEl.width = this.imageEl.OriginHeight * this.getScaleLevel();
+                this.canvasEl.height = this.imageEl.OriginWidth * this.getScaleLevel();
+        
+                if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+                    this.contextEl.drawImage(canvasEl, 0, 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                    break;
+                }
+                
+                this.contextEl.drawImage(canvasEl, 0, Math.abs(this.canvasEl.width - this.canvasEl.height), this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                
+                break;
+            default : 
+                break;
+        }
+        
+        this.previewEl.appendChild(this.canvasEl);
+        
+        this.setCanvasPosition(false);
+    },
+    
+    crop : function()
+    {
+        if(!this.canvasLoaded){
+            return;
+        }
+        
+        var imageCanvas = document.createElement("canvas");
+        
+        var imageContext = imageCanvas.getContext("2d");
+        
+        imageCanvas.width = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? this.imageEl.OriginWidth : this.imageEl.OriginHeight;
+        imageCanvas.height = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? this.imageEl.OriginWidth : this.imageEl.OriginHeight;
+        
+        var center = imageCanvas.width / 2;
+        
+        imageContext.translate(center, center);
+        
+        imageContext.rotate(this.rotate * Math.PI / 180);
+        
+        imageContext.drawImage(this.imageEl, 0, 0, this.imageEl.OriginWidth, this.imageEl.OriginHeight, center * -1, center * -1, this.imageEl.OriginWidth, this.imageEl.OriginHeight);
+        
+        var canvas = document.createElement("canvas");
+        
+        var context = canvas.getContext("2d");
+
+        canvas.width = this.thumbEl.getWidth() / this.getScaleLevel();
+        
+        canvas.height = this.thumbEl.getHeight() / this.getScaleLevel();
+
+        switch (this.rotate) {
+            case 0 :
+                
+                var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getWidth() / this.getScaleLevel());
+                var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getHeight() / this.getScaleLevel());
+                
+                var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel());
+                var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel());
+                
+                var sx = this.thumbEl.getLeft(true) - this.previewEl.getLeft(true);
+                var sy = this.thumbEl.getTop(true) - this.previewEl.getTop(true);
+
+                sx = sx < 0 ? 0 : (sx / this.getScaleLevel());
+                sy = sy < 0 ? 0 : (sy / this.getScaleLevel());
+
+                if(canvas.width > this.outputMaxWidth) {
+                    var scale = this.outputMaxWidth / canvas.width;
+                    canvas.width = canvas.width * scale;
+                    canvas.height = canvas.height * scale;
+                    context.scale(scale, scale);
+                }
+
+                context.fillStyle = 'white';
+                context.fillRect(0, 0, this.thumbEl.getWidth() / this.getScaleLevel(), this.thumbEl.getHeight() / this.getScaleLevel());
+
+
+                context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height);
+                
+                break;
+            case 90 : 
+                
+                var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getWidth() / this.getScaleLevel());
+                var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getHeight() / this.getScaleLevel());
+                
+                var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel());
+                var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel());
+                
+                var targetWidth = this.minWidth - 2 * x;
+                var targetHeight = this.minHeight - 2 * y;
+                
+                var scale = 1;
+                
+                if((x == 0 && y == 0) || (x == 0 && y > 0)){
+                    scale = targetWidth / width;
+                }
+                
+                if(x > 0 && y == 0){
+                    scale = targetHeight / height;
+                }
+                
+                if(x > 0 && y > 0){
+                    scale = targetWidth / width;
+                    
+                    if(width < height){
+                        scale = targetHeight / height;
+                    }
+                }
+                
+                context.scale(scale, scale);
+                
+                var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true));
+                var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true));
+
+                sx = sx < 0 ? 0 : (sx / this.getScaleLevel());
+                sy = sy < 0 ? 0 : (sy / this.getScaleLevel());
+                
+                sx += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight) : 0;
+                
+                context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height);
+                
+                break;
+            case 180 :
+                
+                var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getWidth() / this.getScaleLevel());
+                var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getHeight() / this.getScaleLevel());
+                
+                var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel());
+                var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel());
+                
+                var targetWidth = this.minWidth - 2 * x;
+                var targetHeight = this.minHeight - 2 * y;
+                
+                var scale = 1;
+                
+                if((x == 0 && y == 0) || (x == 0 && y > 0)){
+                    scale = targetWidth / width;
+                }
+                
+                if(x > 0 && y == 0){
+                    scale = targetHeight / height;
+                }
+                
+                if(x > 0 && y > 0){
+                    scale = targetWidth / width;
+                    
+                    if(width < height){
+                        scale = targetHeight / height;
+                    }
+                }
+                
+                context.scale(scale, scale);
+                
+                var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true));
+                var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true));
+
+                sx = sx < 0 ? 0 : (sx / this.getScaleLevel());
+                sy = sy < 0 ? 0 : (sy / this.getScaleLevel());
+
+                sx += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? 0 : Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight);
+                sy += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight) : 0;
+                
+                context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height);
+                
+                break;
+            case 270 :
+                
+                var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getWidth() / this.getScaleLevel());
+                var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getHeight() / this.getScaleLevel());
+                
+                var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel());
+                var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel());
+                
+                var targetWidth = this.minWidth - 2 * x;
+                var targetHeight = this.minHeight - 2 * y;
+                
+                var scale = 1;
+                
+                if((x == 0 && y == 0) || (x == 0 && y > 0)){
+                    scale = targetWidth / width;
+                }
+                
+                if(x > 0 && y == 0){
+                    scale = targetHeight / height;
+                }
+                
+                if(x > 0 && y > 0){
+                    scale = targetWidth / width;
+                    
+                    if(width < height){
+                        scale = targetHeight / height;
+                    }
+                }
+                
+                context.scale(scale, scale);
+                var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true));
+                var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true));
+
+                sx = sx < 0 ? 0 : (sx / this.getScaleLevel());
+                sy = sy < 0 ? 0 : (sy / this.getScaleLevel());
+                
+                sy += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? 0 : Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight);
+                
+                context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height);
+                
+                break;
+            default : 
+                break;
+        }
+        
+        this.cropData = canvas.toDataURL(this.cropType);
+        
+        if(this.fireEvent('crop', this, this.cropData) !== false){
+            this.process(this.file, this.cropData);
+        }
+        
+        return;
+        
+    },
+    
+    setThumbBoxSize : function()
+    {
+        var width, height;
+        
+        if(this.isDocument && typeof(this.imageEl) != 'undefined'){
+            width = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.max(this.minWidth, this.minHeight) : Math.min(this.minWidth, this.minHeight);
+            height = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.min(this.minWidth, this.minHeight) : Math.max(this.minWidth, this.minHeight);
+            
+            this.minWidth = width;
+            this.minHeight = height;
+            
+            if(this.rotate == 90 || this.rotate == 270){
+                this.minWidth = height;
+                this.minHeight = width;
+            }
+        }
+        
+        height = this.windowSize;
+        width = Math.ceil(this.minWidth * height / this.minHeight);
+        
+        if(this.minWidth > this.minHeight){
+            width = this.windowSize;
+            height = Math.ceil(this.minHeight * width / this.minWidth);
+        }
+        
+        this.thumbEl.setStyle({
+            width : width + 'px',
+            height : height + 'px'
+        });
+
+        return;
+            
+    },
+    
+    setThumbBoxPosition : function()
+    {
+        var x = Math.ceil((this.bodyEl.getWidth() - this.thumbEl.getWidth()) / 2 );
+        var y = Math.ceil((this.bodyEl.getHeight() - this.thumbEl.getHeight()) / 2);
+        
+        this.thumbEl.setLeft(x);
+        this.thumbEl.setTop(y);
+        
+    },
+    
+    baseRotateLevel : function()
+    {
+        this.baseRotate = 1;
+        
+        if(
+                typeof(this.exif) != 'undefined' &&
+                typeof(this.exif[Roo.panel.Cropbox['tags']['Orientation']]) != 'undefined' &&
+                [1, 3, 6, 8].indexOf(this.exif[Roo.panel.Cropbox['tags']['Orientation']]) != -1
+        ){
+            this.baseRotate = this.exif[Roo.panel.Cropbox['tags']['Orientation']];
+        }
+        
+        this.rotate = Roo.panel.Cropbox['Orientation'][this.baseRotate];
+        
+    },
+    
+    baseScaleLevel : function()
+    {
+        var width, height;
+        
+        if(this.isDocument){
+            
+            if(this.baseRotate == 6 || this.baseRotate == 8){
+            
+                height = this.thumbEl.getHeight();
+                this.baseScale = height / this.imageEl.OriginWidth;
+
+                if(this.imageEl.OriginHeight * this.baseScale > this.thumbEl.getWidth()){
+                    width = this.thumbEl.getWidth();
+                    this.baseScale = width / this.imageEl.OriginHeight;
+                }
+
+                return;
+            }
+
+            height = this.thumbEl.getHeight();
+            this.baseScale = height / this.imageEl.OriginHeight;
+
+            if(this.imageEl.OriginWidth * this.baseScale > this.thumbEl.getWidth()){
+                width = this.thumbEl.getWidth();
+                this.baseScale = width / this.imageEl.OriginWidth;
+            }
+
+            return;
+        }
+        
+        if(this.baseRotate == 6 || this.baseRotate == 8){
+            
+            width = this.thumbEl.getHeight();
+            this.baseScale = width / this.imageEl.OriginHeight;
+            
+            if(this.imageEl.OriginHeight * this.baseScale < this.thumbEl.getWidth()){
+                height = this.thumbEl.getWidth();
+                this.baseScale = height / this.imageEl.OriginHeight;
+            }
+            
+            if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+                height = this.thumbEl.getWidth();
+                this.baseScale = height / this.imageEl.OriginHeight;
+                
+                if(this.imageEl.OriginWidth * this.baseScale < this.thumbEl.getHeight()){
+                    width = this.thumbEl.getHeight();
+                    this.baseScale = width / this.imageEl.OriginWidth;
+                }
+            }
+            
+            return;
+        }
+        
+        width = this.thumbEl.getWidth();
+        this.baseScale = width / this.imageEl.OriginWidth;
+        
+        if(this.imageEl.OriginHeight * this.baseScale < this.thumbEl.getHeight()){
+            height = this.thumbEl.getHeight();
+            this.baseScale = height / this.imageEl.OriginHeight;
+        }
+        
+        if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+            
+            height = this.thumbEl.getHeight();
+            this.baseScale = height / this.imageEl.OriginHeight;
+            
+            if(this.imageEl.OriginWidth * this.baseScale < this.thumbEl.getWidth()){
+                width = this.thumbEl.getWidth();
+                this.baseScale = width / this.imageEl.OriginWidth;
+            }
+            
+        }
+
+        if(this.imageEl.OriginWidth < this.minWidth || this.imageEl.OriginHeight < this.minHeight) {
+            this.baseScale = width / this.minWidth;
+        }
+
+        return;
+    },
+    
+    getScaleLevel : function()
+    {
+        return this.baseScale * Math.pow(1.02, this.scale);
+    },
+    
+    onTouchStart : function(e)
+    {
+        if(!this.canvasLoaded){
+            this.beforeSelectFile(e);
+            return;
+        }
+        
+        var touches = e.browserEvent.touches;
+        
+        if(!touches){
+            return;
+        }
+        
+        if(touches.length == 1){
+            this.onMouseDown(e);
+            return;
+        }
+        
+        if(touches.length != 2){
+            return;
+        }
+        
+        var coords = [];
+        
+        for(var i = 0, finger; finger = touches[i]; i++){
+            coords.push(finger.pageX, finger.pageY);
+        }
+        
+        var x = Math.pow(coords[0] - coords[2], 2);
+        var y = Math.pow(coords[1] - coords[3], 2);
+        
+        this.startDistance = Math.sqrt(x + y);
+        
+        this.startScale = this.scale;
+        
+        this.pinching = true;
+        this.dragable = false;
+        
+    },
+    
+    onTouchMove : function(e)
+    {
+        if(!this.pinching && !this.dragable){
+            return;
+        }
+        
+        var touches = e.browserEvent.touches;
+        
+        if(!touches){
+            return;
+        }
+        
+        if(this.dragable){
+            this.onMouseMove(e);
+            return;
+        }
+        
+        var coords = [];
+        
+        for(var i = 0, finger; finger = touches[i]; i++){
+            coords.push(finger.pageX, finger.pageY);
+        }
+        
+        var x = Math.pow(coords[0] - coords[2], 2);
+        var y = Math.pow(coords[1] - coords[3], 2);
+        
+        this.endDistance = Math.sqrt(x + y);
+        
+        this.scale = this.startScale + Math.floor(Math.log(this.endDistance / this.startDistance) / Math.log(1.1));
+        
+        if(!this.zoomable()){
+            this.scale = this.startScale;
+            return;
+        }
+        
+        this.draw();
+        
+    },
+    
+    onTouchEnd : function(e)
+    {
+        this.pinching = false;
+        this.dragable = false;
+        
+    },
+    
+    process : function(file, crop)
+    {
+        if(this.loadMask){
+            this.maskEl.mask(this.loadingText);
+        }
+        
+        this.xhr = new XMLHttpRequest();
+        
+        file.xhr = this.xhr;
+
+        this.xhr.open(this.method, this.url, true);
+        
+        var headers = {
+            "Accept": "application/json",
+            "Cache-Control": "no-cache",
+            "X-Requested-With": "XMLHttpRequest"
+        };
+        
+        for (var headerName in headers) {
+            var headerValue = headers[headerName];
+            if (headerValue) {
+                this.xhr.setRequestHeader(headerName, headerValue);
+            }
+        }
+        
+        var _this = this;
+        
+        this.xhr.onload = function()
+        {
+            _this.xhrOnLoad(_this.xhr);
+        }
+        
+        this.xhr.onerror = function()
+        {
+            _this.xhrOnError(_this.xhr);
+        }
+        
+        var formData = new FormData();
+
+        formData.append('returnHTML', 'NO');
+
+        if(crop){
+            formData.append('crop', crop);
+            var blobBin = atob(crop.split(',')[1]);
+            var array = [];
+            for(var i = 0; i < blobBin.length; i++) {
+                array.push(blobBin.charCodeAt(i));
+            }
+            var croppedFile =new Blob([new Uint8Array(array)], {type: this.cropType});
+            formData.append(this.paramName, croppedFile, file.name);
+        }
+        
+        if(typeof(file.filename) != 'undefined'){
+            formData.append('filename', file.filename);
+        }
+        
+        if(typeof(file.mimetype) != 'undefined'){
+            formData.append('mimetype', file.mimetype);
+        }
+
+        if(this.fireEvent('arrange', this, formData) != false){
+            this.xhr.send(formData);
+        };
+    },
+    
+    xhrOnLoad : function(xhr)
+    {
+        if(this.loadMask){
+            this.maskEl.unmask();
+        }
+        
+        if (xhr.readyState !== 4) {
+            this.fireEvent('exception', this, xhr);
+            return;
+        }
+
+        var response = Roo.decode(xhr.responseText);
+        
+        if(!response.success){
+            this.fireEvent('exception', this, xhr);
+            return;
+        }
+        
+        var response = Roo.decode(xhr.responseText);
+        
+        this.fireEvent('upload', this, response);
+        
+    },
+    
+    xhrOnError : function()
+    {
+        if(this.loadMask){
+            this.maskEl.unmask();
+        }
+        
+        Roo.log('xhr on error');
+        
+        var response = Roo.decode(xhr.responseText);
+          
+        Roo.log(response);
+        
+    },
+    
+    prepare : function(file)
+    {   
+        if(this.loadMask){
+            this.maskEl.mask(this.loadingText);
+        }
+        
+        this.file = false;
+        this.exif = {};
+        
+        if(typeof(file) === 'string'){
+            this.loadCanvas(file);
+            return;
+        }
+        
+        if(!file || !this.urlAPI){
+            return;
+        }
+        
+        this.file = file;
+        if(typeof(file.type) != 'undefined' && file.type.length != 0) {
+            this.cropType = file.type;
+        }
+        
+        var _this = this;
+        
+        if(this.fireEvent('prepare', this, this.file) != false){
+            
+            var reader = new FileReader();
+            
+            reader.onload = function (e) {
+                if (e.target.error) {
+                    Roo.log(e.target.error);
+                    return;
+                }
+                
+                var buffer = e.target.result,
+                    dataView = new DataView(buffer),
+                    offset = 2,
+                    maxOffset = dataView.byteLength - 4,
+                    markerBytes,
+                    markerLength;
+                
+                if (dataView.getUint16(0) === 0xffd8) {
+                    while (offset < maxOffset) {
+                        markerBytes = dataView.getUint16(offset);
+                        
+                        if ((markerBytes >= 0xffe0 && markerBytes <= 0xffef) || markerBytes === 0xfffe) {
+                            markerLength = dataView.getUint16(offset + 2) + 2;
+                            if (offset + markerLength > dataView.byteLength) {
+                                Roo.log('Invalid meta data: Invalid segment size.');
+                                break;
+                            }
+                            
+                            if(markerBytes == 0xffe1){
+                                _this.parseExifData(
+                                    dataView,
+                                    offset,
+                                    markerLength
+                                );
+                            }
+                            
+                            offset += markerLength;
+                            
+                            continue;
+                        }
+                        
+                        break;
+                    }
+                    
+                }
+                
+                var url = _this.urlAPI.createObjectURL(_this.file);
+                
+                _this.loadCanvas(url);
+                
+                return;
+            }
+            
+            reader.readAsArrayBuffer(this.file);
+            
+        }
+        
+    },
+    
+    parseExifData : function(dataView, offset, length)
+    {
+        var tiffOffset = offset + 10,
+            littleEndian,
+            dirOffset;
+    
+        if (dataView.getUint32(offset + 4) !== 0x45786966) {
+            // No Exif data, might be XMP data instead
+            return;
+        }
+        
+        // Check for the ASCII code for "Exif" (0x45786966):
+        if (dataView.getUint32(offset + 4) !== 0x45786966) {
+            // No Exif data, might be XMP data instead
+            return;
+        }
+        if (tiffOffset + 8 > dataView.byteLength) {
+            Roo.log('Invalid Exif data: Invalid segment size.');
+            return;
+        }
+        // Check for the two null bytes:
+        if (dataView.getUint16(offset + 8) !== 0x0000) {
+            Roo.log('Invalid Exif data: Missing byte alignment offset.');
+            return;
+        }
+        // Check the byte alignment:
+        switch (dataView.getUint16(tiffOffset)) {
+        case 0x4949:
+            littleEndian = true;
+            break;
+        case 0x4D4D:
+            littleEndian = false;
+            break;
+        default:
+            Roo.log('Invalid Exif data: Invalid byte alignment marker.');
+            return;
+        }
+        // Check for the TIFF tag marker (0x002A):
+        if (dataView.getUint16(tiffOffset + 2, littleEndian) !== 0x002A) {
+            Roo.log('Invalid Exif data: Missing TIFF marker.');
+            return;
+        }
+        // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal:
+        dirOffset = dataView.getUint32(tiffOffset + 4, littleEndian);
+        
+        this.parseExifTags(
+            dataView,
+            tiffOffset,
+            tiffOffset + dirOffset,
+            littleEndian
+        );
+    },
+    
+    parseExifTags : function(dataView, tiffOffset, dirOffset, littleEndian)
+    {
+        var tagsNumber,
+            dirEndOffset,
+            i;
+        if (dirOffset + 6 > dataView.byteLength) {
+            Roo.log('Invalid Exif data: Invalid directory offset.');
+            return;
+        }
+        tagsNumber = dataView.getUint16(dirOffset, littleEndian);
+        dirEndOffset = dirOffset + 2 + 12 * tagsNumber;
+        if (dirEndOffset + 4 > dataView.byteLength) {
+            Roo.log('Invalid Exif data: Invalid directory size.');
+            return;
+        }
+        for (i = 0; i < tagsNumber; i += 1) {
+            this.parseExifTag(
+                dataView,
+                tiffOffset,
+                dirOffset + 2 + 12 * i, // tag offset
+                littleEndian
+            );
+        }
+        // Return the offset to the next directory:
+        return dataView.getUint32(dirEndOffset, littleEndian);
+    },
+    
+    parseExifTag : function (dataView, tiffOffset, offset, littleEndian) 
+    {
+        var tag = dataView.getUint16(offset, littleEndian);
+        
+        this.exif[tag] = this.getExifValue(
+            dataView,
+            tiffOffset,
+            offset,
+            dataView.getUint16(offset + 2, littleEndian), // tag type
+            dataView.getUint32(offset + 4, littleEndian), // tag length
+            littleEndian
+        );
+    },
+    
+    getExifValue : function (dataView, tiffOffset, offset, type, length, littleEndian)
+    {
+        var tagType = Roo.panel.Cropbox.exifTagTypes[type],
+            tagSize,
+            dataOffset,
+            values,
+            i,
+            str,
+            c;
+    
+        if (!tagType) {
+            Roo.log('Invalid Exif data: Invalid tag type.');
+            return;
+        }
+        
+        tagSize = tagType.size * length;
+        // Determine if the value is contained in the dataOffset bytes,
+        // or if the value at the dataOffset is a pointer to the actual data:
+        dataOffset = tagSize > 4 ?
+                tiffOffset + dataView.getUint32(offset + 8, littleEndian) : (offset + 8);
+        if (dataOffset + tagSize > dataView.byteLength) {
+            Roo.log('Invalid Exif data: Invalid data offset.');
+            return;
+        }
+        if (length === 1) {
+            return tagType.getValue(dataView, dataOffset, littleEndian);
+        }
+        values = [];
+        for (i = 0; i < length; i += 1) {
+            values[i] = tagType.getValue(dataView, dataOffset + i * tagType.size, littleEndian);
+        }
+        
+        if (tagType.ascii) {
+            str = '';
+            // Concatenate the chars:
+            for (i = 0; i < values.length; i += 1) {
+                c = values[i];
+                // Ignore the terminating NULL byte(s):
+                if (c === '\u0000') {
+                    break;
+                }
+                str += c;
+            }
+            return str;
+        }
+        return values;
+    }
+    
+});
+
+Roo.apply(Roo.panel.Cropbox, {
+    tags : {
+        'Orientation': 0x0112
+    },
+    
+    Orientation: {
+            1: 0, //'top-left',
+//            2: 'top-right',
+            3: 180, //'bottom-right',
+//            4: 'bottom-left',
+//            5: 'left-top',
+            6: 90, //'right-top',
+//            7: 'right-bottom',
+            8: 270 //'left-bottom'
+    },
+    
+    exifTagTypes : {
+        // byte, 8-bit unsigned int:
+        1: {
+            getValue: function (dataView, dataOffset) {
+                return dataView.getUint8(dataOffset);
+            },
+            size: 1
+        },
+        // ascii, 8-bit byte:
+        2: {
+            getValue: function (dataView, dataOffset) {
+                return String.fromCharCode(dataView.getUint8(dataOffset));
+            },
+            size: 1,
+            ascii: true
+        },
+        // short, 16 bit int:
+        3: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getUint16(dataOffset, littleEndian);
+            },
+            size: 2
+        },
+        // long, 32 bit int:
+        4: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getUint32(dataOffset, littleEndian);
+            },
+            size: 4
+        },
+        // rational = two long values, first is numerator, second is denominator:
+        5: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getUint32(dataOffset, littleEndian) /
+                    dataView.getUint32(dataOffset + 4, littleEndian);
+            },
+            size: 8
+        },
+        // slong, 32 bit signed int:
+        9: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getInt32(dataOffset, littleEndian);
+            },
+            size: 4
+        },
+        // srational, two slongs, first is numerator, second is denominator:
+        10: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getInt32(dataOffset, littleEndian) /
+                    dataView.getInt32(dataOffset + 4, littleEndian);
+            },
+            size: 8
+        }
+    },
+    
+    footer : {
+        STANDARD : [
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-left',
+                action : 'rotate-left',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-undo"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-picture',
+                action : 'picture',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-picture-o"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-right',
+                action : 'rotate-right',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-repeat"></i>'
+                    }
+                ]
+            }
+        ],
+        DOCUMENT : [
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-left',
+                action : 'rotate-left',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-undo"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-download',
+                action : 'download',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-download"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-crop',
+                action : 'crop',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-crop"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-trash',
+                action : 'trash',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-trash"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-right',
+                action : 'rotate-right',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-repeat"></i>'
+                    }
+                ]
+            }
+        ],
+        ROTATOR : [
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-left',
+                action : 'rotate-left',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-undo"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-right',
+                action : 'rotate-right',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-repeat"></i>'
+                    }
+                ]
+            }
+        ],
+        CENTER : [
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-center',
+                action : 'center',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : 'CENTER'
+                    }
+                ]
+            }
+        ]
+    }
+});
+        /*
  * Based on:
  * Ext JS Library 1.1.1
  * Copyright(c) 2006-2007, Ext JS, LLC.
@@ -29942,20 +31878,20 @@ Roo.extend(Roo.DatePicker, Roo.Component, {
  * <script type="text/javascript">
  */
 /**
- * @class Roo.TabPanel
+ * @class Roo.panel.Tab
  * @extends Roo.util.Observable
  * A lightweight tab container.
  * <br><br>
  * Usage:
  * <pre><code>
 // basic tabs 1, built from existing content
-var tabs = new Roo.TabPanel("tabs1");
+var tabs = new Roo.panel.Tab("tabs1");
 tabs.addTab("script", "View Script");
 tabs.addTab("markup", "View Markup");
 tabs.activate("script");
 
 // more advanced tabs, built from javascript
-var jtabs = new Roo.TabPanel("jtabs");
+var jtabs = new Roo.panel.Tab("jtabs");
 jtabs.addTab("jtabs-1", "Normal Tab", "My content was added during construction.");
 
 // set up the UpdateManager
@@ -29979,7 +31915,7 @@ jtabs.activate("jtabs-1");
  * @param {String/HTMLElement/Roo.Element} container The id, DOM element or Roo.Element container where this TabPanel is to be rendered.
  * @param {Object/Boolean} config Config object to set any properties for this TabPanel, or true to render the tabs on the bottom.
  */
-Roo.TabPanel = function(container, config){
+Roo.panel.Tab = function(container, config){
     /**
     * The container element for this TabPanel.
     * @type Roo.Element
@@ -30003,7 +31939,7 @@ Roo.TabPanel = function(container, config){
         Roo.fly(this.stripWrap.dom.firstChild).setStyle("overflow-x", "hidden");
     }
     if(this.tabPosition != "bottom"){
-        /** The body element that contains {@link Roo.TabPanelItem} bodies. +
+        /** The body element that contains {@link Roo.panel.TabItem} bodies. +
          * @type Roo.Element
          */
         this.bodyEl = Roo.get(this.createBody(this.el.dom));
@@ -30020,16 +31956,16 @@ Roo.TabPanel = function(container, config){
         /**
          * @event tabchange
          * Fires when the active tab changes
-         * @param {Roo.TabPanel} this
-         * @param {Roo.TabPanelItem} activePanel The new active tab
+         * @param {Roo.panel.Tab} this
+         * @param {Roo.panel.TabItem} activePanel The new active tab
          */
         "tabchange": true,
         /**
          * @event beforetabchange
          * Fires before the active tab changes, set cancel to true on the "e" parameter to cancel the change
-         * @param {Roo.TabPanel} this
+         * @param {Roo.panel.Tab} this
          * @param {Object} e Set cancel to true on this object to cancel the tab change
-         * @param {Roo.TabPanelItem} tab The tab being changed to
+         * @param {Roo.panel.TabItem} tab The tab being changed to
          */
         "beforetabchange" : true
     });
@@ -30053,10 +31989,10 @@ Roo.TabPanel = function(container, config){
    
 
 
-    Roo.TabPanel.superclass.constructor.call(this);
+    Roo.panel.Tab.superclass.constructor.call(this);
 };
 
-Roo.extend(Roo.TabPanel, Roo.util.Observable, {
+Roo.extend(Roo.panel.Tab, Roo.util.Observable, {
     /*
      *@cfg {String} tabPosition "top" or "bottom" (defaults to "top")
      */
@@ -30091,15 +32027,15 @@ Roo.extend(Roo.TabPanel, Roo.util.Observable, {
     toolbar : false,
 
     /**
-     * Creates a new {@link Roo.TabPanelItem} by looking for an existing element with the provided id -- if it's not found it creates one.
+     * Creates a new {@link Roo.panel.TabItem} by looking for an existing element with the provided id -- if it's not found it creates one.
      * @param {String} id The id of the div to use <b>or create</b>
      * @param {String} text The text for the tab
      * @param {String} content (optional) Content to put in the TabPanelItem body
      * @param {Boolean} closable (optional) True to create a close icon on the tab
-     * @return {Roo.TabPanelItem} The created TabPanelItem
+     * @return {Roo.panel.TabItem} The created TabPanelItem
      */
     addTab : function(id, text, content, closable){
-        var item = new Roo.TabPanelItem(this, id, text, closable);
+        var item = new Roo.panel.TabItem(this, id, text, closable);
         this.addTabItem(item);
         if(content){
             item.setContent(content);
@@ -30108,16 +32044,16 @@ Roo.extend(Roo.TabPanel, Roo.util.Observable, {
     },
 
     /**
-     * Returns the {@link Roo.TabPanelItem} with the specified id/index
+     * Returns the {@link Roo.panel.TabItem} with the specified id/index
      * @param {String/Number} id The id or index of the TabPanelItem to fetch.
-     * @return {Roo.TabPanelItem}
+     * @return {Roo.panel.TabItem}
      */
     getTab : function(id){
         return this.items[id];
     },
 
     /**
-     * Hides the {@link Roo.TabPanelItem} with the specified id/index
+     * Hides the {@link Roo.panel.TabItem} with the specified id/index
      * @param {String/Number} id The id or index of the TabPanelItem to hide.
      */
     hideTab : function(id){
@@ -30130,7 +32066,7 @@ Roo.extend(Roo.TabPanel, Roo.util.Observable, {
     },
 
     /**
-     * "Unhides" the {@link Roo.TabPanelItem} with the specified id/index.
+     * "Unhides" the {@link Roo.panel.TabItem} with the specified id/index.
      * @param {String/Number} id The id or index of the TabPanelItem to unhide.
      */
     unhideTab : function(id){
@@ -30143,8 +32079,8 @@ Roo.extend(Roo.TabPanel, Roo.util.Observable, {
     },
 
     /**
-     * Adds an existing {@link Roo.TabPanelItem}.
-     * @param {Roo.TabPanelItem} item The TabPanelItem to add
+     * Adds an existing {@link Roo.panel.TabItem}.
+     * @param {Roo.panel.TabItem} item The TabPanelItem to add
      */
     addTabItem : function(item){
         this.items[item.id] = item;
@@ -30158,7 +32094,7 @@ Roo.extend(Roo.TabPanel, Roo.util.Observable, {
     },
 
     /**
-     * Removes a {@link Roo.TabPanelItem}.
+     * Removes a {@link Roo.panel.TabItem}.
      * @param {String/Number} id The id or index of the TabPanelItem to remove.
      */
     removeTab : function(id){
@@ -30206,7 +32142,7 @@ Roo.extend(Roo.TabPanel, Roo.util.Observable, {
     },
 
     /**
-     * Disables a {@link Roo.TabPanelItem}. It cannot be the active tab, if it is this call is ignored.
+     * Disables a {@link Roo.panel.TabItem}. It cannot be the active tab, if it is this call is ignored.
      * @param {String/Number} id The id or index of the TabPanelItem to disable.
      */
     disableTab : function(id){
@@ -30217,7 +32153,7 @@ Roo.extend(Roo.TabPanel, Roo.util.Observable, {
     },
 
     /**
-     * Enables a {@link Roo.TabPanelItem} that is disabled.
+     * Enables a {@link Roo.panel.TabItem} that is disabled.
      * @param {String/Number} id The id or index of the TabPanelItem to enable.
      */
     enableTab : function(id){
@@ -30226,9 +32162,9 @@ Roo.extend(Roo.TabPanel, Roo.util.Observable, {
     },
 
     /**
-     * Activates a {@link Roo.TabPanelItem}. The currently active one will be deactivated.
+     * Activates a {@link Roo.panel.TabItem}. The currently active one will be deactivated.
      * @param {String/Number} id The id or index of the TabPanelItem to activate.
-     * @return {Roo.TabPanelItem} The TabPanelItem.
+     * @return {Roo.panel.TabItem} The TabPanelItem.
      */
     activate : function(id){
         var tab = this.items[id];
@@ -30252,8 +32188,8 @@ Roo.extend(Roo.TabPanel, Roo.util.Observable, {
     },
 
     /**
-     * Gets the active {@link Roo.TabPanelItem}.
-     * @return {Roo.TabPanelItem} The active TabPanelItem or null if none are active.
+     * Gets the active {@link Roo.panel.TabItem}.
+     * @return {Roo.panel.TabItem} The active TabPanelItem or null if none are active.
      */
     getActiveTab : function(){
         return this.active;
@@ -30359,19 +32295,77 @@ Roo.extend(Roo.TabPanel, Roo.util.Observable, {
     }
 });
 
-/**
- * @class Roo.TabPanelItem
+
+/** @private */
+Roo.panel.Tab.prototype.createStripList = function(strip){
+    // div wrapper for retard IE
+    // returns the "tr" element.
+    strip.innerHTML = '<div class="x-tabs-strip-wrap">'+
+        '<table class="x-tabs-strip" cellspacing="0" cellpadding="0" border="0"><tbody><tr>'+
+        '<td class="x-tab-strip-toolbar"></td></tr></tbody></table></div>';
+    return strip.firstChild.firstChild.firstChild.firstChild;
+};
+/** @private */
+Roo.panel.Tab.prototype.createBody = function(container){
+    var body = document.createElement("div");
+    Roo.id(body, "tab-body");
+    Roo.fly(body).addClass("x-tabs-body");
+    container.appendChild(body);
+    return body;
+};
+/** @private */
+Roo.panel.Tab.prototype.createItemBody = function(bodyEl, id){
+    var body = Roo.getDom(id);
+    if(!body){
+        body = document.createElement("div");
+        body.id = id;
+    }
+    Roo.fly(body).addClass("x-tabs-item-body");
+    bodyEl.insertBefore(body, bodyEl.firstChild);
+    return body;
+};
+/** @private */
+Roo.panel.Tab.prototype.createStripElements = function(stripEl, text, closable){
+    var td = document.createElement("td");
+    stripEl.insertBefore(td, stripEl.childNodes[stripEl.childNodes.length-1]);
+    //stripEl.appendChild(td);
+    if(closable){
+        td.className = "x-tabs-closable";
+        if(!this.closeTpl){
+            this.closeTpl = new Roo.Template(
+               '<a href="#" class="x-tabs-right"><span class="x-tabs-left"><em class="x-tabs-inner">' +
+               '<span unselectable="on"' + (this.disableTooltips ? '' : ' title="{text}"') +' class="x-tabs-text">{text}</span>' +
+               '<div unselectable="on" class="close-icon">&#160;</div></em></span></a>'
+            );
+        }
+        var el = this.closeTpl.overwrite(td, {"text": text});
+        var close = el.getElementsByTagName("div")[0];
+        var inner = el.getElementsByTagName("em")[0];
+        return {"el": el, "close": close, "inner": inner};
+    } else {
+        if(!this.tabTpl){
+            this.tabTpl = new Roo.Template(
+               '<a href="#" class="x-tabs-right"><span class="x-tabs-left"><em class="x-tabs-inner">' +
+               '<span unselectable="on"' + (this.disableTooltips ? '' : ' title="{text}"') +' class="x-tabs-text">{text}</span></em></span></a>'
+            );
+        }
+        var el = this.tabTpl.overwrite(td, {"text": text});
+        var inner = el.getElementsByTagName("em")[0];
+        return {"el": el, "inner": inner};
+    }
+};/**
+ * @class Roo.panel.TabItem
  * @extends Roo.util.Observable
  * Represents an individual item (tab plus body) in a TabPanel.
- * @param {Roo.TabPanel} tabPanel The {@link Roo.TabPanel} this TabPanelItem belongs to
+ * @param {Roo.panel.Tab} tabPanel The {@link Roo.panel.Tab} this TabPanelItem belongs to
  * @param {String} id The id of this TabPanelItem
  * @param {String} text The text for the tab of this TabPanelItem
  * @param {Boolean} closable True to allow this TabPanelItem to be closable (defaults to false)
  */
-Roo.TabPanelItem = function(tabPanel, id, text, closable){
+ Roo.panel.TabItem = function(tabPanel, id, text, closable){
     /**
-     * The {@link Roo.TabPanel} this TabPanelItem belongs to
-     * @type Roo.TabPanel
+     * The {@link Roo.panel.Tab} this TabPanelItem belongs to
+     * @type Roo.panel.Tab
      */
     this.tabPanel = tabPanel;
     /**
@@ -30417,37 +32411,37 @@ Roo.TabPanelItem = function(tabPanel, id, text, closable){
          /**
          * @event activate
          * Fires when this tab becomes the active tab.
-         * @param {Roo.TabPanel} tabPanel The parent TabPanel
-         * @param {Roo.TabPanelItem} this
+         * @param {Roo.panel.Tab} tabPanel The parent TabPanel
+         * @param {Roo.panel.TabItem} this
          */
         "activate": true,
         /**
          * @event beforeclose
          * Fires before this tab is closed. To cancel the close, set cancel to true on e (e.cancel = true).
-         * @param {Roo.TabPanelItem} this
+         * @param {Roo.panel.TabItem} this
          * @param {Object} e Set cancel to true on this object to cancel the close.
          */
         "beforeclose": true,
         /**
          * @event close
          * Fires when this tab is closed.
-         * @param {Roo.TabPanelItem} this
+         * @param {Roo.panel.TabItem} this
          */
          "close": true,
         /**
          * @event deactivate
          * Fires when this tab is no longer the active tab.
-         * @param {Roo.TabPanel} tabPanel The parent TabPanel
-         * @param {Roo.TabPanelItem} this
+         * @param {Roo.panel.Tab} tabPanel The parent TabPanel
+         * @param {Roo.panel.TabItem} this
          */
          "deactivate" : true
     });
     this.hidden = false;
 
-    Roo.TabPanelItem.superclass.constructor.call(this);
+    Roo.panel.TabItem.superclass.constructor.call(this);
 };
 
-Roo.extend(Roo.TabPanelItem, Roo.util.Observable, {
+Roo.extend(Roo.panel.TabItem, Roo.util.Observable, {
     purgeListeners : function(){
        Roo.util.Observable.prototype.purgeListeners.call(this);
        this.el.removeAllListeners();
@@ -30677,69 +32671,11 @@ Roo.extend(Roo.TabPanelItem, Roo.util.Observable, {
 });
 
 /** @private */
-Roo.TabPanel.prototype.createStrip = function(container){
+Roo.panel.Tab.prototype.createStrip = function(container){
     var strip = document.createElement("div");
     strip.className = "x-tabs-wrap";
     container.appendChild(strip);
     return strip;
-};
-/** @private */
-Roo.TabPanel.prototype.createStripList = function(strip){
-    // div wrapper for retard IE
-    // returns the "tr" element.
-    strip.innerHTML = '<div class="x-tabs-strip-wrap">'+
-        '<table class="x-tabs-strip" cellspacing="0" cellpadding="0" border="0"><tbody><tr>'+
-        '<td class="x-tab-strip-toolbar"></td></tr></tbody></table></div>';
-    return strip.firstChild.firstChild.firstChild.firstChild;
-};
-/** @private */
-Roo.TabPanel.prototype.createBody = function(container){
-    var body = document.createElement("div");
-    Roo.id(body, "tab-body");
-    Roo.fly(body).addClass("x-tabs-body");
-    container.appendChild(body);
-    return body;
-};
-/** @private */
-Roo.TabPanel.prototype.createItemBody = function(bodyEl, id){
-    var body = Roo.getDom(id);
-    if(!body){
-        body = document.createElement("div");
-        body.id = id;
-    }
-    Roo.fly(body).addClass("x-tabs-item-body");
-    bodyEl.insertBefore(body, bodyEl.firstChild);
-    return body;
-};
-/** @private */
-Roo.TabPanel.prototype.createStripElements = function(stripEl, text, closable){
-    var td = document.createElement("td");
-    stripEl.insertBefore(td, stripEl.childNodes[stripEl.childNodes.length-1]);
-    //stripEl.appendChild(td);
-    if(closable){
-        td.className = "x-tabs-closable";
-        if(!this.closeTpl){
-            this.closeTpl = new Roo.Template(
-               '<a href="#" class="x-tabs-right"><span class="x-tabs-left"><em class="x-tabs-inner">' +
-               '<span unselectable="on"' + (this.disableTooltips ? '' : ' title="{text}"') +' class="x-tabs-text">{text}</span>' +
-               '<div unselectable="on" class="close-icon">&#160;</div></em></span></a>'
-            );
-        }
-        var el = this.closeTpl.overwrite(td, {"text": text});
-        var close = el.getElementsByTagName("div")[0];
-        var inner = el.getElementsByTagName("em")[0];
-        return {"el": el, "close": close, "inner": inner};
-    } else {
-        if(!this.tabTpl){
-            this.tabTpl = new Roo.Template(
-               '<a href="#" class="x-tabs-right"><span class="x-tabs-left"><em class="x-tabs-inner">' +
-               '<span unselectable="on"' + (this.disableTooltips ? '' : ' title="{text}"') +' class="x-tabs-text">{text}</span></em></span></a>'
-            );
-        }
-        var el = this.tabTpl.overwrite(td, {"text": text});
-        var inner = el.getElementsByTagName("em")[0];
-        return {"el": el, "inner": inner};
-    }
 };/*
  * Based on:
  * Ext JS Library 1.1.1
@@ -31111,7 +33047,23 @@ Roo.extend(Roo.Button, Roo.util.Observable, {
             this.hide();
         }
     },
-    
+    /**
+        * Similar to toggle, but does not trigger event.
+        * @param {Boolean} state [required] Force a particular state
+        */
+       setPressed : function(state)
+       {
+           if(state != this.pressed){
+            if(state){
+                this.el.addClass("x-btn-pressed");
+                this.pressed = true;
+            }else{
+                this.el.removeClass("x-btn-pressed");
+                this.pressed = false;
+            }
+        }
+       },
+       
     /**
      * If a state it passed, it becomes the pressed state otherwise the current state is toggled.
      * @param {Boolean} state (optional) Force a particular state
@@ -31134,6 +33086,8 @@ Roo.extend(Roo.Button, Roo.util.Observable, {
         }
     },
     
+       
+       
     /**
      * Focus the button
      */
@@ -33820,7 +35774,7 @@ Roo.extend(Roo.BasicDialog, Roo.util.Observable, {
 
     /**
      * Reinitializes the tabs component, clearing out old tabs and finding new ones.
-     * @return {Roo.TabPanel} The tabs component
+     * @return {Roo.panel.Tab} The tabs component
      */
     initTabs : function(){
         var tabs = this.getTabs();
@@ -33941,16 +35895,16 @@ Roo.extend(Roo.BasicDialog, Roo.util.Observable, {
     },
 
     /**
-     * Returns the TabPanel component (creates it if it doesn't exist).
+     * Returns the panel.Tab component (creates it if it doesn't exist).
      * Note: If you wish to simply check for the existence of tabs without creating them,
      * check for a null 'tabs' property.
-     * @return {Roo.TabPanel} The tabs component
+     * @return {Roo.panel.Tab} The tabs component
      */
     getTabs : function(){
         if(!this.tabs){
             this.el.addClass("x-dlg-auto-tabs");
             this.body.addClass(this.tabPosition == "bottom" ? "x-tabs-bottom" : "x-tabs-top");
-            this.tabs = new Roo.TabPanel(this.body.dom, this.tabPosition == "bottom");
+            this.tabs = new Roo.panel.Tab(this.body.dom, this.tabPosition == "bottom");
         }
         return this.tabs;
     },
@@ -34607,7 +36561,7 @@ Roo.DialogManager = function(){
 /**
  * @class Roo.LayoutDialog
  * @extends Roo.BasicDialog
- * @children Roo.ContentPanel
+ * @children Roo.panel.Content
  * @parent builder none
  * Dialog which provides adjustments for working with a layout in a Dialog.
  * Add your necessary layout config options to the dialog's config.<br>
@@ -34634,7 +36588,7 @@ if(!dialog){
     dialog.addButton("Build It!", this.getDownload, this);
 
     // we can even add nested layouts
-    var innerLayout = new Roo.BorderLayout("dl-inner", {
+    var innerLayout = new Roo.layout.Border("dl-inner", {
         east: {
             initialSize: 200,
             autoScroll:true,
@@ -34645,15 +36599,15 @@ if(!dialog){
         }
     });
     innerLayout.beginUpdate();
-    innerLayout.add("east", new Roo.ContentPanel("dl-details"));
-    innerLayout.add("center", new Roo.ContentPanel("selection-panel"));
+    innerLayout.add("east", new Roo.panel.Content("dl-details"));
+    innerLayout.add("center", new Roo.panel.Content("selection-panel"));
     innerLayout.endUpdate(true);
 
     var layout = dialog.getLayout();
     layout.beginUpdate();
-    layout.add("center", new Roo.ContentPanel("standard-panel",
+    layout.add("center", new Roo.panel.Content("standard-panel",
                         {title: "Download the Source", fitToFrame:true}));
-    layout.add("center", new Roo.NestedLayoutPanel(innerLayout,
+    layout.add("center", new Roo.panel.NestedLayout(innerLayout,
                {title: "Build your own roo.js"}));
     layout.getRegion("center").showPanel(sp);
     layout.endUpdate();
@@ -34679,7 +36633,7 @@ Roo.LayoutDialog = function(el, cfg){
     config.autoTabs = false;
     Roo.LayoutDialog.superclass.constructor.call(this, el, config);
     this.body.setStyle({overflow:"hidden", position:"relative"});
-    this.layout = new Roo.BorderLayout(this.body.dom, config);
+    this.layout = new Roo.layout.Border(this.body.dom, config);
     this.layout.monitorWindowResize = false;
     this.el.addClass("x-dlg-auto-layout");
     // fix case when center region overwrites center function
@@ -34697,19 +36651,19 @@ Roo.extend(Roo.LayoutDialog, Roo.BasicDialog, {
     
     
     /**
-     * @cfg {Roo.LayoutRegion} east  
+     * @cfg {Roo.layout.Region} east  
      */
     /**
-     * @cfg {Roo.LayoutRegion} west
+     * @cfg {Roo.layout.Region} west
      */
     /**
-     * @cfg {Roo.LayoutRegion} south
+     * @cfg {Roo.layout.Region} south
      */
     /**
-     * @cfg {Roo.LayoutRegion} north
+     * @cfg {Roo.layout.Region} north
      */
     /**
-     * @cfg {Roo.LayoutRegion} center
+     * @cfg {Roo.layout.Region} center
      */
     /**
      * @cfg {Roo.Button} buttons[]  Bottom buttons..
@@ -34734,7 +36688,7 @@ Roo.extend(Roo.LayoutDialog, Roo.BasicDialog, {
 
     /**
      * Get the BorderLayout for this dialog
-     * @return {Roo.BorderLayout}
+     * @return {Roo.layout.Border}
      */
     getLayout : function(){
         return this.layout;
@@ -40493,6 +42447,9 @@ Roo.form.Field = function(config){
 Roo.extend(Roo.form.Field, Roo.BoxComponent,  {
     /**
      * @cfg {String} fieldLabel Label to use when rendering a form.
+     */
+       /**
+     * @cfg {String} labelSeparator the ':' after a field label (default :)  = set it to empty string to hide the field label.
      */
        /**
      * @cfg {String} qtip Mouse over tip
@@ -41182,9 +43139,9 @@ Roo.extend(Roo.form.TextField, Roo.form.Field,  {
         if(this.selectOnFocus){
             this.on("focus", this.preFocus, this);
         }
-       if (!this.allowLeadingSpace) {
-           this.on('blur', this.cleanLeadingSpace, this);
-       }
+               if (!this.allowLeadingSpace) {
+                       this.on('blur', this.cleanLeadingSpace, this);
+               }
        
         if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Roo.form.VTypes[this.vtype+'Mask']))){
             this.el.on("keypress", this.filterKeys, this);
@@ -41295,6 +43252,11 @@ Roo.extend(Roo.form.TextField, Roo.form.Field,  {
         }
         if(this.vtype){
             var vt = Roo.form.VTypes;
+                       if (value.trim() != value) { // trim before checking email (and other stuf??)
+                               value = value.trim();
+                               this.el.dom.value  = value;
+                       }
+                       
             if(!vt[this.vtype](value, this)){
                 this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
                 return false;
@@ -41375,7 +43337,8 @@ Roo.extend(Roo.form.TextField, Roo.form.Field,  {
             return;
         }
         
-        if(isSelectAll && event.getCharCode() > 31){ // backspace and delete key
+        // skip handling paste
+        if(isSelectAll && event.getCharCode() > 31 && !(event.ctrlKey && event.getCharCode() == 86)){ // backspace and delete key
             
             event.preventDefault();
             // this is very hacky as keydown always get's upper case.
@@ -41388,6 +43351,60 @@ Roo.extend(Roo.form.TextField, Roo.form.Field,  {
         }
         
         
+    }
+});Roo.form.Password = function(config){
+    Roo.form.Password.superclass.constructor.call(this, config);
+
+    this.inputType = 'password';
+};
+
+Roo.extend(Roo.form.Password, Roo.form.TextField,  {
+    onRender : function(ct, position)
+    {
+        Roo.form.Password.superclass.onRender.call(this, ct, position);
+
+        this.parentEl().addClass('form-password');
+
+        this.wrap = this.el.wrap({
+            cls : 'password-wrap'
+        });
+
+        this.toggle = this.wrap.createChild({
+            tag : 'Button',
+            cls : 'password-toggle'
+        });
+
+
+        this.toggleEl().addClass('password-hidden');
+
+        this.toggleEl().on('click', this.onToggleClick, this);;
+    },
+    
+    parentEl : function()
+    {
+        return this.el.findParent('.x-form-element', 5, true);
+    },
+
+    toggleEl: function()
+    {
+        return this.parentEl().select('button.password-toggle',true).first();
+    },
+
+    onToggleClick : function(e) 
+    {
+        var input = this.el;
+        var toggle = this.toggleEl();
+
+        toggle.removeClass(['password-visible', 'password-hidden']);
+
+        if(input.attr('type') == 'password') {
+            input.attr('type', 'text');
+            toggle.addClass('password-visible');
+        }
+        else {
+            input.attr('type', 'password');
+            toggle.addClass('password-hidden');
+        }
     }
 });/*
  * Based on:
@@ -41857,6 +43874,10 @@ Roo.extend(Roo.form.NumberField, Roo.form.TextField,  {
      * @cfg {String} decimalSeparator Character(s) to allow as the decimal separator (defaults to '.')
      */
     decimalSeparator : ".",
+    /**
+     * @cfg {String} thousandSeparator Character(s) to allow as the thousand separator (defaults to '') - set to ',' for example
+     */
+    thousandSeparator : "",
     /**
      * @cfg {Number} decimalPrecision The maximum precision to display after the decimal separator (defaults to 2)
      */
@@ -41886,14 +43907,60 @@ Roo.extend(Roo.form.NumberField, Roo.form.TextField,  {
      * if a valid character like '.' or '-' is left in the field with no number (defaults to "{value} is not a valid number")
      */
     nanText : "{0} is not a valid number",
-
+    
+    hiddenField : false,
+     
+    onRender : function(ct, position)
+    {
+        Roo.form.TextField.superclass.onRender.call(this, ct, position);
+    
+            //this.el.dom.removeAttribute('name'); 
+        Roo.log("Changing name?");
+        if (this.thousandSeparator != '') {
+            this.el.dom.setAttribute('name', this.name + '____hidden___' ); 
+            this.hiddenField = this.el.insertSibling({ tag:'input', type:'hidden', name: this.name },
+                        'before', true);
+            this.hiddenField.value = this.value ? this.parseValue(this.value) : '';
+            this.el.on('blur', this.onBlur, this);
+        }
+        
+            // prevent input submission
+        
+            
+            
+    },
+     onBlur : function(){
+        this.beforeBlur();
+        if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
+            this.el.removeClass(this.focusClass);
+        }
+        this.hasFocus = false;
+        if(this.validationEvent !== false && this.validateOnBlur && this.validationEvent != "blur"){
+            this.validate();
+        }
+        var v = this.getValue();
+        if(String(v) !== String(this.startValue)){
+            this.setValue( this.parseValue(v));
+            this.fireEvent('change', this, v, this.startValue);
+        }
+        this.fireEvent("blur", this);
+    },
+    
+    // override name, so that it works with hidden field.
+    getName: function(){
+        if (this.thousandSeparator != '') {
+            return this.name;
+        }
+        return Roo.form.TextField.superclass.getName.call(this);
+    },
     // private
     initEvents : function(){
-        Roo.form.NumberField.superclass.initEvents.call(this);
+          
         var allowed = "0123456789";
         if(this.allowDecimals){
             allowed += this.decimalSeparator;
         }
+        allowed += this.thousandSeparator;
         if(this.allowNegative){
             allowed += "-";
         }
@@ -41941,7 +44008,7 @@ Roo.extend(Roo.form.NumberField, Roo.form.TextField,  {
 
     // private
     parseValue : function(value){
-        value = parseFloat(String(value).replace(this.decimalSeparator, "."));
+        value = parseFloat(String(value).replace(this.decimalSeparator, ".").split(this.thousandSeparator).join(''));
         return isNaN(value) ? '' : value;
     },
 
@@ -41956,7 +44023,15 @@ Roo.extend(Roo.form.NumberField, Roo.form.TextField,  {
 
     setValue : function(v){
         v = this.fixPrecision(v);
+        if(this.thousandSeparator != ''){
+            v = Roo.util.Format.number(v, this.decimalPrecision, this.thousandSeparator);
+        } 
         Roo.form.NumberField.superclass.setValue.call(this, String(v).replace(".", this.decimalSeparator));
+        if (this.hiddenField !== false) {
+            this.hiddenField.value = v ? this.parseValue(v) : '';
+        }
+        
+
     },
 
     // private
@@ -42313,7 +44388,7 @@ dateField.setValue('2006-5-4');
     // private
     // Implements the default empty TriggerField.onTriggerClick function to display the DatePicker
     onTriggerClick : function(){
-        if(this.disabled){
+        if(this.disabled || this.readOnly){
             return;
         }
         if(this.menu == null){
@@ -43083,7 +45158,7 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
     {
         Roo.form.ComboBox.superclass.onRender.call(this, ct, position);
         
-       if(this.hiddenName){
+               if(this.hiddenName){
             this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName, id:  (this.hiddenId||this.hiddenName)},
                     'before', true);
             this.hiddenField.value =
@@ -43845,7 +45920,11 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
         this.view.select(match);
         var sn = Roo.get(this.view.getSelectedNodes()[0]);
         sn.scrollIntoView(sn.dom.parentNode, false);
-    } 
+    },
+       cleanLeadingSpace : function()
+       {
+               // override textfield strip white space (trigers set on blur)
+       }
 
     /** 
     * @cfg {Boolean} grow 
@@ -43964,7 +46043,8 @@ Roo.extend(Roo.form.ComboBoxArray, Roo.form.TextField,
      */
     seperator : ',',
     
-    // private the array of items that are displayed..
+    
+       // private the array of items that are displayed..
     items  : false,
     // private - the hidden field el.
     hiddenEl : false,
@@ -44058,8 +46138,10 @@ Roo.extend(Roo.form.ComboBoxArray, Roo.form.TextField,
             // add to list
             
         }, this);
-        
-        
+         
+       
+       
+           
     },
     
     
@@ -44293,7 +46375,7 @@ Roo.extend(Roo.form.ComboBoxArray.Item, Roo.BoxComponent, {
     cb: false,
     displayField : false,
     tipField : false,
-    
+     
     
     defaultAutoCreate : {
         tag: 'div',
@@ -44972,7 +47054,9 @@ Roo.extend(Roo.form.Checkbox, Roo.form.Field,  {
             this.fireEvent('check', this, state);
         }
         this.inSetChecked = true;
-        this.el.dom.value = state ? this.inputValue : this.valueOff;
+                
+               this.el.dom.value = state ? this.inputValue : this.valueOff;
+                
         this.inSetChecked = false;
         
     },
@@ -45063,9 +47147,49 @@ Roo.extend(Roo.form.Radio, Roo.form.Checkbox, {
             this.el.dom.checked =   'checked' ;
         }
          
+    },
+    /**
+     * Sets the checked state of the checkbox.
+     * On is always based on a string comparison between inputValue and the param.
+     * @param {Boolean/String} value - the value to set 
+     * @param {Boolean/String} suppressEvent - whether to suppress the checkchange event.
+     */
+    setValue : function(v,suppressEvent){
+        
+        
+        //this.checked = (v === true || v === 'true' || v == '1' || String(v).toLowerCase() == 'on');
+        //if(this.el && this.el.dom){
+        //    this.el.dom.checked = this.checked;
+        //    this.el.dom.defaultChecked = this.checked;
+        //}
+        this.setChecked(String(v) === String(this.inputValue), suppressEvent);
+        
+        this.el.dom.form[this.name].value = v;
+     
+        //this.fireEvent("check", this, this.checked);
+    },
+    // private..
+    setChecked : function(state,suppressEvent)
+    {
+         
+        if(this.wrap){
+            this.wrap[state ? 'addClass' : 'removeClass']('x-menu-item-checked');
+        }
+        this.checked = state;
+        if(suppressEvent !== true){
+            this.fireEvent('check', this, state);
+        }
+                
+                 
+       
+        
+    },
+    reset : function(){
+        // this.setValue(this.resetValue);
+        //this.originalValue = this.getValue();
+        this.clearInvalid();
     } 
     
-    
 });Roo.rtf = {}; // namespace
 Roo.rtf.Hex = function(hex)
 {
@@ -45351,7 +47475,7 @@ Roo.rtf.Parser.prototype = {
         this.hexStore.push(cmd);
     },
     cmderror : function(cmd) {
-        throw new Exception (cmd.value);
+        throw cmd.value;
     },
     
     /*
@@ -45481,7 +47605,8 @@ Roo.rtf.Parser.prototype = {
     {
         this.emitText();
         if (this.controlWord === '') {
-            this.emitError('empty control word');
+            // do we want to track this - it seems just to cause problems.
+            //this.emitError('empty control word');
         } else {
             this.push({
                   type: 'controlword',
@@ -45605,6 +47730,8 @@ Roo.htmleditor.Filter.prototype = {
                     return;
                 
                 case this.tag === true: // everything
+                case e.tagName.indexOf(":") > -1 && typeof(this.tag) == 'object' && this.tag.indexOf(":") > -1:
+                case e.tagName.indexOf(":") > -1 && typeof(this.tag) == 'string' && this.tag == ":":
                 case typeof(this.tag) == 'object' && this.tag.indexOf(e.tagName) > -1: // array and it matches.
                 case typeof(this.tag) == 'string' && this.tag == e.tagName: // array and it matches.
                     if (this.replaceTag && false === this.replaceTag(e)) {
@@ -45623,6 +47750,39 @@ Roo.htmleditor.Filter.prototype = {
             
         }, this);
         
+    },
+    
+    
+    removeNodeKeepChildren : function( node)
+    {
+    
+        ar = Array.from(node.childNodes);
+        for (var i = 0; i < ar.length; i++) {
+         
+            node.removeChild(ar[i]);
+            // what if we need to walk these???
+            node.parentNode.insertBefore(ar[i], node);
+           
+        }
+        node.parentNode.removeChild(node);
+    },
+
+    searchTag : function(dom)
+    {
+        if(this.tag === false) {
+            return;
+        }
+
+        var els = dom.getElementsByTagName(this.tag);
+
+        Roo.each(Array.from(els), function(e){
+            if(e.parentNode == null) {
+                return;
+            }
+            if(this.replaceTag) {
+                this.replaceTag(e);
+            }
+        }, this);
     }
 }; 
 
@@ -45821,6 +47981,49 @@ Roo.extend(Roo.htmleditor.FilterComment, Roo.htmleditor.Filter,
     {
         n.parentNode.removeChild(n);
     }
+});/**
+ * @class Roo.htmleditor.FilterEmpty
+ * filter empty elements
+ * @constructor
+ * Run a new Empty Filter
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.FilterEmpty = function(cfg)
+{
+    // no need to apply config.
+    this.walk(cfg.node);
+}
+
+Roo.extend(Roo.htmleditor.FilterEmpty, Roo.htmleditor.FilterBlack,
+{
+     
+    tag : true,
+     
+    replaceTag : function(node)
+    {
+        // start from leaf node
+        if(node.hasChildNodes()) {
+            this.walk(node);
+        }
+
+        // only filter empty leaf element with certain tags
+        if(
+            ['B', 'I', 'U', 'S'].indexOf(node.tagName) < 0
+            ||
+            node.attributes && node.attributes.length > 0
+            ||
+            node.hasChildNodes()
+        ) {
+            return false; // don't walk
+        }
+
+        Roo.htmleditor.FilterBlack.prototype.replaceTag.call(this, node);
+        return false; // don't walk
+     
+    }
+    
 });/**
  * @class Roo.htmleditor.FilterKeepChildren
  * remove tags but keep children
@@ -45835,25 +48038,36 @@ Roo.htmleditor.FilterKeepChildren = function(cfg)
     if (this.tag === false) {
         return; // dont walk.. (you can use this to use this just to do a child removal on a single tag )
     }
+    // hacky?
+    if ((typeof(this.tag) == 'object' && this.tag.indexOf(":") > -1)) {
+        this.cleanNamespace = true;
+    }
+        
     this.walk(cfg.node);
 }
 
 Roo.extend(Roo.htmleditor.FilterKeepChildren, Roo.htmleditor.FilterBlack,
 {
-    
+    cleanNamespace : false, // should really be an option, rather than using ':' inside of this tag.
   
     replaceTag : function(node)
     {
         // walk children...
-        //Roo.log(node);
+        //Roo.log(node.tagName);
         var ar = Array.from(node.childNodes);
         //remove first..
+        
         for (var i = 0; i < ar.length; i++) {
-            if (ar[i].nodeType == 1) {
+            var e = ar[i];
+            if (e.nodeType == 1) {
                 if (
-                    (typeof(this.tag) == 'object' && this.tag.indexOf(ar[i].tagName) > -1)
+                    (typeof(this.tag) == 'object' && this.tag.indexOf(e.tagName) > -1)
                     || // array and it matches
-                    (typeof(this.tag) == 'string' && this.tag == ar[i].tagName)
+                    (typeof(this.tag) == 'string' && this.tag == e.tagName)
+                    ||
+                    (e.tagName.indexOf(":") > -1 && typeof(this.tag) == 'object' && this.tag.indexOf(":") > -1)
+                    ||
+                    (e.tagName.indexOf(":") > -1 && typeof(this.tag) == 'string' && this.tag == ":")
                 ) {
                     this.replaceTag(ar[i]); // child is blacklisted as well...
                     continue;
@@ -45871,6 +48085,7 @@ Roo.extend(Roo.htmleditor.FilterKeepChildren, Roo.htmleditor.FilterBlack,
                 
             }
         }
+        //Roo.log("REMOVE:" + node.tagName);
         node.parentNode.removeChild(node);
         return false; // don't walk children
         
@@ -45888,7 +48103,7 @@ Roo.extend(Roo.htmleditor.FilterKeepChildren, Roo.htmleditor.FilterBlack,
 Roo.htmleditor.FilterParagraph = function(cfg)
 {
     // no need to apply config.
-    this.walk(cfg.node);
+    this.searchTag(cfg.node);
 }
 
 Roo.extend(Roo.htmleditor.FilterParagraph, Roo.htmleditor.Filter,
@@ -45909,6 +48124,7 @@ Roo.extend(Roo.htmleditor.FilterParagraph, Roo.htmleditor.Filter,
             node.parentNode.replaceChild(node.ownerDocument.createElement('BR'),node);
             return false; // no need to walk..
         }
+
         var ar = Array.from(node.childNodes);
         for (var i = 0; i < ar.length; i++) {
             node.removeChild(ar[i]);
@@ -45928,6 +48144,41 @@ Roo.extend(Roo.htmleditor.FilterParagraph, Roo.htmleditor.Filter,
     }
     
 });/**
+ * @class Roo.htmleditor.FilterHashLink
+ * remove hash link
+ * @constructor
+ * Run a new Hash Link Filter
+ * @param {Object} config Configuration options
+ */
+
+ Roo.htmleditor.FilterHashLink = function(cfg)
+ {
+     // no need to apply config.
+    //  this.walk(cfg.node);
+    this.searchTag(cfg.node);
+ }
+ Roo.extend(Roo.htmleditor.FilterHashLink, Roo.htmleditor.Filter,
+ {
+      
+     tag : 'A',
+     
+      
+     replaceTag : function(node)
+     {
+         for(var i = 0; i < node.attributes.length; i ++) {
+             var a = node.attributes[i];
+
+             if(a.name.toLowerCase() == 'href' && a.value.startsWith('#')) {
+                 this.removeNodeKeepChildren(node);
+             }
+         }
+         
+         return false;
+     }
+     
+ });/**
  * @class Roo.htmleditor.FilterSpan
  * filter span's with no attributes out..
  * @constructor
@@ -45938,7 +48189,7 @@ Roo.extend(Roo.htmleditor.FilterParagraph, Roo.htmleditor.Filter,
 Roo.htmleditor.FilterSpan = function(cfg)
 {
     // no need to apply config.
-    this.walk(cfg.node);
+    this.searchTag(cfg.node);
 }
 
 Roo.extend(Roo.htmleditor.FilterSpan, Roo.htmleditor.FilterKeepChildren,
@@ -46030,7 +48281,13 @@ Roo.extend(Roo.htmleditor.FilterTableWidth, Roo.htmleditor.Filter,
 Roo.htmleditor.FilterWord = function(cfg)
 {
     // no need to apply config.
-    this.walk(cfg.node);
+    this.replaceDocBullets(cfg.node);
+    
+    this.replaceAname(cfg.node);
+    // this is disabled as the removal is done by other filters;
+   // this.walk(cfg.node);
+    this.replaceImageTable(cfg.node);
+    
 }
 
 Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
@@ -46080,7 +48337,10 @@ Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
                 node.removeChild(cn);
                 node.parentNode.insertBefore(cn, node);
                 // move node to parent - and clean it..
-                this.replaceTag(cn);
+                if (cn.nodeType == 1) {
+                    this.replaceTag(cn);
+                }
+                
             }
             node.parentNode.removeChild(node);
             /// no need to iterate chidlren = it's got none..
@@ -46132,7 +48392,317 @@ Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
         
         
         
+    },
+    
+    styleToObject: function(node)
+    {
+        var styles = (node.getAttribute("style") || '').split(";");
+        var ret = {};
+        Roo.each(styles, function(s) {
+            if (!s.match(/:/)) {
+                return;
+            }
+            var kv = s.split(":");
+             
+            // what ever is left... we allow.
+            ret[kv[0].trim()] = kv[1];
+        });
+        return ret;
+    },
+    
+    
+    replaceAname : function (doc)
+    {
+        // replace all the a/name without..
+        var aa = Array.from(doc.getElementsByTagName('a'));
+        for (var i = 0; i  < aa.length; i++) {
+            var a = aa[i];
+            if (a.hasAttribute("name")) {
+                a.removeAttribute("name");
+            }
+            if (a.hasAttribute("href")) {
+                continue;
+            }
+            // reparent children.
+            this.removeNodeKeepChildren(a);
+            
+        }
+        
+        
+        
+    },
+
+    
+    
+    replaceDocBullets : function(doc)
+    {
+        // this is a bit odd - but it appears some indents use ql-indent-1
+         //Roo.log(doc.innerHTML);
+        
+        var listpara = Array.from(doc.getElementsByClassName('MsoListParagraphCxSpFirst'));
+        for( var i = 0; i < listpara.length; i ++) {
+            listpara[i].className = "MsoListParagraph";
+        }
+        
+        listpara =  Array.from(doc.getElementsByClassName('MsoListParagraphCxSpMiddle'));
+        for( var i = 0; i < listpara.length; i ++) {
+            listpara[i].className = "MsoListParagraph";
+        }
+        listpara =  Array.from(doc.getElementsByClassName('MsoListParagraphCxSpLast'));
+        for( var i = 0; i < listpara.length; i ++) {
+            listpara[i].className = "MsoListParagraph";
+        }
+        listpara =  Array.from(doc.getElementsByClassName('ql-indent-1'));
+        for( var i = 0; i < listpara.length; i ++) {
+            listpara[i].className = "MsoListParagraph";
+        }
+        
+        // this is a bit hacky - we had one word document where h2 had a miso-list attribute.
+        var htwo =  Array.from(doc.getElementsByTagName('h2'));
+        for( var i = 0; i < htwo.length; i ++) {
+            if (htwo[i].hasAttribute('style') && htwo[i].getAttribute('style').match(/mso-list:/)) {
+                htwo[i].className = "MsoListParagraph";
+            }
+        }
+        listpara =  Array.from(doc.getElementsByClassName('MsoNormal'));
+        for( var i = 0; i < listpara.length; i ++) {
+            if (listpara[i].hasAttribute('style') && listpara[i].getAttribute('style').match(/mso-list:/)) {
+                listpara[i].className = "MsoListParagraph";
+            } else {
+                listpara[i].className = "MsoNormalx";
+            }
+        }
+       
+        listpara = doc.getElementsByClassName('MsoListParagraph');
+        // Roo.log(doc.innerHTML);
+        
+        
+        
+        while(listpara.length) {
+            
+            this.replaceDocBullet(listpara.item(0));
+        }
+      
+    },
+    
+     
+    
+    replaceDocBullet : function(p)
+    {
+        // gather all the siblings.
+        var ns = p,
+            parent = p.parentNode,
+            doc = parent.ownerDocument,
+            items = [];
+         
+        //Roo.log("Parsing: " + p.innerText)    ;
+        var listtype = 'ul';   
+        while (ns) {
+            if (ns.nodeType != 1) {
+                ns = ns.nextSibling;
+                continue;
+            }
+            if (!ns.className.match(/(MsoListParagraph|ql-indent-1)/i)) {
+                //Roo.log("Missing para r q1indent - got:" + ns.className);
+                break;
+            }
+            var spans = ns.getElementsByTagName('span');
+            
+            if (ns.hasAttribute('style') && ns.getAttribute('style').match(/mso-list/)) {
+                items.push(ns);
+                ns = ns.nextSibling;
+                has_list = true;
+                if (!spans.length) {
+                    continue;
+                }
+                var ff = '';
+                var se = spans[0];
+                for (var i = 0; i < spans.length;i++) {
+                    se = spans[i];
+                    if (se.hasAttribute('style')  && se.hasAttribute('style') && se.style.fontFamily != '') {
+                        ff = se.style.fontFamily;
+                        break;
+                    }
+                }
+                 
+                    
+                //Roo.log("got font family: " + ff);
+                if (typeof(ff) != 'undefined' && !ff.match(/(Symbol|Wingdings)/) && "·o".indexOf(se.innerText.trim()) < 0) {
+                    listtype = 'ol';
+                }
+                
+                continue;
+            }
+            //Roo.log("no mso-list?");
+            
+            var spans = ns.getElementsByTagName('span');
+            if (!spans.length) {
+                break;
+            }
+            var has_list  = false;
+            for(var i = 0; i < spans.length; i++) {
+                if (spans[i].hasAttribute('style') && spans[i].getAttribute('style').match(/mso-list/)) {
+                    has_list = true;
+                    break;
+                }
+            }
+            if (!has_list) {
+                break;
+            }
+            items.push(ns);
+            ns = ns.nextSibling;
+            
+            
+        }
+        if (!items.length) {
+            ns.className = "";
+            return;
+        }
+        
+        var ul = parent.ownerDocument.createElement(listtype); // what about number lists...
+        parent.insertBefore(ul, p);
+        var lvl = 0;
+        var stack = [ ul ];
+        var last_li = false;
+        
+        var margin_to_depth = {};
+        max_margins = -1;
+        
+        items.forEach(function(n, ipos) {
+            //Roo.log("got innertHMLT=" + n.innerHTML);
+            
+            var spans = n.getElementsByTagName('span');
+            if (!spans.length) {
+                //Roo.log("No spans found");
+                 
+                parent.removeChild(n);
+                
+                
+                return; // skip it...
+            }
+           
+                
+            var num = 1;
+            var style = {};
+            for(var i = 0; i < spans.length; i++) {
+            
+                style = this.styleToObject(spans[i]);
+                if (typeof(style['mso-list']) == 'undefined') {
+                    continue;
+                }
+                if (listtype == 'ol') {
+                   num = spans[i].innerText.replace(/[^0-9]+]/g,'')  * 1;
+                }
+                spans[i].parentNode.removeChild(spans[i]); // remove the fake bullet.
+                break;
+            }
+            //Roo.log("NOW GOT innertHMLT=" + n.innerHTML);
+            style = this.styleToObject(n); // mo-list is from the parent node.
+            if (typeof(style['mso-list']) == 'undefined') {
+                //Roo.log("parent is missing level");
+                  
+                parent.removeChild(n);
+                 
+                return;
+            }
+            
+            var margin = style['margin-left'];
+            if (typeof(margin_to_depth[margin]) == 'undefined') {
+                max_margins++;
+                margin_to_depth[margin] = max_margins;
+            }
+            nlvl = margin_to_depth[margin] ;
+             
+            if (nlvl > lvl) {
+                //new indent
+                var nul = doc.createElement(listtype); // what about number lists...
+                if (!last_li) {
+                    last_li = doc.createElement('li');
+                    stack[lvl].appendChild(last_li);
+                }
+                last_li.appendChild(nul);
+                stack[nlvl] = nul;
+                
+            }
+            lvl = nlvl;
+            
+            // not starting at 1..
+            if (!stack[nlvl].hasAttribute("start") && listtype == "ol") {
+                stack[nlvl].setAttribute("start", num);
+            }
+            
+            var nli = stack[nlvl].appendChild(doc.createElement('li'));
+            last_li = nli;
+            nli.innerHTML = n.innerHTML;
+            //Roo.log("innerHTML = " + n.innerHTML);
+            parent.removeChild(n);
+            
+             
+             
+            
+        },this);
+        
+        
+        
+        
+    },
+    
+    replaceImageTable : function(doc)
+    {
+         /*
+          <table cellpadding=0 cellspacing=0 align=left>
+  <tr>
+   <td width=423 height=0></td>
+  </tr>
+  <tr>
+   <td></td>
+   <td><img width=601 height=401
+   src="file:///C:/Users/Alan/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg"
+   v:shapes="Picture_x0020_2"></td>
+  </tr>
+ </table>
+ */
+        var imgs = Array.from(doc.getElementsByTagName('img'));
+        Roo.each(imgs, function(img) {
+            var td = img.parentNode;
+            if (td.nodeName !=  'TD') {
+                return;
+            }
+            var tr = td.parentNode;
+            if (tr.nodeName !=  'TR') {
+                return;
+            }
+            var tbody = tr.parentNode;
+            if (tbody.nodeName !=  'TBODY') {
+                return;
+            }
+            var table = tbody.parentNode;
+            if (table.nodeName !=  'TABLE') {
+                return;
+            }
+            // first row..
+            
+            if (table.getElementsByTagName('tr').length != 2) {
+                return;
+            }
+            if (table.getElementsByTagName('td').length != 3) {
+                return;
+            }
+            if (table.innerText.trim() != '') {
+                return;
+            }
+            var p = table.parentNode;
+            img.parentNode.removeChild(img);
+            p.insertBefore(img, table);
+            p.removeChild(table);
+            
+            
+            
+        });
+        
+      
     }
+    
 });
 /**
  * @class Roo.htmleditor.FilterStyleToTag
@@ -46149,12 +48719,12 @@ Roo.htmleditor.FilterStyleToTag = function(cfg)
 {
     
     this.tags = {
-        B  : [ 'fontWeight' , 'bold'],
-        I :  [ 'fontStyle' , 'italic'],
+        B  : [ 'fontWeight' , 'bold', 'font-weight'],
+        I :  [ 'fontStyle' , 'italic', 'font-style'],
         //pre :  [ 'font-style' , 'italic'],
         // h1.. h6 ?? font-size?
-        SUP : [ 'verticalAlign' , 'super' ],
-        SUB : [ 'verticalAlign' , 'sub' ]
+        SUP : [ 'verticalAlign' , 'super', 'vertical-align'],
+        SUB : [ 'verticalAlign' , 'sub', 'vertical-align']
         
         
     };
@@ -46187,7 +48757,7 @@ Roo.extend(Roo.htmleditor.FilterStyleToTag, Roo.htmleditor.Filter,
         for (var k in this.tags) {
             if (node.style[this.tags[k][0]] == this.tags[k][1]) {
                 inject.push(k);
-                node.style.removeProperty(this.tags[k][0]);
+                node.style.removeProperty(this.tags[k][2]);
             }
         }
         if (!inject.length) {
@@ -46200,7 +48770,7 @@ Roo.extend(Roo.htmleditor.FilterStyleToTag, Roo.htmleditor.Filter,
             nn.appendChild(nc);
             nn = nc;
         });
-        for(var i = 0;i < cn.length;cn++) {
+        for(var i = 0;i < cn.length;i++) {
             node.removeChild(cn[i]);
             nn.appendChild(cn[i]);
         }
@@ -46218,7 +48788,7 @@ Roo.extend(Roo.htmleditor.FilterStyleToTag, Roo.htmleditor.Filter,
 Roo.htmleditor.FilterLongBr = function(cfg)
 {
     // no need to apply config.
-    this.walk(cfg.node);
+    this.searchTag(cfg.node);
 }
 
 Roo.extend(Roo.htmleditor.FilterLongBr, Roo.htmleditor.Filter,
@@ -46252,8 +48822,6 @@ Roo.extend(Roo.htmleditor.FilterLongBr, Roo.htmleditor.Filter,
         
         
         
-        
-        
         if (!node.previousSibling) {
             return false;
         }
@@ -46620,12 +49188,14 @@ Roo.htmleditor.TidyWriter.prototype = {
      * @param {String} text String to write out.
      * @param {Boolean} raw Optional raw state if true the contents wont get encoded.
      */
-    text: function(text, node)
+    text: function(in_text, node)
     {
         // if not in whitespace critical
-        if (text.length < 1) {
+        if (in_text.length < 1) {
             return;
         }
+        var text = new XMLSerializer().serializeToString(document.createTextNode(in_text)); // escape it properly?
+        
         if (this.in_pre) {
             this.html[this.html.length] =  text;
             return;   
@@ -47623,7 +50193,17 @@ Roo.htmleditor.KeyEnter.prototype = {
         var pc = range.closest([ 'ol', 'ul']);
         var pli = range.closest('li');
         if (!pc || e.ctrlKey) {
-            sel.insertNode('br', 'after'); 
+            // on it list, or ctrl pressed.
+            if (!e.ctrlKey) {
+                sel.insertNode('br', 'after'); 
+            } else {
+                // only do this if we have ctrl key..
+                var br = doc.createElement('br');
+                br.className = 'clear';
+                br.setAttribute('style', 'clear: both');
+                sel.insertNode(br, 'after'); 
+            }
+            
          
             this.core.undoManager.addEvent();
             this.core.fireEditorEvent(e);
@@ -47987,10 +50567,11 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
                 store : {
                     xtype : 'SimpleStore',
                     data : [
-                        ['auto'],
-                        ['50%'],
+                        ['100%'],
                         ['80%'],
-                        ['100%']
+                        ['50%'],
+                        ['20%'],
+                        ['10%']
                     ],
                     fields : [ 'val'],
                     xns : Roo.data
@@ -48036,7 +50617,7 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
                 }
             },
             
-            
+              
             {
                 xtype : 'Button',
                 text: 'Hide Caption',
@@ -48044,7 +50625,10 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
                 pressed : false,
                 enableToggle : true,
                 setValue : function(v) {
-                    this.toggle(v == 'block' ? false : true);
+                    // this trigger toggle.
+                     
+                    this.setText(v ? "Hide Caption" : "Show Caption");
+                    this.setPressed(v != 'block');
                 },
                 listeners : {
                     toggle: function (btn, state)
@@ -48083,11 +50667,13 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
             style: {
                 width : iw,
                 maxWidth : iw + ' !important', // this is not getting rendered?
-                margin : m 
-                
+                margin : m  
                 
-            }
+            },
+            width: this.align == 'center' ?  this.width : '100%' 
+
         };
+        
         /*
         '<div class="{0}" width="420" height="315" src="{1}" frameborder="0" allowfullscreen>' +
                     '<a href="{2}">' + 
@@ -48122,13 +50708,15 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
                 ]
             };
         }
-        // we remove caption totally if its hidden... - will delete data.. but otherwise we end up with fake caption
-        var captionhtml = this.caption_display == 'none' ? '' : (this.caption.length ? this.caption : "Caption");
-        
-        return  {
+
+
+  
+        var ret =   {
             tag: 'figure',
             'data-block' : 'Figure',
-            
+            'data-width' : this.width,
+            'data-caption' : this.caption, 
+            'data-caption-display' : this.caption_display,
             contenteditable : 'false',
             
             style : {
@@ -48137,55 +50725,57 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
                 maxWidth :  this.align == 'center' ? '100% !important' : (this.width + ' !important'),
                 width : this.align == 'center' ? '100%' : this.width,
                 margin:  '0px',
-                padding: '10px',
+                padding: this.align == 'center' ? '0' : '0 10px' ,
                 textAlign : this.align   // seems to work for email..
                 
             },
-           
             
             align : this.align,
             cn : [
-                img,
-              
-                {
-                    tag: 'figcaption',
-                    'data-display' : this.caption_display,
-                    style : {
-                        textAlign : 'left',
-                        fontSize : '16px',
-                        lineHeight : '24px',
-                        display : this.caption_display,
-                        maxWidth : this.width + ' !important',
-                        margin: m,
-                        width: this.width
-                    
-                         
-                    },
-                    cls : this.cls.length > 0 ? (this.cls  + '-thumbnail' ) : '',
-                    cn : [
-                        {
-                            tag: 'div',
-                            style  : {
-                                marginTop : '16px',
-                                textAlign : 'left'
-                            },
-                            align: 'left',
-                            cn : [
-                                {
-                                    // we can not rely on yahoo syndication to use CSS elements - so have to use  '<i>' to encase stuff.
-                                    tag : 'i',
-                                    contenteditable : true,
-                                    html : captionhtml
-                                }
-                                
-                            ]
-                        }
-                        
-                    ]
-                    
-                }
+                img
             ]
         };
+
+        // show figcaption only if caption_display is 'block'
+        if(this.caption_display == 'block') {
+            ret['cn'].push({
+                tag: 'figcaption',
+                style : {
+                    textAlign : 'left',
+                    fontSize : '16px',
+                    lineHeight : '24px',
+                    display : this.caption_display,
+                    maxWidth : (this.align == 'center' ?  this.width : '100%' ) + ' !important',
+                    margin: m,
+                    width: this.align == 'center' ?  this.width : '100%' 
+                
+                     
+                },
+                cls : this.cls.length > 0 ? (this.cls  + '-thumbnail' ) : '',
+                cn : [
+                    {
+                        tag: 'div',
+                        style  : {
+                            marginTop : '16px',
+                            textAlign : 'start'
+                        },
+                        align: 'left',
+                        cn : [
+                            {
+                                // we can not rely on yahoo syndication to use CSS elements - so have to use  '<i>' to encase stuff.
+                                tag : 'i',
+                                contenteditable : Roo.htmleditor.BlockFigure.caption_edit,
+                                html : this.caption.length ? this.caption : "Caption" // fake caption
+                            }
+                            
+                        ]
+                    }
+                    
+                ]
+                
+            });
+        }
+        return ret;
          
     },
     
@@ -48200,12 +50790,33 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
         this.image_src = this.getVal(node, 'img', 'src');
          
         this.align = this.getVal(node, 'figure', 'align');
+
+        // caption display is stored in figure
+        this.caption_display = this.getVal(node, true, 'data-caption-display');
+
+        // backward compatible
+        // it was stored in figcaption
+        if(this.caption_display == '') {
+            this.caption_display = this.getVal(node, 'figcaption', 'data-display');
+        }
+
+        // read caption from figcaption
         var figcaption = this.getVal(node, 'figcaption', false);
-        this.caption = this.getVal(figcaption, 'i', 'html');
 
-        this.caption_display = this.getVal(node, 'figcaption', 'data-display');
+        if (figcaption !== '') {
+            this.caption = this.getVal(figcaption, 'i', 'html');
+        }
+                
+
+        // read caption from data-caption in figure if no caption from figcaption
+        var dc = this.getVal(node, true, 'data-caption');
+
+        if(this.caption_display == 'none' && dc && dc.length){
+            this.caption = dc;
+        }
+
         //this.text_align = this.getVal(node, 'figcaption', 'style','text-align');
-        this.width = this.getVal(node, 'figcaption', 'style', 'width');
+        this.width = this.getVal(node, true, 'data-width');
         //this.margin = this.getVal(node, 'figure', 'style', 'margin');
         
     },
@@ -48221,7 +50832,11 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
     
     
     
-})
+});
+
+Roo.apply(Roo.htmleditor.BlockFigure, {
+    caption_edit : true
+});
 
  
 
@@ -49053,7 +51668,6 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
      */
     toObject : function()
     {
-        
         var ret = {
             tag : 'td',
             contenteditable : 'true', // this stops cell selection from picking the table.
@@ -49094,6 +51708,9 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
         this.colspan = Math.max(1,1*node.getAttribute('colspan'));
         this.rowspan = Math.max(1,1*node.getAttribute('rowspan'));
         this.html = node.innerHTML;
+        if (node.style.textAlign != '') {
+            this.textAlign = node.style.textAlign;
+        }
         
         
     },
@@ -49151,7 +51768,7 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
                     c.col = cn;
                 }
                 
-                if (typeof(this.colWidths[cn]) == 'undefined') {
+                if (typeof(this.colWidths[cn]) == 'undefined' && c.colspan < 2) {
                     this.colWidths[cn] =   ce.style.width;
                     if (this.colWidths[cn] != '') {
                         all_auto = false;
@@ -49220,6 +51837,9 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
         this.colspan += rc.colspan;
         this.node.setAttribute('colspan', this.colspan);
 
+        var table = this.toTableArray();
+        this.normalizeWidths(table);
+        this.updateWidths(table);
     },
     
     
@@ -49254,19 +51874,17 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
         this.colspan = 1;
         
         for(var r = cd.row; r < cd.row + cd.rowspan; r++) {
-            
-            
+             
             
             for(var c = cd.col; c < cd.col + cd.colspan; c++) {
                 if (r == cd.row && c == cd.col) {
                     this.node.removeAttribute('rowspan');
                     this.node.removeAttribute('colspan');
-                    continue;
                 }
                  
                 var ntd = this.node.cloneNode(); // which col/row should be 0..
-                ntd.removeAttribute('id'); //
-                //ntd.style.width  = '';
+                ntd.removeAttribute('id'); 
+                ntd.style.width  = this.colWidths[c];
                 ntd.innerHTML = '';
                 table[r][c] = { cell : ntd, col : c, row: r , colspan : 1 , rowspan : 1   };
             }
@@ -49274,8 +51892,6 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
         }
         this.redrawAllCells(table);
         
-         
-        
     },
     
     
@@ -49324,13 +51940,27 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
                     el.width = Math.floor(this.colWidths[c])  +'%';
                     el.updateElement(el.node);
                 }
+                if (this.colWidths[0] != false && table[r][c].colspan > 1) {
+                    var el = Roo.htmleditor.Block.factory(table[r][c].cell);
+                    var width = 0;
+                    var lv = false;
+                    for(var i = 0; i < table[r][c].colspan; i ++) {
+                        if (typeof(this.colWidths[c + i]) != 'undefined') {
+                            lv = this.colWidths[c + i];
+                        } else {
+                            this.colWidths[c + i] = lv;
+                        }
+                        width += Math.floor(this.colWidths[c + i]);
+                    }
+                    el.width = width  +'%';
+                    el.updateElement(el.node);
+                }
                 table[r][c].cell = false; // done
             }
         }
     },
     normalizeWidths : function(table)
     {
-    
         if (this.colWidths[0] === false) {
             var nw = 100.0 / this.colWidths.length;
             this.colWidths.forEach(function(w,i) {
@@ -49389,7 +52019,11 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
                  this.colWidths[i] = nw;
                 return;
             }
-            this.colWidths[i] += otherAdd
+            if (typeof(this.colWidths[i]) == 'undefined') {
+                this.colWidths[i] = otherAdd;
+            } else {
+                this.colWidths[i] += otherAdd;
+            }
         }, this);
         this.updateWidths(table);
          
@@ -49409,7 +52043,12 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
                 this.colWidths[i] = nw;
                 return;
             }
-            this.colWidths[i] -= otherSub
+            if (typeof(this.colWidths[i]) == 'undefined') {
+                this.colWidths[i] = otherSub;
+            } else {
+                this.colWidths[i] -= otherSub;
+            }
+            
         }, this);
         this.updateWidths(table);
          
@@ -49535,7 +52174,7 @@ Roo.HtmlEditorCore = function(config){
          * @param {Roo.HtmlEditorCore} this
          */
         editorevent: true 
-         
+        
         
     });
     
@@ -49559,10 +52198,9 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
     owner : false,
     
      /**
-     * @cfg {String} resizable  's' or 'se' or 'e' - wrapps the element in a
-     *                        Roo.resizable.
+     * @cfg {String} css styling for resizing. (used on bootstrap only)
      */
-    resizable : false,
+    resize : false,
      /**
      * @cfg {Number} height (in pixels)
      */   
@@ -49695,17 +52333,19 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         
         this.frameId = Roo.id();
         
-         
-        
-        var iframe = this.owner.wrap.createChild({
+        var ifcfg = {
             tag: 'iframe',
             cls: 'form-control', // bootstrap..
             id: this.frameId,
             name: this.frameId,
             frameBorder : 'no',
             'src' : Roo.SSL_SECURE_URL ? Roo.SSL_SECURE_URL  :  "javascript:false"
-        }, this.el
-        );
+        };
+        if (this.resize) {
+            ifcfg.style = { resize : this.resize };
+        }
+        
+        var iframe = this.owner.wrap.createChild(ifcfg, this.el); 
         
         
         this.iframe = iframe.dom;
@@ -49818,7 +52458,9 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         //Roo.log("HtmlEditorCore:syncValue (EDITOR->TEXT)");
         if(this.initialized){
             
-            this.undoManager.addEvent();
+            if (this.undoManager) {
+                this.undoManager.addEvent();
+            }
 
             
             var bd = (this.doc.body || this.doc.documentElement);
@@ -49836,13 +52478,57 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
             
            
             if (this.enableBlocks) {
+                Array.from(bd.getElementsByTagName('img')).forEach(function(img) {
+                    var fig = img.closest('figure');
+                    if (fig) {
+                        var bf = new Roo.htmleditor.BlockFigure({
+                            node : fig
+                        });
+                        bf.updateElement();
+                    }
+                    
+                });
                 new Roo.htmleditor.FilterBlock({ node : div });
             }
+            
+            var html = div.innerHTML;
+            
             //?? tidy?
-            var tidy = new Roo.htmleditor.TidySerializer({
-                inner:  true
-            });
-            var html  = tidy.serialize(div);
+            if (this.autoClean) {
+                new Roo.htmleditor.FilterBlack({ node : div, tag : this.black});
+                new Roo.htmleditor.FilterAttributes({
+                    node : div,
+                    attrib_white : [
+                            'href',
+                            'src',
+                            'name',
+                            'align',
+                            'colspan',
+                            'rowspan',
+                            'data-display',
+                            'data-caption-display',
+                            'data-width',
+                            'data-caption',
+                            'start' ,
+                            'style',
+                            // youtube embed.
+                            'class',
+                            'allowfullscreen',
+                            'frameborder',
+                            'width',
+                            'height',
+                            'alt'
+                            ],
+                    attrib_clean : ['href', 'src' ] 
+                });
+                new Roo.htmleditor.FilterEmpty({ node : div});
+                
+                var tidy = new Roo.htmleditor.TidySerializer({
+                    inner:  true
+                });
+                html  = tidy.serialize(div);
+                
+            }
             
             
             if(Roo.isSafari){
@@ -50030,14 +52716,39 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         var cd = (e.browserEvent.clipboardData || window.clipboardData);
         
         // check what type of paste - if it's an image, then handle it differently.
-        if (cd.files && cd.files.length > 0) {
-            // pasting images?
+        if (cd.files && cd.files.length > 0 && cd.types.indexOf('text/html') < 0) {
+            // pasting images? 
             var urlAPI = (window.createObjectURL && window) || 
                 (window.URL && URL.revokeObjectURL && URL) || 
                 (window.webkitURL && webkitURL);
-    
-            var url = urlAPI.createObjectURL( cd.files[0]);
-            this.insertAtCursor('<img src=" + url + ">');
+            
+            var r = new FileReader();
+            var t = this;
+            r.addEventListener('load',function()
+            {
+                
+                var d = (new DOMParser().parseFromString('<img src="' + r.result+ '">', 'text/html')).body;
+                // is insert asycn?
+                if (t.enableBlocks) {
+                    
+                    Array.from(d.getElementsByTagName('img')).forEach(function(img) {
+                        if (img.closest('figure')) { // assume!! that it's aready
+                            return;
+                        }
+                        var fig  = new Roo.htmleditor.BlockFigure({
+                            image_src  : img.src
+                        });
+                        fig.updateElement(img); // replace it..
+                        
+                    });
+                }
+                t.insertAtCursor(d.innerHTML.replace(/&nbsp;/g,' '));
+                t.owner.fireEvent('paste', this);
+            });
+            r.readAsDataURL(cd.files[0]);
+            
+            e.preventDefault();
+            
             return false;
         }
         if (cd.types.indexOf('text/html') < 0 ) {
@@ -50049,14 +52760,14 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
             var parser = new Roo.rtf.Parser(cd.getData('text/rtf'));
             images = parser.doc ? parser.doc.getElementsByType('pict') : [];
         }
-        Roo.log(images);
-        //Roo.log(imgs);
+        // Roo.log(images);
+        // Roo.log(imgs);
         // fixme..
         images = images.filter(function(g) { return !g.path.match(/^rtf\/(head|pgdsctbl|listtable|footerf)/); }) // ignore headers/footers etc.
                        .map(function(g) { return g.toDataURL(); })
                        .filter(function(g) { return g != 'about:blank'; });
         
-        
+        //Roo.log(html);
         html = this.cleanWordChars(html);
         
         var d = (new DOMParser().parseFromString(html, 'text/html')).body;
@@ -50074,24 +52785,63 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
             return false;
         }
         
+        
+        
         if (images.length > 0) {
+            // replace all v:imagedata - with img.
+            var ar = Array.from(d.getElementsByTagName('v:imagedata'));
+            Roo.each(ar, function(node) {
+                node.parentNode.insertBefore(d.ownerDocument.createElement('img'), node );
+                node.parentNode.removeChild(node);
+            });
+            
+            
             Roo.each(d.getElementsByTagName('img'), function(img, i) {
                 img.setAttribute('src', images[i]);
             });
         }
         if (this.autoClean) {
+            new Roo.htmleditor.FilterWord({ node : d });
+            
             new Roo.htmleditor.FilterStyleToTag({ node : d });
             new Roo.htmleditor.FilterAttributes({
                 node : d,
-                attrib_white : ['href', 'src', 'name', 'align', 'colspan', 'rowspan'],
+                attrib_white : [
+                    'href',
+                    'src',
+                    'name',
+                    'align',
+                    'colspan',
+                    'rowspan' 
+                /*  THESE ARE NOT ALLWOED FOR PASTE
+                 *    'data-display',
+                    'data-caption-display',
+                    'data-width',
+                    'data-caption',
+                    'start' ,
+                    'style',
+                    // youtube embed.
+                    'class',
+                    'allowfullscreen',
+                    'frameborder',
+                    'width',
+                    'height',
+                    'alt'
+                    */
+                    ],
                 attrib_clean : ['href', 'src' ] 
             });
             new Roo.htmleditor.FilterBlack({ node : d, tag : this.black});
             // should be fonts..
-            new Roo.htmleditor.FilterKeepChildren({node : d, tag : [ 'FONT', 'O:P' ]} );
+            new Roo.htmleditor.FilterKeepChildren({node : d, tag : [ 'FONT', ':' ]} );
             new Roo.htmleditor.FilterParagraph({ node : d });
+            new Roo.htmleditor.FilterHashLink({node : d});
             new Roo.htmleditor.FilterSpan({ node : d });
             new Roo.htmleditor.FilterLongBr({ node : d });
+            new Roo.htmleditor.FilterComment({ node : d });
+            new Roo.htmleditor.FilterEmpty({ node : d});
+            
+            
         }
         if (this.enableBlocks) {
                 
@@ -50112,9 +52862,10 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         if (this.enableBlocks) {
             Roo.htmleditor.Block.initAll(this.doc.body);
         }
-        
+         
         
         e.preventDefault();
+        this.owner.fireEvent('paste', this);
         return false;
         // default behaveiour should be our local cleanup paste? (optional?)
         // for simple editor - we want to hammer the paste and get rid of everything... - so over-rideable..
@@ -50191,6 +52942,8 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         if (e && (e.ctrlKey || e.metaKey) && e.keyCode === 90) {
             return; // we do not handle this.. (undo manager does..)
         }
+        // clicking a 'block'?
+        
         // in theory this detects if the last element is not a br, then we try and do that.
         // its so clicking in space at bottom triggers adding a br and moving the cursor.
         if (e &&
@@ -50293,6 +53046,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                 break;
             case 'bold':
             case 'italic':
+            case 'underline':                
                 // if there is no selection, then we insert, and set the curson inside it..
                 this.execCmd('styleWithCSS', false); 
                 break;
@@ -50775,6 +53529,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
     cleanWord : function(node)
     {
         new Roo.htmleditor.FilterWord({ node : node ? node : this.doc.body });
+        new Roo.htmleditor.FilterKeepChildren({node : node ? node : this.doc.body, tag : [ 'FONT', ':' ]} );
         
     },
    
@@ -51282,6 +54037,7 @@ Roo.extend(Roo.form.HtmlEditor, Roo.form.Field, {
             * @param {Roo.HtmlEditorCore} this
             */
             paste: true 
+            
         });
         this.defaultAutoCreate =  {
             tag: "textarea",
@@ -53505,12 +56261,12 @@ Roo.extend(Roo.form.BasicForm, Roo.util.Observable, {
     disableMask : false,
     
     /**
-     * @cfg {Boolean} errorMask (true|false) default false
+     * @cfg {Boolean} errorMask Should the form be masked (and the active element highlighted on error - default false
      */
     errorMask : false,
     
     /**
-     * @cfg {Number} maskOffset Default 100
+     * @cfg {Number} maskOffset space around form element to mask if there is an error Default 100
      */
     maskOffset : 100,
 
@@ -53881,6 +56637,9 @@ clientValidation  Boolean          Applies to submit only.  Pass true to call fo
             for(id in values){
                 if(typeof values[id] != 'function' && (field = this.findField(id))){
                     
+                    
+                    
+                    
                     if (field.setFromData && 
                         field.valueField && 
                         field.displayField &&
@@ -53895,6 +56654,9 @@ clientValidation  Boolean          Applies to submit only.  Pass true to call fo
                         sd[field.displayField] = typeof(values[field.name]) == 'undefined' ? '' : values[field.name];
                         field.setFromData(sd);
                         
+                    } else if (field.inputType && field.inputType == 'radio') {
+                        
+                        field.setValue(values[id]);
                     } else {
                         field.setValue(values[id]);
                     }
@@ -53920,7 +56682,7 @@ clientValidation  Boolean          Applies to submit only.  Pass true to call fo
     /**
      * Returns the fields in this form as an object with key/value pairs. If multiple fields exist with the same name
      * they are returned as an array.
-     * @param {Boolean} asString
+     * @param {Boolean} asString (def)
      * @return {Object}
      */
     getValues : function(asString)
@@ -54343,7 +57105,7 @@ Roo.extend(Roo.form.Form, Roo.form.BasicForm, {
      * @cfg {String} itemCls A css class to apply to the x-form-item of fields. This property cascades to child containers.
      */
     /**
-     * @cfg {String} buttonAlign Valid values are "left," "center" and "right" (defaults to "center")
+     * @cfg {String} buttonAlign (left|center|right)  Valid values are "left," "center" and "right" (defaults to "center")
      */
     buttonAlign:'center',
 
@@ -54353,7 +57115,7 @@ Roo.extend(Roo.form.Form, Roo.form.BasicForm, {
     minButtonWidth:75,
 
     /**
-     * @cfg {String} labelAlign Valid values are "left," "top" and "right" (defaults to "left").
+     * @cfg {String} labelAlign (left|top|right) Valid values are "left," "top" and "right" (defaults to "left").
      * This property cascades to child containers if not set.
      */
     labelAlign:'left',
@@ -55000,7 +57762,13 @@ Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
         }
         var ret = false;
         try {
-            ret = Roo.decode(response.responseText);
+            var rt = response.responseText;
+            if (rt.match(/^\<!--\[CDATA\[/)) {
+                rt = rt.replace(/^\<!--\[CDATA\[/,'');
+                rt = rt.replace(/\]\]--\>$/,'');
+            }
+            
+            ret = Roo.decode(rt);
         } catch (e) {
             ret = {
                 success: false,
@@ -55103,7 +57871,7 @@ Roo.extend(Roo.form.Layout, Roo.Component, {
      * a function which returns such a specification.
      */
     /**
-     * @cfg {String} labelAlign
+     * @cfg {String} labelAlign (left|top|right)
      * Valid values are "left," "top" and "right" (defaults to "left")
      */
     /**
@@ -55223,6 +57991,7 @@ Roo.extend(Roo.form.Layout, Roo.Component, {
     }
 });
 
+
 /**
  * @class Roo.form.Column
  * @extends Roo.form.Layout
@@ -55257,7 +58026,6 @@ Roo.extend(Roo.form.Column, Roo.form.Layout, {
     }
 });
 
-
 /**
  * @class Roo.form.Row
  * @extends Roo.form.Layout
@@ -55393,8 +58161,9 @@ Roo.form.VTypes = function(){
     // closure these in so they are only created once.
     var alpha = /^[a-zA-Z_]+$/;
     var alphanum = /^[a-zA-Z0-9_]+$/;
-    var email = /^([\w]+)(.[\w]+)*@([\w-]+\.){1,5}([A-Za-z]){2,24}$/;
-    var url = /(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
+    var email = /^([\w'-]+)(\.[\w'-]+)*@([\w-]+\.){1,5}([A-Za-z]){2,24}$/;
+    var url = /^(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
+    var urlWeb = /^((https?):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
 
     // All these messages and functions are configurable
     return {
@@ -55402,68 +58171,75 @@ Roo.form.VTypes = function(){
          * The function used to validate email addresses
          * @param {String} value The email address
          */
-        'email' : function(v){
+        email : function(v){
             return email.test(v);
         },
         /**
          * The error text to display when the email validation function returns false
          * @type String
          */
-        'emailText' : 'This field should be an e-mail address in the format "user@domain.com"',
+        emailText : 'This field should be an e-mail address in the format "user@domain.com"',
         /**
          * The keystroke filter mask to be applied on email input
          * @type RegExp
          */
-        'emailMask' : /[a-z0-9_\.\-@]/i,
+        emailMask : /[a-z0-9_\.\-@]/i,
 
         /**
          * The function used to validate URLs
          * @param {String} value The URL
          */
-        'url' : function(v){
+        url : function(v){
             return url.test(v);
         },
+        /**
+         * The funciton used to validate URLs (only allow schemes 'https' and 'http')
+         * @param {String} v The URL
+         */
+        urlWeb : function(v) {
+            return urlWeb.test(v);
+        },
         /**
          * The error text to display when the url validation function returns false
          * @type String
          */
-        'urlText' : 'This field should be a URL in the format "http:/'+'/www.domain.com"',
+        urlText : 'This field should be a URL in the format "http:/'+'/www.domain.com"',
         
         /**
          * The function used to validate alpha values
          * @param {String} value The value
          */
-        'alpha' : function(v){
+        alpha : function(v){
             return alpha.test(v);
         },
         /**
          * The error text to display when the alpha validation function returns false
          * @type String
          */
-        'alphaText' : 'This field should only contain letters and _',
+        alphaText : 'This field should only contain letters and _',
         /**
          * The keystroke filter mask to be applied on alpha input
          * @type RegExp
          */
-        'alphaMask' : /[a-z_]/i,
+        alphaMask : /[a-z_]/i,
 
         /**
          * The function used to validate alphanumeric values
          * @param {String} value The value
          */
-        'alphanum' : function(v){
+        alphanum : function(v){
             return alphanum.test(v);
         },
         /**
          * The error text to display when the alphanumeric validation function returns false
          * @type String
          */
-        'alphanumText' : 'This field should only contain letters, numbers and _',
+        alphanumText : 'This field should only contain letters, numbers and _',
         /**
          * The keystroke filter mask to be applied on alphanumeric input
          * @type RegExp
          */
-        'alphanumMask' : /[a-z0-9_]/i
+        alphanumMask : /[a-z0-9_]/i
     };
 }();//<script type="text/javascript">
 
@@ -56333,16 +59109,30 @@ Roo.extend(Roo.form.ComboCheck, Roo.form.ComboBox, {
         this.view.singleSelect = false;
         this.view.multiSelect = true;
         this.view.toggleSelect = true;
-        this.pageTb.add(new Roo.Toolbar.Fill(), {
+        this.pageTb.add(new Roo.Toolbar.Fill(),{
             
+            text: 'Select All',
+            handler: function() {
+                _t.selectAll();
+            }
+        },
+        {
             text: 'Done',
-            handler: function()
-            {
+            handler: function() {
                 _t.collapse();
             }
         });
     },
     
+    cleanLeadingSpace : function(e)
+    {
+        // this is disabled, as it retriggers setvalue on blur
+        return;
+    },
+    doForce : function() {
+        // no idea what this did, but it blanks out our values.
+        return;
+    },
     onViewOver : function(e, t){
         // do nothing...
         return;
@@ -56375,7 +59165,17 @@ Roo.extend(Roo.form.ComboCheck, Roo.form.ComboBox, {
         return false;
     },
     
-    
+    selectAll : function()
+    {
+        var sels = [];
+        this.store.each(function(r,i) {
+            sels.push(i);
+        });
+        this.view.select(sels);
+        this.collapse();
+        return false;
+
+    },
     
     onSelect : function(record, index){
        // Roo.log("onselect Called");
@@ -57826,7 +60626,7 @@ Roo.extend(Roo.DDView, Roo.View, {
                }
     }
 });
-/*
+Roo.layout = {};/*
  * Based on:
  * Ext JS Library 1.1.1
  * Copyright(c) 2006-2007, Ext JS, LLC.
@@ -57838,12 +60638,12 @@ Roo.extend(Roo.DDView, Roo.View, {
  */
  
 /**
- * @class Roo.LayoutManager
+ * @class Roo.layout.Manager
  * @extends Roo.util.Observable
  * Base class for layout managers.
  */
-Roo.LayoutManager = function(container, config){
-    Roo.LayoutManager.superclass.constructor.call(this);
+Roo.layout.Manager = function(container, config){
+    Roo.layout.Manager.superclass.constructor.call(this);
     this.el = Roo.get(container);
     // ie scrollbar fix
     if(this.el.dom == document.body && Roo.isIE && !config.allowScroll){
@@ -57860,26 +60660,26 @@ Roo.LayoutManager = function(container, config){
         /**
          * @event layout
          * Fires when a layout is performed. 
-         * @param {Roo.LayoutManager} this
+         * @param {Roo.layout.Manager} this
          */
         "layout" : true,
         /**
          * @event regionresized
          * Fires when the user resizes a region. 
-         * @param {Roo.LayoutRegion} region The resized region
+         * @param {Roo.layout.Region} region The resized region
          * @param {Number} newSize The new size (width for east/west, height for north/south)
          */
         "regionresized" : true,
         /**
          * @event regioncollapsed
          * Fires when a region is collapsed. 
-         * @param {Roo.LayoutRegion} region The collapsed region
+         * @param {Roo.layout.Region} region The collapsed region
          */
         "regioncollapsed" : true,
         /**
          * @event regionexpanded
          * Fires when a region is expanded.  
-         * @param {Roo.LayoutRegion} region The expanded region
+         * @param {Roo.layout.Region} region The expanded region
          */
         "regionexpanded" : true
     });
@@ -57887,7 +60687,7 @@ Roo.LayoutManager = function(container, config){
     Roo.EventManager.onWindowResize(this.onWindowResize, this, true);
 };
 
-Roo.extend(Roo.LayoutManager, Roo.util.Observable, {
+Roo.extend(Roo.layout.Manager, Roo.util.Observable, {
     /**
      * Returns true if this layout is currently being updated
      * @return {Boolean}
@@ -57960,7 +60760,7 @@ Roo.extend(Roo.LayoutManager, Roo.util.Observable, {
     /**
      * Returns the specified region.
      * @param {String} target The region key ('center', 'north', 'south', 'east' or 'west')
-     * @return {Roo.LayoutRegion}
+     * @return {Roo.layout.Region}
      */
     getRegion : function(target){
         return this.regions[target.toLowerCase()];
@@ -57982,16 +60782,16 @@ Roo.extend(Roo.LayoutManager, Roo.util.Observable, {
  * <script type="text/javascript">
  */
 /**
- * @class Roo.BorderLayout
- * @extends Roo.LayoutManager
- * @children Roo.ContentPanel
+ * @class Roo.layout.Border
+ * @extends Roo.layout.Manager
+ * @children Roo.panel.Content
  * This class represents a common layout manager used in desktop applications. For screenshots and more details,
  * please see: <br><br>
  * <a href="http://www.jackslocum.com/yui/2006/10/19/cross-browser-web-20-layouts-with-yahoo-ui/">Cross Browser Layouts - Part 1</a><br>
  * <a href="http://www.jackslocum.com/yui/2006/10/28/cross-browser-web-20-layouts-part-2-ajax-feed-viewer-20/">Cross Browser Layouts - Part 2</a><br><br>
  * Example:
  <pre><code>
- var layout = new Roo.BorderLayout(document.body, {
+ var layout = new Roo.layout.Border(document.body, {
     north: {
         initialSize: 25,
         titlebar: false
@@ -58030,7 +60830,7 @@ Roo.extend(Roo.LayoutManager, Roo.util.Observable, {
 });
 
 // shorthand
-var CP = Roo.ContentPanel;
+var CP = Roo.panel.Content;
 
 layout.beginUpdate();
 layout.add("north", new CP("north", "North"));
@@ -58053,10 +60853,10 @@ the container size if it is not the body element.</b>
 * @param {String/HTMLElement/Element} container The container this layout is bound to
 * @param {Object} config Configuration options
  */
-Roo.BorderLayout = function(container, config){
+Roo.layout.Border = function(container, config){
     config = config || {};
-    Roo.BorderLayout.superclass.constructor.call(this, container, config);
-    this.factory = config.factory || Roo.BorderLayout.RegionFactory;
+    Roo.layout.Border.superclass.constructor.call(this, container, config);
+    this.factory = config.factory || Roo.layout.Border.RegionFactory;
     for(var i = 0, len = this.factory.validRegions.length; i < len; i++) {
        var target = this.factory.validRegions[i];
        if(config[target]){
@@ -58065,22 +60865,22 @@ Roo.BorderLayout = function(container, config){
     }
 };
 
-Roo.extend(Roo.BorderLayout, Roo.LayoutManager, {
+Roo.extend(Roo.layout.Border, Roo.layout.Manager, {
        
        /**
-        * @cfg {Roo.LayoutRegion} east
+        * @cfg {Roo.layout.Region} east
         */
        /**
-        * @cfg {Roo.LayoutRegion} west
+        * @cfg {Roo.layout.Region} west
         */
        /**
-        * @cfg {Roo.LayoutRegion} north
+        * @cfg {Roo.layout.Region} north
         */
        /**
-        * @cfg {Roo.LayoutRegion} south
+        * @cfg {Roo.layout.Region} south
         */
        /**
-        * @cfg {Roo.LayoutRegion} center
+        * @cfg {Roo.layout.Region} center
         */
     /**
      * Creates and adds a new region if it doesn't already exist.
@@ -58201,8 +61001,8 @@ Roo.extend(Roo.BorderLayout, Roo.LayoutManager, {
     /**
      * Adds a ContentPanel (or subclass) to this layout.
      * @param {String} target The target region key (north, south, east, west or center).
-     * @param {Roo.ContentPanel} panel The panel to add
-     * @return {Roo.ContentPanel} The added panel
+     * @param {Roo.panel.Content} panel The panel to add
+     * @return {Roo.panel.Content} The added panel
      */
     add : function(target, panel){
          
@@ -58213,8 +61013,8 @@ Roo.extend(Roo.BorderLayout, Roo.LayoutManager, {
     /**
      * Remove a ContentPanel (or subclass) to this layout.
      * @param {String} target The target region key (north, south, east, west or center).
-     * @param {Number/String/Roo.ContentPanel} panel The index, id or panel to remove
-     * @return {Roo.ContentPanel} The removed panel
+     * @param {Number/String/Roo.panel.Content} panel The index, id or panel to remove
+     * @return {Roo.panel.Content} The removed panel
      */
     remove : function(target, panel){
         target = target.toLowerCase();
@@ -58224,7 +61024,7 @@ Roo.extend(Roo.BorderLayout, Roo.LayoutManager, {
     /**
      * Searches all regions for a panel with the specified id
      * @param {String} panelId
-     * @return {Roo.ContentPanel} The panel or null if it wasn't found
+     * @return {Roo.panel.Content} The panel or null if it wasn't found
      */
     findPanel : function(panelId){
         var rs = this.regions;
@@ -58241,8 +61041,8 @@ Roo.extend(Roo.BorderLayout, Roo.LayoutManager, {
 
     /**
      * Searches all regions for a panel with the specified id and activates (shows) it.
-     * @param {String/ContentPanel} panelId The panels id or the panel itself
-     * @return {Roo.ContentPanel} The shown panel or null
+     * @param {String/panel.Content} panelId The panels id or the panel itself
+     * @return {Roo.panel.Content} The shown panel or null
      */
     showPanel : function(panelId) {
       var rs = this.regions;
@@ -58265,7 +61065,7 @@ Roo.extend(Roo.BorderLayout, Roo.LayoutManager, {
         if(!provider){
             provider = Roo.state.Manager;
         }
-        var sm = new Roo.LayoutStateManager();
+        var sm = new Roo.layout.StateManager();
         sm.init(this, provider);
     },
 
@@ -58275,7 +61075,7 @@ Roo.extend(Roo.BorderLayout, Roo.LayoutManager, {
      * a valid ContentPanel config object.  Example:
      * <pre><code>
 // Create the main layout
-var layout = new Roo.BorderLayout('main-ct', {
+var layout = new Roo.layout.Border('main-ct', {
     west: {
         split:true,
         minSize: 175,
@@ -58320,7 +61120,7 @@ layout.batchAdd({
     // private
     addTypedPanels : function(lr, ps){
         if(typeof ps == 'string'){
-            lr.add(new Roo.ContentPanel(ps));
+            lr.add(new Roo.panel.Content(ps));
         }
         else if(ps instanceof Array){
             for(var i =0, len = ps.length; i < len; i++){
@@ -58330,7 +61130,7 @@ layout.batchAdd({
         else if(!ps.events){ // raw config?
             var el = ps.el;
             delete ps.el; // prevent conflict
-            lr.add(new Roo.ContentPanel(el || Roo.id(), ps));
+            lr.add(new Roo.panel.Content(el || Roo.id(), ps));
         }
         else {  // panel object assumed!
             lr.add(ps);
@@ -58364,13 +61164,13 @@ layout.addxtype({
     {
         // basically accepts a pannel...
         // can accept a layout region..!?!?
-        //Roo.log('Roo.BorderLayout add ' + cfg.xtype)
+        //Roo.log('Roo.layout.Border add ' + cfg.xtype)
         
-        if (!cfg.xtype.match(/Panel$/)) {
-            return false;
-        }
+        // if (!cfg.xtype.match(/Panel$/)) {
+        //     return false;
+        // }
         var ret = false;
-        
+
         if (typeof(cfg.region) == 'undefined') {
             Roo.log("Failed to add Panel, region was not set");
             Roo.log(cfg);
@@ -58389,7 +61189,72 @@ layout.addxtype({
         
         switch(cfg.xtype) 
         {
-            case 'ContentPanel':  // ContentPanel (el, cfg)
+            case 'Content':
+                if(cfg.autoCreate) {
+                    ret = new Roo.panel[cfg.xtype](cfg); // new panel!!!!!
+                } else {
+                    var el = this.el.createChild();
+                    ret = new Roo.panel[cfg.xtype](el, cfg); // new panel!!!!!
+                }
+                
+                this.add(region, ret);
+                break;
+            case 'Grid':
+                // needs grid and region
+                
+                //var el = this.getRegion(region).el.createChild();
+                var el = this.el.createChild();
+                // create the grid first...
+                
+                var grid = new Roo.grid[cfg.grid.xtype](el, cfg.grid);
+                delete cfg.grid;
+                if (region == 'center' && this.active ) {
+                    cfg.background = false;
+                }
+                ret = new Roo.panel[cfg.xtype](grid, cfg); // new panel!!!!!
+                
+                this.add(region, ret);
+                if (cfg.background) {
+                    ret.on('activate', function(gp) {
+                        if (!gp.grid.rendered) {
+                            gp.grid.render();
+                        }
+                    });
+                } else {
+                    grid.render();
+                }
+                break;
+            case 'NestedLayout': 
+                // create a new Layout (which is  a Border Layout...
+                var el = this.el.createChild();
+                var clayout = cfg.layout;
+                delete cfg.layout;
+                clayout.items   = clayout.items  || [];
+                // replace this exitems with the clayout ones..
+                xitems = clayout.items;
+                 
+                
+                if (region == 'center' && this.active && this.getRegion('center').panels.length < 1) {
+                    cfg.background = false;
+                }
+                var layout = new Roo.layout.Border(el, clayout);
+                
+                ret = new Roo.panel[cfg.xtype](layout, cfg); // new panel!!!!!
+                //console.log('adding nested layout panel '  + cfg.toSource());
+                this.add(region, ret);
+                nb = {}; /// find first...
+                break;
+                
+            case 'Calendar':
+                ret = new Roo.panel[cfg.xtype](cfg); // new panel!!!!!
+                this.add(region, ret);
+                break;
+            case 'Tree': // our new panel!
+                cfg.el = this.el.createChild();
+                ret = new Roo.panel[cfg.xtype](cfg); // new panel!!!!!
+                this.add(region, ret);
+                break;
+            case 'ContentPanel':
             case 'ScrollPanel':  // ContentPanel (el, cfg)
             case 'ViewPanel': 
                 if(cfg.autoCreate) {
@@ -58422,7 +61287,7 @@ layout.addxtype({
                 if (region == 'center' && this.active && this.getRegion('center').panels.length < 1) {
                     cfg.background = false;
                 }
-                var layout = new Roo.BorderLayout(el, clayout);
+                var layout = new Roo.layout.Border(el, clayout);
                 
                 ret = new Roo[cfg.xtype](layout, cfg); // new panel!!!!!
                 //console.log('adding nested layout panel '  + cfg.toSource());
@@ -58523,7 +61388,7 @@ layout.addxtype({
 // shorthand
 var CP = Roo.ContentPanel;
 
-var layout = Roo.BorderLayout.create({
+var layout = Roo.layout.Border.create({
     north: {
         initialSize: 25,
         titlebar: false,
@@ -58574,10 +61439,10 @@ layout.getRegion("center").showPanel("center1");
  * @param config
  * @param targetEl
  */
-Roo.BorderLayout.create = function(config, targetEl){
-    var layout = new Roo.BorderLayout(targetEl || document.body, config);
+Roo.layout.Border.create = function(config, targetEl){
+    var layout = new Roo.layout.Border(targetEl || document.body, config);
     layout.beginUpdate();
-    var regions = Roo.BorderLayout.RegionFactory.validRegions;
+    var regions = Roo.layout.Border.RegionFactory.validRegions;
     for(var j = 0, jlen = regions.length; j < jlen; j++){
         var lr = regions[j];
         if(layout.regions[lr] && config[lr].panels){
@@ -58591,7 +61456,7 @@ Roo.BorderLayout.create = function(config, targetEl){
 };
 
 // private
-Roo.BorderLayout.RegionFactory = {
+Roo.layout.Border.RegionFactory = {
     // private
     validRegions : ["north","south","east","west","center"],
 
@@ -58599,21 +61464,15 @@ Roo.BorderLayout.RegionFactory = {
     create : function(target, mgr, config){
         target = target.toLowerCase();
         if(config.lightweight || config.basic){
-            return new Roo.BasicLayoutRegion(mgr, config, target);
-        }
-        switch(target){
-            case "north":
-                return new Roo.NorthLayoutRegion(mgr, config);
-            case "south":
-                return new Roo.SouthLayoutRegion(mgr, config);
-            case "east":
-                return new Roo.EastLayoutRegion(mgr, config);
-            case "west":
-                return new Roo.WestLayoutRegion(mgr, config);
-            case "center":
-                return new Roo.CenterLayoutRegion(mgr, config);
+            return new Roo.layout.BasicRegion(mgr, config, target);
         }
-        throw 'Layout region "'+target+'" not supported.';
+               var cn = target.charAt(0).toUpperCase() + target.slice(1);
+               if (typeof (Roo.layout[cn]) == 'undefined') {
+                       throw 'Layout region "'+target+'" not supported.';
+               }
+               return new Roo.layout[cn](mgr, config);
+         
+        
     }
 };/*
  * Based on:
@@ -58627,96 +61486,96 @@ Roo.BorderLayout.RegionFactory = {
  */
  
 /**
- * @class Roo.BasicLayoutRegion
+ * @class Roo.layout.BasicRegion
  * @extends Roo.util.Observable
  * This class represents a lightweight region in a layout manager. This region does not move dom nodes
  * and does not have a titlebar, tabs or any other features. All it does is size and position 
  * panels. To create a BasicLayoutRegion, add lightweight:true or basic:true to your regions config.
  */
-Roo.BasicLayoutRegion = function(mgr, config, pos, skipConfig){
+Roo.layout.BasicRegion= function(mgr, config, pos, skipConfig){
     this.mgr = mgr;
     this.position  = pos;
     this.events = {
         /**
-         * @scope Roo.BasicLayoutRegion
+         * @scope Roo.layout.BasicRegion
          */
         
         /**
          * @event beforeremove
          * Fires before a panel is removed (or closed). To cancel the removal set "e.cancel = true" on the event argument.
-         * @param {Roo.LayoutRegion} this
-         * @param {Roo.ContentPanel} panel The panel
+         * @param {Roo.layout.Region} this
+         * @param {Roo.panel.Content} panel The panel
          * @param {Object} e The cancel event object
          */
         "beforeremove" : true,
         /**
          * @event invalidated
          * Fires when the layout for this region is changed.
-         * @param {Roo.LayoutRegion} this
+         * @param {Roo.layout.Region} this
          */
         "invalidated" : true,
         /**
          * @event visibilitychange
          * Fires when this region is shown or hidden 
-         * @param {Roo.LayoutRegion} this
+         * @param {Roo.layout.Region} this
          * @param {Boolean} visibility true or false
          */
         "visibilitychange" : true,
         /**
          * @event paneladded
          * Fires when a panel is added. 
-         * @param {Roo.LayoutRegion} this
-         * @param {Roo.ContentPanel} panel The panel
+         * @param {Roo.layout.Region} this
+         * @param {Roo.panel.Content} panel The panel
          */
         "paneladded" : true,
         /**
          * @event panelremoved
          * Fires when a panel is removed. 
-         * @param {Roo.LayoutRegion} this
-         * @param {Roo.ContentPanel} panel The panel
+         * @param {Roo.layout.Region} this
+         * @param {Roo.panel.Content} panel The panel
          */
         "panelremoved" : true,
         /**
          * @event beforecollapse
          * Fires when this region before collapse.
-         * @param {Roo.LayoutRegion} this
+         * @param {Roo.layout.Region} this
          */
         "beforecollapse" : true,
         /**
          * @event collapsed
          * Fires when this region is collapsed.
-         * @param {Roo.LayoutRegion} this
+         * @param {Roo.layout.Region} this
          */
         "collapsed" : true,
         /**
          * @event expanded
          * Fires when this region is expanded.
-         * @param {Roo.LayoutRegion} this
+         * @param {Roo.layout.Region} this
          */
         "expanded" : true,
         /**
          * @event slideshow
          * Fires when this region is slid into view.
-         * @param {Roo.LayoutRegion} this
+         * @param {Roo.layout.Region} this
          */
         "slideshow" : true,
         /**
          * @event slidehide
          * Fires when this region slides out of view. 
-         * @param {Roo.LayoutRegion} this
+         * @param {Roo.layout.Region} this
          */
         "slidehide" : true,
         /**
          * @event panelactivated
          * Fires when a panel is activated. 
-         * @param {Roo.LayoutRegion} this
-         * @param {Roo.ContentPanel} panel The activated panel
+         * @param {Roo.layout.Region} this
+         * @param {Roo.panel.Content} panel The activated panel
          */
         "panelactivated" : true,
         /**
          * @event resized
          * Fires when the user resizes this region. 
-         * @param {Roo.LayoutRegion} this
+         * @param {Roo.layout.Region} this
          * @param {Number} newSize The new size (width for east/west, height for north/south)
          */
         "resized" : true
@@ -58729,7 +61588,7 @@ Roo.BasicLayoutRegion = function(mgr, config, pos, skipConfig){
     // ensure listeners are added...
     
     if (config.listeners || config.events) {
-        Roo.BasicLayoutRegion.superclass.constructor.call(this, {
+        Roo.layout.BasicRegion.superclass.constructor.call(this, {
             listeners : config.listeners || {},
             events : config.events || {}
         });
@@ -58740,7 +61599,7 @@ Roo.BasicLayoutRegion = function(mgr, config, pos, skipConfig){
     }
 };
 
-Roo.extend(Roo.BasicLayoutRegion, Roo.util.Observable, {
+Roo.extend(Roo.layout.BasicRegion, Roo.util.Observable, {
     getPanelId : function(p){
         return p.getId();
     },
@@ -58824,8 +61683,8 @@ Roo.extend(Roo.BasicLayoutRegion, Roo.util.Observable, {
     
     /**
      * Show the specified panel.
-     * @param {Number/String/ContentPanel} panelId The panels index, id or the panel itself
-     * @return {Roo.ContentPanel} The shown panel or null
+     * @param {Number/String/panel.Content} panelId The panels index, id or the panel itself
+     * @return {Roo.panel.Content} The shown panel or null
      */
     showPanel : function(panel){
         if(panel = this.getPanel(panel)){
@@ -58836,7 +61695,7 @@ Roo.extend(Roo.BasicLayoutRegion, Roo.util.Observable, {
     
     /**
      * Get the active panel for this region.
-     * @return {Roo.ContentPanel} The active panel or null
+     * @return {Roo.panel.Content} The active panel or null
      */
     getActivePanel : function(){
         return this.activePanel;
@@ -58844,8 +61703,8 @@ Roo.extend(Roo.BasicLayoutRegion, Roo.util.Observable, {
     
     /**
      * Add the passed ContentPanel(s)
-     * @param {ContentPanel...} panel The ContentPanel(s) to add (you can pass more than one)
-     * @return {Roo.ContentPanel} The panel added (if only one was added)
+     * @param {panel.Content...} panel The ContentPanel(s) to add (you can pass more than one)
+     * @return {Roo.panel.Content} The panel added (if only one was added)
      */
     add : function(panel){
         if(arguments.length > 1){
@@ -58879,7 +61738,7 @@ Roo.extend(Roo.BasicLayoutRegion, Roo.util.Observable, {
     
     /**
      * Returns true if the panel is in this region.
-     * @param {Number/String/ContentPanel} panel The panels index, id or the panel itself
+     * @param {Number/String/panel.Content} panel The panels index, id or the panel itself
      * @return {Boolean}
      */
     hasPanel : function(panel){
@@ -58891,9 +61750,9 @@ Roo.extend(Roo.BasicLayoutRegion, Roo.util.Observable, {
     
     /**
      * Removes the specified panel. If preservePanel is not true (either here or in the config), the panel is destroyed.
-     * @param {Number/String/ContentPanel} panel The panels index, id or the panel itself
+     * @param {Number/String/panel.Content} panel The panels index, id or the panel itself
      * @param {Boolean} preservePanel Overrides the config preservePanel option
-     * @return {Roo.ContentPanel} The panel that was removed
+     * @return {Roo.panel.Content} The panel that was removed
      */
     remove : function(panel, preservePanel){
         panel = this.getPanel(panel);
@@ -58912,8 +61771,8 @@ Roo.extend(Roo.BasicLayoutRegion, Roo.util.Observable, {
     
     /**
      * Returns the panel specified or null if it's not in this region.
-     * @param {Number/String/ContentPanel} panel The panels index, id or the panel itself
-     * @return {Roo.ContentPanel}
+     * @param {Number/String/panel.Content} panel The panels index, id or the panel itself
+     * @return {Roo.panel.Content}
      */
     getPanel : function(id){
         if(typeof id == "object"){ // must be panel obj
@@ -58941,8 +61800,8 @@ Roo.extend(Roo.BasicLayoutRegion, Roo.util.Observable, {
  */
  
 /**
- * @class Roo.LayoutRegion
- * @extends Roo.BasicLayoutRegion
+ * @class Roo.layout.Region
+ * @extends Roo.layout.BasicRegion
  * This class represents a region in a layout manager.
  * @cfg {Boolean}   collapsible     False to disable collapsing (defaults to true)
  * @cfg {Boolean}   collapsed       True to set the initial display to collapsed (defaults to false)
@@ -58973,8 +61832,8 @@ Roo.extend(Roo.BasicLayoutRegion, Roo.util.Observable, {
  * @cfg {Boolean}   split           To show the splitter
  * @cfg {Boolean}   toolbar         xtype configuration for a toolbar - shows on right of tabbar
  */
-Roo.LayoutRegion = function(mgr, config, pos){
-    Roo.LayoutRegion.superclass.constructor.call(this, mgr, config, pos, true);
+Roo.layout.Region = function(mgr, config, pos){
+    Roo.layout.Region.superclass.constructor.call(this, mgr, config, pos, true);
     var dh = Roo.DomHelper;
     /** This region's container element 
     * @type Roo.Element */
@@ -59008,7 +61867,7 @@ Roo.LayoutRegion = function(mgr, config, pos){
     this.applyConfig(config);
 };
 
-Roo.extend(Roo.LayoutRegion, Roo.BasicLayoutRegion, {
+Roo.extend(Roo.layout.Region, Roo.layout.BasicRegion, {
 
     createBody : function(){
         /** This region's body element 
@@ -59300,7 +62159,7 @@ Roo.extend(Roo.LayoutRegion, Roo.BasicLayoutRegion, {
     initTabs : function()
     {
         this.bodyEl.setStyle("overflow", "hidden");
-        var ts = new Roo.TabPanel(
+        var ts = new Roo.panel.Tab(
                 this.bodyEl.dom,
                 {
                     tabPosition: this.bottomTabs ? 'bottom' : 'top',
@@ -59381,8 +62240,8 @@ Roo.extend(Roo.LayoutRegion, Roo.BasicLayoutRegion, {
 
     /**
      * Shows the specified panel.
-     * @param {Number/String/ContentPanel} panelId The panel's index, id or the panel itself
-     * @return {Roo.ContentPanel} The shown panel, or null if a panel could not be found from panelId
+     * @param {Number/String/panel.Content} panelId The panel's index, id or the panel itself
+     * @return {Roo.panel.Content} The shown panel, or null if a panel could not be found from panelId
      */
     showPanel : function(panel)
     {
@@ -59403,7 +62262,7 @@ Roo.extend(Roo.LayoutRegion, Roo.BasicLayoutRegion, {
 
     /**
      * Get the active panel for this region.
-     * @return {Roo.ContentPanel} The active panel or null
+     * @return {Roo.panel.Content} The active panel or null
      */
     getActivePanel : function(){
         return this.activePanel;
@@ -59423,8 +62282,8 @@ Roo.extend(Roo.LayoutRegion, Roo.BasicLayoutRegion, {
 
     /**
      * Adds the passed ContentPanel(s) to this region.
-     * @param {ContentPanel...} panel The ContentPanel(s) to add (you can pass more than one)
-     * @return {Roo.ContentPanel} The panel added (if only one was added; null otherwise)
+     * @param {panel.Content...} panel The ContentPanel(s) to add (you can pass more than one)
+     * @return {Roo.panel.Content} The panel added (if only one was added; null otherwise)
      */
     add : function(panel){
         if(arguments.length > 1){
@@ -59461,7 +62320,7 @@ Roo.extend(Roo.LayoutRegion, Roo.BasicLayoutRegion, {
 
     /**
      * Hides the tab for the specified panel.
-     * @param {Number/String/ContentPanel} panel The panel's index, id or the panel itself
+     * @param {Number/String/panel.Content} panel The panel's index, id or the panel itself
      */
     hidePanel : function(panel){
         if(this.tabs && (panel = this.getPanel(panel))){
@@ -59471,7 +62330,7 @@ Roo.extend(Roo.LayoutRegion, Roo.BasicLayoutRegion, {
 
     /**
      * Unhides the tab for a previously hidden panel.
-     * @param {Number/String/ContentPanel} panel The panel's index, id or the panel itself
+     * @param {Number/String/panel.Content} panel The panel's index, id or the panel itself
      */
     unhidePanel : function(panel){
         if(this.tabs && (panel = this.getPanel(panel))){
@@ -59487,9 +62346,9 @@ Roo.extend(Roo.LayoutRegion, Roo.BasicLayoutRegion, {
 
     /**
      * Removes the specified panel. If preservePanel is not true (either here or in the config), the panel is destroyed.
-     * @param {Number/String/ContentPanel} panel The panel's index, id or the panel itself
+     * @param {Number/String/panel.Content} panel The panel's index, id or the panel itself
      * @param {Boolean} preservePanel Overrides the config preservePanel option
-     * @return {Roo.ContentPanel} The panel that was removed
+     * @return {Roo.panel.Content} The panel that was removed
      */
     remove : function(panel, preservePanel){
         panel = this.getPanel(panel);
@@ -59537,7 +62396,7 @@ Roo.extend(Roo.LayoutRegion, Roo.BasicLayoutRegion, {
 
     /**
      * Returns the TabPanel component used by this region
-     * @return {Roo.TabPanel}
+     * @return {Roo.panel.Tab}
      */
     getTabs : function(){
         return this.tabs;
@@ -59563,22 +62422,22 @@ Roo.extend(Roo.LayoutRegion, Roo.BasicLayoutRegion, {
 
 
 /**
- * @class Roo.SplitLayoutRegion
- * @extends Roo.LayoutRegion
- * Adds a splitbar and other (private) useful functionality to a {@link Roo.LayoutRegion}.
+ * @class Roo.layout.SplitRegion
+ * @extends Roo.layout.Region
+ * Adds a splitbar and other (private) useful functionality to a {@link Roo.layout.Region}.
  */
-Roo.SplitLayoutRegion = function(mgr, config, pos, cursor){
+Roo.layout.SplitRegion = function(mgr, config, pos, cursor){
     this.cursor = cursor;
-    Roo.SplitLayoutRegion.superclass.constructor.call(this, mgr, config, pos);
+    Roo.layout.SplitRegion.superclass.constructor.call(this, mgr, config, pos);
 };
 
-Roo.extend(Roo.SplitLayoutRegion, Roo.LayoutRegion, {
+Roo.extend(Roo.layout.SplitRegion, Roo.layout.Region, {
     splitTip : "Drag to resize.",
     collapsibleSplitTip : "Drag to resize. Double click to hide.",
     useSplitTips : false,
 
     applyConfig : function(config){
-        Roo.SplitLayoutRegion.superclass.applyConfig.call(this, config);
+        Roo.layout.SplitRegion.superclass.applyConfig.call(this, config);
         if(config.split){
             if(!this.split){
                 var splitEl = Roo.DomHelper.append(this.mgr.el.dom, 
@@ -59634,7 +62493,7 @@ Roo.extend(Roo.SplitLayoutRegion, Roo.LayoutRegion, {
     
     hide : function(){
         this.hideSplitter();
-        Roo.SplitLayoutRegion.superclass.hide.call(this);
+        Roo.layout.SplitRegion.superclass.hide.call(this);
     },
 
     hideSplitter : function(){
@@ -59648,7 +62507,7 @@ Roo.extend(Roo.SplitLayoutRegion, Roo.LayoutRegion, {
         if(this.split){
             this.split.el.show();
         }
-        Roo.SplitLayoutRegion.superclass.show.call(this);
+        Roo.layout.SplitRegion.superclass.show.call(this);
     },
     
     beforeSlide: function(){
@@ -59904,14 +62763,14 @@ Roo.extend(Roo.SplitLayoutRegion, Roo.LayoutRegion, {
 /*
  * These classes are private internal classes
  */
-Roo.CenterLayoutRegion = function(mgr, config){
-    Roo.LayoutRegion.call(this, mgr, config, "center");
+Roo.layout.Center = function(mgr, config){
+    Roo.layout.Region.call(this, mgr, config, "center");
     this.visible = true;
     this.minWidth = config.minWidth || 20;
     this.minHeight = config.minHeight || 20;
 };
 
-Roo.extend(Roo.CenterLayoutRegion, Roo.LayoutRegion, {
+Roo.extend(Roo.layout.Center, Roo.layout.Region, {
     hide : function(){
         // center panel can't be hidden
     },
@@ -59928,173 +62787,168 @@ Roo.extend(Roo.CenterLayoutRegion, Roo.LayoutRegion, {
         return this.minHeight;
     }
 });
-
-
-Roo.NorthLayoutRegion = function(mgr, config){
-    Roo.LayoutRegion.call(this, mgr, config, "north", "n-resize");
+Roo.layout.West = function(mgr, config){
+    Roo.layout.SplitRegion.call(this, mgr, config, "west", "w-resize");
     if(this.split){
-        this.split.placement = Roo.SplitBar.TOP;
-        this.split.orientation = Roo.SplitBar.VERTICAL;
-        this.split.el.addClass("x-layout-split-v");
+        this.split.placement = Roo.SplitBar.LEFT;
+        this.split.orientation = Roo.SplitBar.HORIZONTAL;
+        this.split.el.addClass("x-layout-split-h");
     }
-    var size = config.initialSize || config.height;
+    var size = config.initialSize || config.width;
     if(typeof size != "undefined"){
-        this.el.setHeight(size);
+        this.el.setWidth(size);
     }
 };
-Roo.extend(Roo.NorthLayoutRegion, Roo.SplitLayoutRegion, {
-    orientation: Roo.SplitBar.VERTICAL,
+Roo.extend(Roo.layout.West, Roo.layout.SplitRegion, {
+    orientation: Roo.SplitBar.HORIZONTAL,
     getBox : function(){
         if(this.collapsed){
             return this.collapsedEl.getBox();
         }
         var box = this.el.getBox();
         if(this.split){
-            box.height += this.split.el.getHeight();
+            box.width += this.split.el.getWidth();
         }
         return box;
     },
     
     updateBox : function(box){
         if(this.split && !this.collapsed){
-            box.height -= this.split.el.getHeight();
-            this.split.el.setLeft(box.x);
-            this.split.el.setTop(box.y+box.height);
-            this.split.el.setWidth(box.width);
+            var sw = this.split.el.getWidth();
+            box.width -= sw;
+            this.split.el.setLeft(box.x+box.width);
+            this.split.el.setTop(box.y);
+            this.split.el.setHeight(box.height);
         }
         if(this.collapsed){
-            this.updateBody(box.width, null);
+            this.updateBody(null, box.height);
         }
-        Roo.LayoutRegion.prototype.updateBox.call(this, box);
+        Roo.layout.Region.prototype.updateBox.call(this, box);
     }
 });
-
-Roo.SouthLayoutRegion = function(mgr, config){
-    Roo.SplitLayoutRegion.call(this, mgr, config, "south", "s-resize");
+Roo.layout.East = function(mgr, config){
+    Roo.layout.SplitRegion.call(this, mgr, config, "east", "e-resize");
     if(this.split){
-        this.split.placement = Roo.SplitBar.BOTTOM;
-        this.split.orientation = Roo.SplitBar.VERTICAL;
-        this.split.el.addClass("x-layout-split-v");
+        this.split.placement = Roo.SplitBar.RIGHT;
+        this.split.orientation = Roo.SplitBar.HORIZONTAL;
+        this.split.el.addClass("x-layout-split-h");
     }
-    var size = config.initialSize || config.height;
+    var size = config.initialSize || config.width;
     if(typeof size != "undefined"){
-        this.el.setHeight(size);
+        this.el.setWidth(size);
     }
 };
-Roo.extend(Roo.SouthLayoutRegion, Roo.SplitLayoutRegion, {
-    orientation: Roo.SplitBar.VERTICAL,
+Roo.extend(Roo.layout.East, Roo.layout.SplitRegion, {
+    orientation: Roo.SplitBar.HORIZONTAL,
     getBox : function(){
         if(this.collapsed){
             return this.collapsedEl.getBox();
         }
         var box = this.el.getBox();
         if(this.split){
-            var sh = this.split.el.getHeight();
-            box.height += sh;
-            box.y -= sh;
+            var sw = this.split.el.getWidth();
+            box.width += sw;
+            box.x -= sw;
         }
         return box;
     },
-    
+
     updateBox : function(box){
         if(this.split && !this.collapsed){
-            var sh = this.split.el.getHeight();
-            box.height -= sh;
-            box.y += sh;
+            var sw = this.split.el.getWidth();
+            box.width -= sw;
             this.split.el.setLeft(box.x);
-            this.split.el.setTop(box.y-sh);
-            this.split.el.setWidth(box.width);
+            this.split.el.setTop(box.y);
+            this.split.el.setHeight(box.height);
+            box.x += sw;
         }
         if(this.collapsed){
-            this.updateBody(box.width, null);
+            this.updateBody(null, box.height);
         }
-        Roo.LayoutRegion.prototype.updateBox.call(this, box);
+        Roo.layout.Region.prototype.updateBox.call(this, box);
     }
-});
-
-Roo.EastLayoutRegion = function(mgr, config){
-    Roo.SplitLayoutRegion.call(this, mgr, config, "east", "e-resize");
+});Roo.layout.South = function(mgr, config){
+    Roo.layout.SplitRegion.call(this, mgr, config, "south", "s-resize");
     if(this.split){
-        this.split.placement = Roo.SplitBar.RIGHT;
-        this.split.orientation = Roo.SplitBar.HORIZONTAL;
-        this.split.el.addClass("x-layout-split-h");
+        this.split.placement = Roo.SplitBar.BOTTOM;
+        this.split.orientation = Roo.SplitBar.VERTICAL;
+        this.split.el.addClass("x-layout-split-v");
     }
-    var size = config.initialSize || config.width;
+    var size = config.initialSize || config.height;
     if(typeof size != "undefined"){
-        this.el.setWidth(size);
+        this.el.setHeight(size);
     }
 };
-Roo.extend(Roo.EastLayoutRegion, Roo.SplitLayoutRegion, {
-    orientation: Roo.SplitBar.HORIZONTAL,
+Roo.extend(Roo.layout.South, Roo.layout.SplitRegion, {
+    orientation: Roo.SplitBar.VERTICAL,
     getBox : function(){
         if(this.collapsed){
             return this.collapsedEl.getBox();
         }
         var box = this.el.getBox();
         if(this.split){
-            var sw = this.split.el.getWidth();
-            box.width += sw;
-            box.x -= sw;
+            var sh = this.split.el.getHeight();
+            box.height += sh;
+            box.y -= sh;
         }
         return box;
     },
-
+    
     updateBox : function(box){
         if(this.split && !this.collapsed){
-            var sw = this.split.el.getWidth();
-            box.width -= sw;
+            var sh = this.split.el.getHeight();
+            box.height -= sh;
+            box.y += sh;
             this.split.el.setLeft(box.x);
-            this.split.el.setTop(box.y);
-            this.split.el.setHeight(box.height);
-            box.x += sw;
+            this.split.el.setTop(box.y-sh);
+            this.split.el.setWidth(box.width);
         }
         if(this.collapsed){
-            this.updateBody(null, box.height);
+            this.updateBody(box.width, null);
         }
-        Roo.LayoutRegion.prototype.updateBox.call(this, box);
+        Roo.layout.Region.prototype.updateBox.call(this, box);
     }
 });
 
-Roo.WestLayoutRegion = function(mgr, config){
-    Roo.SplitLayoutRegion.call(this, mgr, config, "west", "w-resize");
+
+Roo.layout.North = function(mgr, config){
+    Roo.layout.Region.call(this, mgr, config, "north", "n-resize");
     if(this.split){
-        this.split.placement = Roo.SplitBar.LEFT;
-        this.split.orientation = Roo.SplitBar.HORIZONTAL;
-        this.split.el.addClass("x-layout-split-h");
+        this.split.placement = Roo.SplitBar.TOP;
+        this.split.orientation = Roo.SplitBar.VERTICAL;
+        this.split.el.addClass("x-layout-split-v");
     }
-    var size = config.initialSize || config.width;
+    var size = config.initialSize || config.height;
     if(typeof size != "undefined"){
-        this.el.setWidth(size);
+        this.el.setHeight(size);
     }
 };
-Roo.extend(Roo.WestLayoutRegion, Roo.SplitLayoutRegion, {
-    orientation: Roo.SplitBar.HORIZONTAL,
+Roo.extend(Roo.layout.North, Roo.layout.SplitRegion, {
+    orientation: Roo.SplitBar.VERTICAL,
     getBox : function(){
         if(this.collapsed){
             return this.collapsedEl.getBox();
         }
         var box = this.el.getBox();
         if(this.split){
-            box.width += this.split.el.getWidth();
+            box.height += this.split.el.getHeight();
         }
         return box;
     },
     
     updateBox : function(box){
         if(this.split && !this.collapsed){
-            var sw = this.split.el.getWidth();
-            box.width -= sw;
-            this.split.el.setLeft(box.x+box.width);
-            this.split.el.setTop(box.y);
-            this.split.el.setHeight(box.height);
+            box.height -= this.split.el.getHeight();
+            this.split.el.setLeft(box.x);
+            this.split.el.setTop(box.y+box.height);
+            this.split.el.setWidth(box.width);
         }
         if(this.collapsed){
-            this.updateBody(null, box.height);
+            this.updateBody(box.width, null);
         }
-        Roo.LayoutRegion.prototype.updateBox.call(this, box);
+        Roo.layout.Region.prototype.updateBox.call(this, box);
     }
-});
-/*
+});/*
  * Based on:
  * Ext JS Library 1.1.1
  * Copyright(c) 2006-2007, Ext JS, LLC.
@@ -60109,7 +62963,7 @@ Roo.extend(Roo.WestLayoutRegion, Roo.SplitLayoutRegion, {
 /*
  * Private internal class for reading and applying state
  */
-Roo.LayoutStateManager = function(layout){
+Roo.layout.StateManager = function(layout){
      // default empty state
      this.state = {
         north: {},
@@ -60119,7 +62973,7 @@ Roo.LayoutStateManager = function(layout){
     };
 };
 
-Roo.LayoutStateManager.prototype = {
+Roo.layout.StateManager.prototype = {
     init : function(layout, provider){
         this.provider = provider;
         var state = provider.get(layout.id+"-layout-state");
@@ -60184,11 +63038,11 @@ Roo.LayoutStateManager.prototype = {
  * <script type="text/javascript">
  */
 /**
- * @class Roo.ContentPanel
+ * @class Roo.panel.Content
  * @extends Roo.util.Observable
  * @children Roo.form.Form Roo.JsonView Roo.View
- * @parent Roo.BorderLayout Roo.LayoutDialog builder
- * A basic ContentPanel element.
+ * @parent Roo.layout.Border Roo.LayoutDialog builder
+ * A basic Content Panel element.
  * @cfg {Boolean}   fitToFrame    True for this panel to adjust its size to fit when the region resizes  (defaults to false)
  * @cfg {Boolean}   fitContainer   When using {@link #fitToFrame} and {@link #resizeEl}, you can also fit the parent container  (defaults to false)
  * @cfg {Boolean|Object} autoCreate True to auto generate the DOM element for this panel, or a {@link Roo.DomHelper} config of the element to create
@@ -60208,15 +63062,14 @@ Roo.LayoutStateManager.prototype = {
  * @cfg {Roo.menu.Menu} menu  popup menu
 
  * @constructor
- * Create a new ContentPanel.
+ * Create a new Content Panel.
  * @param {String/HTMLElement/Roo.Element} el The container element for this panel
  * @param {String/Object} config A string to set only the title or a config object
  * @param {String} content (optional) Set the HTML content for this panel
  * @param {String} region (optional) Used by xtype constructors to add to regions. (values center,east,west,south,north)
  */
-Roo.ContentPanel = function(el, config, content){
+Roo.panel.Content = function(el, config, content){
     
-     
     /*
     if(el.autoCreate || el.xtype){ // xtype is available if this is called from factory
         config = el;
@@ -60286,20 +63139,20 @@ Roo.ContentPanel = function(el, config, content){
         /**
          * @event activate
          * Fires when this panel is activated. 
-         * @param {Roo.ContentPanel} this
+         * @param {Roo.panel.Content} this
          */
         "activate" : true,
         /**
          * @event deactivate
          * Fires when this panel is activated. 
-         * @param {Roo.ContentPanel} this
+         * @param {Roo.panel.Content} this
          */
         "deactivate" : true,
 
         /**
          * @event resize
          * Fires when this panel is resized if fitToFrame is true.
-         * @param {Roo.ContentPanel} this
+         * @param {Roo.panel.Content} this
          * @param {Number} width The width after any component adjustments
          * @param {Number} height The height after any component adjustments
          */
@@ -60308,7 +63161,7 @@ Roo.ContentPanel = function(el, config, content){
          /**
          * @event render
          * Fires when this tab is created
-         * @param {Roo.ContentPanel} this
+         * @param {Roo.panel.Content} this
          */
         "render" : true
          
@@ -60337,7 +63190,7 @@ Roo.ContentPanel = function(el, config, content){
     
     
     
-    Roo.ContentPanel.superclass.constructor.call(this);
+    Roo.panel.Content.superclass.constructor.call(this);
     
     if (this.view && typeof(this.view.xtype) != 'undefined') {
         this.view.el = this.el.appendChild(document.createElement("div"));
@@ -60349,7 +63202,7 @@ Roo.ContentPanel = function(el, config, content){
     this.fireEvent('render', this);
 };
 
-Roo.extend(Roo.ContentPanel, Roo.util.Observable, {
+Roo.extend(Roo.panel.Content, Roo.util.Observable, {
     tabTip:'',
     setRegion : function(region){
         this.region = region;
@@ -60421,7 +63274,7 @@ panel.load({
      * @param {String/Object} params (optional) The parameters to pass as either a URL encoded string "param1=1&amp;param2=2" or an object {param1: 1, param2: 2}
      * @param {Function} callback (optional) Callback when transaction is complete -- called with signature (oElement, bSuccess, oResponse)
      * @param {Boolean} discardUrl (optional) By default when you execute an update the defaultUrl is changed to the last used URL. If true, it will not store the URL.
-     * @return {Roo.ContentPanel} this
+     * @return {Roo.panel.Content} this
      */
     load : function(){
         var um = this.el.getUpdateManager();
@@ -60600,6 +63453,14 @@ layout.addxtype({
      */
     
     addxtype : function(cfg) {
+        if(cfg.xtype.match(/^Cropbox$/)) {
+
+            this.cropbox = new Roo.factory(cfg);
+
+            this.cropbox.render(this.el);
+
+            return this.cropbox;
+        }
         // add form..
         if (cfg.xtype.match(/^Form$/)) {
             
@@ -60647,14 +63508,14 @@ layout.addxtype({
 
 
 /**
- * @class Roo.GridPanel
- * @extends Roo.ContentPanel
- * @parent Roo.BorderLayout Roo.LayoutDialog builder
+ * @class Roo.panel.Grid
+ * @extends Roo.panel.Content
+ * @parent Roo.layout.Border Roo.LayoutDialog builder
  * @constructor
  * Create a new GridPanel.
  * @cfg {Roo.grid.Grid} grid The grid for this panel
  */
-Roo.GridPanel = function(grid, config){
+Roo.panel.Grid = function(grid, config){
     
     // universal ctor...
     if (typeof(grid.grid) != 'undefined') {
@@ -60666,7 +63527,7 @@ Roo.GridPanel = function(grid, config){
         
     this.wrapper.dom.appendChild(grid.getGridEl().dom);
     
-    Roo.GridPanel.superclass.constructor.call(this, this.wrapper, config);
+    Roo.panel.Grid.superclass.constructor.call(this, this.wrapper, config);
     
     if(this.toolbar){
         this.toolbar.el.insertBefore(this.wrapper.dom.firstChild);
@@ -60687,7 +63548,7 @@ Roo.GridPanel = function(grid, config){
     this.grid.getGridEl().replaceClass("x-layout-inactive-content", "x-layout-component-panel");
 };
 
-Roo.extend(Roo.GridPanel, Roo.ContentPanel, {
+Roo.extend(Roo.panel.Grid, Roo.panel.Content, {
     getId : function(){
         return this.grid.id;
     },
@@ -60720,26 +63581,26 @@ Roo.extend(Roo.GridPanel, Roo.ContentPanel, {
     destroy : function(){
         this.grid.destroy();
         delete this.grid;
-        Roo.GridPanel.superclass.destroy.call(this); 
+        Roo.panel.Grid.superclass.destroy.call(this); 
     }
 });
 
 
 /**
- * @class Roo.NestedLayoutPanel
- * @extends Roo.ContentPanel
- * @parent Roo.BorderLayout Roo.LayoutDialog builder
- * @cfg {Roo.BorderLayout} layout   [required] The layout for this panel
+ * @class Roo.panel.NestedLayout
+ * @extends Roo.panel.Content
+ * @parent Roo.layout.Border Roo.LayoutDialog builder
+ * @cfg {Roo.layout.Border} layout   [required] The layout for this panel
  *
  * 
  * @constructor
  * Create a new NestedLayoutPanel.
  * 
  * 
- * @param {Roo.BorderLayout} layout [required] The layout for this panel
+ * @param {Roo.layout.Border} layout [required] The layout for this panel
  * @param {String/Object} config A string to set only the title or a config object
  */
-Roo.NestedLayoutPanel = function(layout, config)
+Roo.panel.NestedLayout = function(layout, config)
 {
     // construct with only one argument..
     /* FIXME - implement nicer consturctors
@@ -60755,7 +63616,7 @@ Roo.NestedLayoutPanel = function(layout, config)
     */
     
     
-    Roo.NestedLayoutPanel.superclass.constructor.call(this, layout.getEl(), config);
+    Roo.panel.NestedLayout.superclass.constructor.call(this, layout.getEl(), config);
     
     layout.monitorWindowResize = false; // turn off autosizing
     this.layout = layout;
@@ -60766,7 +63627,7 @@ Roo.NestedLayoutPanel = function(layout, config)
     
 };
 
-Roo.extend(Roo.NestedLayoutPanel, Roo.ContentPanel, {
+Roo.extend(Roo.panel.NestedLayout, Roo.panel.Content, {
 
     layout : false,
 
@@ -60820,7 +63681,7 @@ Roo.extend(Roo.NestedLayoutPanel, Roo.ContentPanel, {
     
     /**
      * Returns the nested BorderLayout for this panel
-     * @return {Roo.BorderLayout}
+     * @return {Roo.layout.Border}
      */
     getLayout : function(){
         return this.layout;
@@ -60838,7 +63699,7 @@ panel.addxtype({
 );
 
 panel.addxtype({
-        xtype : 'NestedLayoutPanel',
+        xtype : 'panel.NestedLayout',
         region: 'west',
         layout: {
            center: { },
@@ -60856,10 +63717,10 @@ panel.addxtype({
     }
 });
 
-Roo.ScrollPanel = function(el, config, content){
+Roo.panel.Scroll = function(el, config, content){
     config = config || {};
     config.fitToFrame = true;
-    Roo.ScrollPanel.superclass.constructor.call(this, el, config, content);
+    Roo.panel.Scroll.superclass.constructor.call(this, el, config, content);
     
     this.el.dom.style.overflow = "hidden";
     var wrap = this.el.wrap({cls: "x-scroller x-layout-inactive-content"});
@@ -60881,7 +63742,7 @@ Roo.ScrollPanel = function(el, config, content){
     this.el = wrap; this.up = up; this.down = down;
 };
 
-Roo.extend(Roo.ScrollPanel, Roo.ContentPanel, {
+Roo.extend(Roo.panel.Scroll, Roo.panel.Content, {
     increment : 100,
     wheelIncrement : 5,
     scrollUp : function(){
@@ -60900,7 +63761,7 @@ Roo.extend(Roo.ScrollPanel, Roo.ContentPanel, {
     },
 
     setSize : function(){
-        Roo.ScrollPanel.superclass.setSize.apply(this, arguments);
+        Roo.panel.Scroll.superclass.setSize.apply(this, arguments);
         this.afterScroll();
     },
 
@@ -60920,16 +63781,16 @@ Roo.extend(Roo.ScrollPanel, Roo.ContentPanel, {
 
 
 /**
- * @class Roo.TreePanel
- * @extends Roo.ContentPanel
- * @parent Roo.BorderLayout Roo.LayoutDialog builder
+ * @class Roo.panel.Tree
+ * @extends Roo.panel.Content
+ * @parent Roo.layout.Border Roo.LayoutDialog builder
  * Treepanel component
  * 
  * @constructor
  * Create a new TreePanel. - defaults to fit/scoll contents.
  * @param {String/Object} config A string to set only the panel's title, or a config object
  */
-Roo.TreePanel = function(config){
+Roo.panel.Tree = function(config){
     var el = config.el;
     var tree = config.tree;
     delete config.tree; 
@@ -60942,7 +63803,7 @@ Roo.TreePanel = function(config){
     
     
     
-    Roo.TreePanel.superclass.constructor.call(this, el, config);
+    Roo.panel.Tree.superclass.constructor.call(this, el, config);
  
  
     this.tree = new Roo.tree.TreePanel(treeEl , tree);
@@ -60968,11 +63829,11 @@ Roo.TreePanel = function(config){
     
 };
 
-Roo.extend(Roo.TreePanel, Roo.ContentPanel, {   
+Roo.extend(Roo.panel.Tree, Roo.panel.Content, {   
     fitToFrame : true,
     autoScroll : true,
     /*
-     * @cfg {Roo.tree.TreePanel} tree [required] The tree TreePanel, with config etc.
+     * @cfg {Roo.tree.panel.Tree} tree [required] The tree TreePanel, with config etc.
      */
     tree : false
 
@@ -60990,17 +63851,17 @@ Roo.extend(Roo.TreePanel, Roo.ContentPanel, {
  
 
 /**
- * @class Roo.ReaderLayout
- * @extends Roo.BorderLayout
+ * @class Roo.layout.Reader
+ * @extends Roo.layout.Border
  * This is a pre-built layout that represents a classic, 5-pane application.  It consists of a header, a primary
  * center region containing two nested regions (a top one for a list view and one for item preview below),
  * and regions on either side that can be used for navigation, application commands, informational displays, etc.
- * The setup and configuration work exactly the same as it does for a {@link Roo.BorderLayout} - this class simply
+ * The setup and configuration work exactly the same as it does for a {@link Roo.layout.Border} - this class simply
  * expedites the setup of the overall layout and regions for this common application style.
  * Example:
  <pre><code>
-var reader = new Roo.ReaderLayout();
-var CP = Roo.ContentPanel;  // shortcut for adding
+var reader = new Roo.layout.Reader();
+var CP = Roo.panel.Content;  // shortcut for adding
 
 reader.beginUpdate();
 reader.add("north", new CP("north", "North"));
@@ -61017,9 +63878,9 @@ reader.endUpdate();
 * @param {String/HTMLElement/Element} container (optional) The container this layout is bound to (defaults to
 * document.body if omitted)
 */
-Roo.ReaderLayout = function(config, renderTo){
+Roo.layout.Reader = function(config, renderTo){
     var c = config || {size:{}};
-    Roo.ReaderLayout.superclass.constructor.call(this, renderTo || document.body, {
+    Roo.layout.Reader.superclass.constructor.call(this, renderTo || document.body, {
         north: c.north !== false ? Roo.apply({
             split:false,
             initialSize: 32,
@@ -61060,7 +63921,7 @@ Roo.ReaderLayout = function(config, renderTo){
 
     this.beginUpdate();
 
-    var inner = new Roo.BorderLayout(Roo.get(document.body).createChild(), {
+    var inner = new Roo.layout.Border(Roo.get(document.body).createChild(), {
         south: c.preview !== false ? Roo.apply({
             split:true,
             initialSize: 200,
@@ -61076,7 +63937,7 @@ Roo.ReaderLayout = function(config, renderTo){
             minHeight:200
         }, c.listView)
     });
-    this.add('center', new Roo.NestedLayoutPanel(inner,
+    this.add('center', new Roo.panel.NestedLayout(inner,
             Roo.apply({title: c.mainTitle || '',tabTip:''},c.innerPanelCfg)));
 
     this.endUpdate();
@@ -61085,7 +63946,7 @@ Roo.ReaderLayout = function(config, renderTo){
     this.regions.listView = inner.getRegion('center');
 };
 
-Roo.extend(Roo.ReaderLayout, Roo.BorderLayout);/*
+Roo.extend(Roo.layout.Reader, Roo.layout.Border);/*
  * Based on:
  * Ext JS Library 1.1.1
  * Copyright(c) 2006-2007, Ext JS, LLC.
@@ -61419,6 +64280,11 @@ Roo.extend(Roo.grid.Grid, Roo.util.Observable, {
        /**
         * @cfg {Roo.Toolbar} toolbar a toolbar for buttons etc.
         */
+        
+        /**
+        * @cfg {Roo.PagingToolbar} footer the paging toolbar
+        */
+       
        /**
      * @cfg {String} ddGroup - drag drop group.
      */
@@ -64279,7 +67145,7 @@ Roo.grid.ColumnModel = function(config){
 };
 Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, {
     /**
-     * @cfg {String} header The header text to display in the Grid view.
+     * @cfg {String} header [required] The header text to display in the Grid view.
      */
        /**
      * @cfg {String} xsHeader Header at Bootsrap Extra Small width (default for all)
@@ -64297,66 +67163,66 @@ Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, {
      * @cfg {String} xlHeader Header at Bootsrap extra Large width
      */
     /**
-     * @cfg {String} dataIndex (Optional) The name of the field in the grid's {@link Roo.data.Store}'s
+     * @cfg {String} dataIndex  The name of the field in the grid's {@link Roo.data.Store}'s
      * {@link Roo.data.Record} definition from which to draw the column's value. If not
      * specified, the column's index is used as an index into the Record's data Array.
      */
     /**
-     * @cfg {Number} width (Optional) The initial width in pixels of the column. Using this
+     * @cfg {Number} width  The initial width in pixels of the column. Using this
      * instead of {@link Roo.grid.Grid#autoSizeColumns} is more efficient.
      */
     /**
-     * @cfg {Boolean} sortable (Optional) True if sorting is to be allowed on this column.
+     * @cfg {Boolean} sortable True if sorting is to be allowed on this column.
      * Defaults to the value of the {@link #defaultSortable} property.
      * Whether local/remote sorting is used is specified in {@link Roo.data.Store#remoteSort}.
      */
     /**
-     * @cfg {Boolean} locked (Optional) True to lock the column in place while scrolling the Grid.  Defaults to false.
+     * @cfg {Boolean} locked  True to lock the column in place while scrolling the Grid.  Defaults to false.
      */
     /**
-     * @cfg {Boolean} fixed (Optional) True if the column width cannot be changed.  Defaults to false.
+     * @cfg {Boolean} fixed  True if the column width cannot be changed.  Defaults to false.
      */
     /**
-     * @cfg {Boolean} resizable (Optional) False to disable column resizing. Defaults to true.
+     * @cfg {Boolean} resizable  False to disable column resizing. Defaults to true.
      */
     /**
-     * @cfg {Boolean} hidden (Optional) True to hide the column. Defaults to false.
+     * @cfg {Boolean} hidden  True to hide the column. Defaults to false.
      */
     /**
-     * @cfg {Function} renderer (Optional) A function used to generate HTML markup for a cell
+     * @cfg {Function} renderer A function used to generate HTML markup for a cell
      * given the cell's data value. See {@link #setRenderer}. If not specified, the
      * default renderer returns the escaped data value. If an object is returned (bootstrap only)
      * then it is treated as a Roo Component object instance, and it is rendered after the initial row is rendered
      */
        /**
-     * @cfg {Roo.grid.GridEditor} editor (Optional) For grid editors - returns the grid editor 
+     * @cfg {Roo.grid.GridEditor} editor  For grid editors - returns the grid editor 
      */
     /**
-     * @cfg {String} align (Optional) Set the CSS text-align property of the column.  Defaults to undefined.
+     * @cfg {String} align (left|right) Set the CSS text-align property of the column.  Defaults to undefined (left).
      */
     /**
-     * @cfg {String} valign (Optional) Set the CSS vertical-align property of the column (eg. middle, top, bottom etc).  Defaults to undefined.
+     * @cfg {String} valign (top|bottom|middle) Set the CSS vertical-align property of the column (eg. middle, top, bottom etc).  Defaults to undefined (middle)
      */
     /**
-     * @cfg {String} cursor (Optional)
+     * @cfg {String} cursor ( auto|default|none|context-menu|help|pointer|progress|wait|cell|crosshair|text|vertical-text|alias|copy|move|no-drop|not-allowed|e-resize|n-resize|ne-resize|nw-resize|s-resize|se-resize|sw-resize|w-resize|ew-resize|ns-resize|nesw-resize|nwse-resize|col-resize|row-resize|all-scroll|zoom-in|zoom-out|grab|grabbing)
      */
     /**
-     * @cfg {String} tooltip (Optional)
+     * @cfg {String} tooltip mouse over tooltip text
      */
     /**
-     * @cfg {Number} xs (Optional) can be '0' for hidden at this size (number less than 12)
+     * @cfg {Number} xs  can be '0' for hidden at this size (number less than 12)
      */
     /**
-     * @cfg {Number} sm (Optional) can be '0' for hidden at this size (number less than 12)
+     * @cfg {Number} sm can be '0' for hidden at this size (number less than 12)
      */
     /**
-     * @cfg {Number} md (Optional) can be '0' for hidden at this size (number less than 12)
+     * @cfg {Number} md can be '0' for hidden at this size (number less than 12)
      */
     /**
-     * @cfg {Number} lg (Optional) can be '0' for hidden at this size (number less than 12)
+     * @cfg {Number} lg   can be '0' for hidden at this size (number less than 12)
      */
        /**
-     * @cfg {Number} xl (Optional) can be '0' for hidden at this size (number less than 12)
+     * @cfg {Number} xl   can be '0' for hidden at this size (number less than 12)
      */
     /**
      * Returns the id of the column at the specified index.
@@ -67852,4 +70718,33 @@ Roo.extend(Roo.XTemplate, Roo.Template, {
 Roo.XTemplate.from = function(el){
     el = Roo.getDom(el);
     return new Roo.XTemplate(el.value || el.innerHTML);
-};
\ No newline at end of file
+};// old names for panel elements
+Roo.GridPanel = Roo.panel.Grid;
+Roo.CalendarPanel = Roo.panel.Calendar;
+Roo.ContentPanel = Roo.panel.Content;
+Roo.NestedLayoutPanel = Roo.panel.NestedLayout;
+Roo.TabPanel = Roo.panel.Tab;
+Roo.TabPanelItem = Roo.panel.TabItem;
+Roo.TreePanel = Roo.panel.Tree;
+
+
+// phase 2 update
+Roo.ScrollPanel = Roo.panel.Scroll;
+
+Roo.BorderLayout = Roo.layout.Border;
+Roo.BasicLayoutRegion = Roo.layout.BasicRegion;
+Roo.LayoutRegion = Roo.layout.Region;
+Roo.SplitLayoutRegion = Roo.layout.SplitRegion;
+Roo.LayoutManager = Roo.layout.Manager;
+
+
+Roo.NorthLayoutRegion = Roo.layout.North;
+Roo.EastLayoutRegion = Roo.layout.East;
+Roo.WestLayoutRegion = Roo.layout.West;
+Roo.SouthLayoutRegion = Roo.layout.South;
+Roo.CenterLayoutRegion = Roo.layout.Center;
+
+
+Roo.LayoutStateManager  = Roo.layout.StateManager;
+Roo.ReaderLayout = Roo.layout.Reader;
+