Merge branch 'master' of http://git.roojs.com/roojs1
[roojs1] / roojs-debug.js
index 03ae7ba..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 || []);
+
         },
 
         /**
@@ -2702,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]);
             }
@@ -2710,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;
 
@@ -5513,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;
@@ -16630,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(...);
@@ -16992,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];
@@ -18055,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
@@ -18274,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({
@@ -18297,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,
@@ -24973,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
@@ -25980,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
      */
   
@@ -29959,760 +29972,2332 @@ Roo.extend(Roo.DatePicker, Roo.Component, {
         
         
     }
-});        /*
- * Based on:
- * Ext JS Library 1.1.1
- * Copyright(c) 2006-2007, Ext JS, LLC.
- *
- * Originally Released Under LGPL - original licence link has changed is not relivant.
- *
- * Fork - LGPL
- * <script type="text/javascript">
- */
-/**
- * @class Roo.TabPanel
- * @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");
-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");
-jtabs.addTab("jtabs-1", "Normal Tab", "My content was added during construction.");
-
-// set up the UpdateManager
-var tab2 = jtabs.addTab("jtabs-2", "Ajax Tab 1");
-var updater = tab2.getUpdateManager();
-updater.setDefaultUrl("ajax1.htm");
-tab2.on('activate', updater.refresh, updater, true);
-
-// Use setUrl for Ajax loading
-var tab3 = jtabs.addTab("jtabs-3", "Ajax Tab 2");
-tab3.setUrl("ajax2.htm", null, true);
-
-// Disabled tab
-var tab4 = jtabs.addTab("tabs1-5", "Disabled Tab", "Can't see me cause I'm disabled");
-tab4.disable();
+});Roo.panel = {};
+/*
+* Licence: LGPL
+*/
 
-jtabs.activate("jtabs-1");
- * </code></pre>
+/**
+ * @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 TabPanel.
- * @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.
+ * Create a new Cropbox
+ * @param {Object} config The config object
  */
-Roo.TabPanel = function(container, config){
-    /**
-    * The container element for this TabPanel.
-    * @type Roo.Element
-    */
-    this.el = Roo.get(container, true);
-    if(config){
-        if(typeof config == "boolean"){
-            this.tabPosition = config ? "bottom" : "top";
-        }else{
-            Roo.apply(this, config);
-        }
-    }
-    if(this.tabPosition == "bottom"){
-        this.bodyEl = Roo.get(this.createBody(this.el.dom));
-        this.el.addClass("x-tabs-bottom");
-    }
-    this.stripWrap = Roo.get(this.createStrip(this.el.dom), true);
-    this.stripEl = Roo.get(this.createStripList(this.stripWrap.dom), true);
-    this.stripBody = Roo.get(this.stripWrap.dom.firstChild.firstChild, true);
-    if(Roo.isIE){
-        Roo.fly(this.stripWrap.dom.firstChild).setStyle("overflow-x", "hidden");
-    }
-    if(this.tabPosition != "bottom"){
-        /** The body element that contains {@link Roo.TabPanelItem} bodies. +
-         * @type Roo.Element
-         */
-        this.bodyEl = Roo.get(this.createBody(this.el.dom));
-        this.el.addClass("x-tabs-top");
-    }
-    this.items = [];
-
-    this.bodyEl.setStyle("position", "relative");
-
-    this.active = null;
-    this.activateDelegate = this.activate.createDelegate(this);
 
+ Roo.panel.Cropbox = function(config){
+    Roo.panel.Cropbox.superclass.constructor.call(this, config);
+    
     this.addEvents({
         /**
-         * @event tabchange
-         * Fires when the active tab changes
-         * @param {Roo.TabPanel} this
-         * @param {Roo.TabPanelItem} activePanel The new active tab
+         * @event beforeselectfile
+         * Fire before select file
+         * @param {Roo.panel.Cropbox} this
          */
-        "tabchange": true,
+        "beforeselectfile" : 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 {Object} e Set cancel to true on this object to cancel the tab change
-         * @param {Roo.TabPanelItem} tab The tab being changed to
+         * @event initial
+         * Fire after initEvent
+         * @param {Roo.panel.Cropbox} this
          */
-        "beforetabchange" : true
+        "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.EventManager.onWindowResize(this.onResize, this);
-    this.cpad = this.el.getPadding("lr");
-    this.hiddenCount = 0;
-
+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);
 
-    // toolbar on the tabbar support...
-    if (this.toolbar) {
-        var tcfg = this.toolbar;
-        tcfg.container = this.stripEl.child('td.x-tab-strip-toolbar');  
-        this.toolbar = new Roo.Toolbar(tcfg);
-        if (Roo.isSafari) {
-            var tbl = tcfg.container.child('table', true);
-            tbl.setAttribute('width', '100%');
+        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());
         
-    }
-   
-
-
-    Roo.TabPanel.superclass.constructor.call(this);
-};
-
-Roo.extend(Roo.TabPanel, Roo.util.Observable, {
-    /*
-     *@cfg {String} tabPosition "top" or "bottom" (defaults to "top")
-     */
-    tabPosition : "top",
-    /*
-     *@cfg {Number} currentTabWidth The width of the current tab (defaults to 0)
-     */
-    currentTabWidth : 0,
-    /*
-     *@cfg {Number} minTabWidth The minimum width of a tab (defaults to 40) (ignored if {@link #resizeTabs} is not true)
-     */
-    minTabWidth : 40,
-    /*
-     *@cfg {Number} maxTabWidth The maximum width of a tab (defaults to 250) (ignored if {@link #resizeTabs} is not true)
-     */
-    maxTabWidth : 250,
-    /*
-     *@cfg {Number} preferredTabWidth The preferred (default) width of a tab (defaults to 175) (ignored if {@link #resizeTabs} is not true)
-     */
-    preferredTabWidth : 175,
-    /*
-     *@cfg {Boolean} resizeTabs True to enable dynamic tab resizing (defaults to false)
-     */
-    resizeTabs : false,
-    /*
-     *@cfg {Boolean} monitorResize Set this to true to turn on window resize monitoring (ignored if {@link #resizeTabs} is not true) (defaults to true)
-     */
-    monitorResize : true,
-    /*
-     *@cfg {Object} toolbar xtype description of toolbar to show at the right of the tab bar. 
-     */
-    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.
-     * @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
-     */
-    addTab : function(id, text, content, closable){
-        var item = new Roo.TabPanelItem(this, id, text, closable);
-        this.addTabItem(item);
-        if(content){
-            item.setContent(content);
+            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;
         }
-        return item;
     },
-
-    /**
-     * Returns the {@link Roo.TabPanelItem} with the specified id/index
-     * @param {String/Number} id The id or index of the TabPanelItem to fetch.
-     * @return {Roo.TabPanelItem}
-     */
-    getTab : function(id){
-        return this.items[id];
+    
+    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);
     },
 
-    /**
-     * Hides the {@link Roo.TabPanelItem} with the specified id/index
-     * @param {String/Number} id The id or index of the TabPanelItem to hide.
-     */
-    hideTab : function(id){
-        var t = this.items[id];
-        if(!t.isHidden()){
-           t.setHidden(true);
-           this.hiddenCount++;
-           this.autoSizeTabs();
+    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);
         }
-    },
-
-    /**
-     * "Unhides" the {@link Roo.TabPanelItem} with the specified id/index.
-     * @param {String/Number} id The id or index of the TabPanelItem to unhide.
-     */
-    unhideTab : function(id){
-        var t = this.items[id];
-        if(t.isHidden()){
-           t.setHidden(false);
-           this.hiddenCount--;
-           this.autoSizeTabs();
+        
+        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);
     },
-
-    /**
-     * Adds an existing {@link Roo.TabPanelItem}.
-     * @param {Roo.TabPanelItem} item The TabPanelItem to add
-     */
-    addTabItem : function(item){
-        this.items[item.id] = item;
-        this.items.push(item);
-        if(this.resizeTabs){
-           item.setWidth(this.currentTabWidth || this.preferredTabWidth);
-           this.autoSizeTabs();
-        }else{
-            item.autoSize();
+    
+    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();
         }
     },
-
-    /**
-     * Removes a {@link Roo.TabPanelItem}.
-     * @param {String/Number} id The id or index of the TabPanelItem to remove.
-     */
-    removeTab : function(id){
-        var items = this.items;
-        var tab = items[id];
-        if(!tab) { return; }
-        var index = items.indexOf(tab);
-        if(this.active == tab && items.length > 1){
-            var newTab = this.getNextAvailable(index);
-            if(newTab) {
-                newTab.activate();
-            }
+    
+    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.stripEl.dom.removeChild(tab.pnode.dom);
-        if(tab.bodyEl.dom.parentNode == this.bodyEl.dom){ // if it was moved already prevent error
-            this.bodyEl.dom.removeChild(tab.bodyEl.dom);
+        
+        this.fireEvent('footerbuttonclick', this, type);
+    },
+    
+    beforeSelectFile : function(e)
+    {
+        e.preventDefault();
+        
+        if(this.fireEvent('beforeselectfile', this) != false){
+            this.selectorEl.dom.click();
         }
-        items.splice(index, 1);
-        delete this.items[tab.id];
-        tab.fireEvent("close", tab);
-        tab.purgeListeners();
-        this.autoSizeTabs();
     },
-
-    getNextAvailable : function(start){
-        var items = this.items;
-        var index = start;
-        // look for a next tab that will slide over to
-        // replace the one being removed
-        while(index < items.length){
-            var item = items[++index];
-            if(item && !item.isHidden()){
-                return item;
-            }
+    
+    onFileSelected : function(e)
+    {
+        e.preventDefault();
+        
+        if(typeof(this.selectorEl.dom.files) == 'undefined' || !this.selectorEl.dom.files.length){
+            return;
         }
-        // if one isn't found select the previous tab (on the left)
-        index = start;
-        while(index >= 0){
-            var item = items[--index];
-            if(item && !item.isHidden()){
-                return item;
-            }
+        
+        var file = this.selectorEl.dom.files[0];
+        
+        if(this.fireEvent('inspect', this, file) != false){
+            this.prepare(file);
         }
-        return null;
+        
     },
-
-    /**
-     * Disables a {@link Roo.TabPanelItem}. 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){
-        var tab = this.items[id];
-        if(tab && this.active != tab){
-            tab.disable();
-        }
+    
+    trash : function(e)
+    {
+        this.fireEvent('trash', this);
     },
-
-    /**
-     * Enables a {@link Roo.TabPanelItem} that is disabled.
-     * @param {String/Number} id The id or index of the TabPanelItem to enable.
-     */
-    enableTab : function(id){
-        var tab = this.items[id];
-        tab.enable();
+    
+    download : function(e)
+    {
+        this.fireEvent('download', this);
     },
 
-    /**
-     * Activates a {@link Roo.TabPanelItem}. 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.
-     */
-    activate : function(id){
-        var tab = this.items[id];
-        if(!tab){
-            return null;
-        }
-        if(tab == this.active || tab.disabled){
-            return tab;
+    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;
         }
-        var e = {};
-        this.fireEvent("beforetabchange", this, e, tab);
-        if(e.cancel !== true && !tab.disabled){
-            if(this.active){
-                this.active.hide();
+    },
+    
+    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.active = this.items[id];
-            this.active.show();
-            this.fireEvent("tabchange", this, this.active);
+            
+            this.setThumbBoxPosition();
+            
+            this.baseScaleLevel();
+            
+            this.draw();
+            
+            this.resize();
+            
+            this.canvasLoaded = true;
+        
         }
-        return tab;
+        
+        if(this.loadMask){
+            this.maskEl.unmask();
+        }
+        
     },
+    
+    setCanvasPosition : function(center = true)
+    {   
+        if(!this.canvasEl){
+            return;
+        }
 
-    /**
-     * Gets the active {@link Roo.TabPanelItem}.
-     * @return {Roo.TabPanelItem} The active TabPanelItem or null if none are active.
-     */
-    getActiveTab : function(){
-        return this.active;
-    },
+        var newCenterLeft = Math.ceil((this.bodyEl.getWidth() - this.canvasEl.width) / 2);
+        var newCenterTop = Math.ceil((this.bodyEl.getHeight() - this.canvasEl.height) / 2);
 
-    /**
-     * Updates the tab body element to fit the height of the container element
-     * for overflow scrolling
-     * @param {Number} targetHeight (optional) Override the starting height from the elements height
-     */
-    syncHeight : function(targetHeight){
-        var height = (targetHeight || this.el.getHeight())-this.el.getBorderWidth("tb")-this.el.getPadding("tb");
-        var bm = this.bodyEl.getMargins();
-        var newHeight = height-(this.stripWrap.getHeight()||0)-(bm.top+bm.bottom);
-        this.bodyEl.setHeight(newHeight);
-        return newHeight;
-    },
+        if(center) {
+            this.previewEl.setLeft(newCenterLeft);
+            this.previewEl.setTop(newCenterTop);
 
-    onResize : function(){
-        if(this.monitorResize){
-            this.autoSizeTabs();
+            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);
 
-    /**
-     * Disables tab resizing while tabs are being added (if {@link #resizeTabs} is false this does nothing)
-     */
-    beginUpdate : function(){
-        this.updating = true;
-    },
+        var oldCenterLeft = Math.ceil((this.bodyEl.getWidth() - oldCanvasWidth) / 2);
+        var oldCenterTop = Math.ceil((this.bodyEl.getHeight() - oldCanvasHeight) / 2);
 
-    /**
-     * Stops an update and resizes the tabs (if {@link #resizeTabs} is false this does nothing)
-     */
-    endUpdate : function(){
-        this.updating = false;
-        this.autoSizeTabs();
-    },
+        var leftDiff = newCenterLeft - oldCenterLeft;
+        var topDiff = newCenterTop - oldCenterTop;
 
-    /**
-     * Manual call to resize the tabs (if {@link #resizeTabs} is false this does nothing)
-     */
-    autoSizeTabs : function(){
-        var count = this.items.length;
-        var vcount = count - this.hiddenCount;
-        if(!this.resizeTabs || count < 1 || vcount < 1 || this.updating) {
+        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;
         }
-        var w = Math.max(this.el.getWidth() - this.cpad, 10);
-        var availWidth = Math.floor(w / vcount);
-        var b = this.stripBody;
-        if(b.getWidth() > w){
-            var tabs = this.items;
-            this.setTabWidth(Math.max(availWidth, this.minTabWidth)-2);
-            if(availWidth < this.minTabWidth){
-                /*if(!this.sleft){    // incomplete scrolling code
-                    this.createScrollButtons();
+        
+        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;
                 }
-                this.showScroll();
-                this.stripClip.setWidth(w - (this.sleft.getWidth()+this.sright.getWidth()));*/
+                
+                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;
             }
-        }else{
-            if(this.currentTabWidth < this.preferredTabWidth){
-                this.setTabWidth(Math.min(availWidth, this.preferredTabWidth)-2);
+            
+            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);
 
-    /**
-     * Returns the number of tabs in this TabPanel.
-     * @return {Number}
-     */
-     getCount : function(){
-         return this.items.length;
-     },
+        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");
 
-    /**
-     * Resizes all the tabs to the passed width
-     * @param {Number} The new width
-     */
-    setTabWidth : function(width){
-        this.currentTabWidth = width;
-        for(var i = 0, len = this.items.length; i < len; i++) {
-               if(!this.items[i].isHidden()) {
-                this.items[i].setWidth(width);
+        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;
 
-    /**
-     * Destroys this TabPanel
-     * @param {Boolean} removeEl (optional) True to remove the element from the DOM as well (defaults to undefined)
-     */
-    destroy : function(removeEl){
-        Roo.EventManager.removeResizeListener(this.onResize, this);
-        for(var i = 0, len = this.items.length; i < len; i++){
-            this.items[i].purgeListeners();
+                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(removeEl === true){
-            this.el.update("");
-            this.el.remove();
+        
+        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.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+/**
+ * @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.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.panel.Tab("jtabs");
+jtabs.addTab("jtabs-1", "Normal Tab", "My content was added during construction.");
+
+// set up the UpdateManager
+var tab2 = jtabs.addTab("jtabs-2", "Ajax Tab 1");
+var updater = tab2.getUpdateManager();
+updater.setDefaultUrl("ajax1.htm");
+tab2.on('activate', updater.refresh, updater, true);
 
-/**
- * @class Roo.TabPanelItem
- * @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 {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)
+// Use setUrl for Ajax loading
+var tab3 = jtabs.addTab("jtabs-3", "Ajax Tab 2");
+tab3.setUrl("ajax2.htm", null, true);
+
+// Disabled tab
+var tab4 = jtabs.addTab("tabs1-5", "Disabled Tab", "Can't see me cause I'm disabled");
+tab4.disable();
+
+jtabs.activate("jtabs-1");
+ * </code></pre>
+ * @constructor
+ * Create a new TabPanel.
+ * @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.TabPanelItem = function(tabPanel, id, text, closable){
+Roo.panel.Tab = function(container, config){
     /**
-     * The {@link Roo.TabPanel} this TabPanelItem belongs to
-     * @type Roo.TabPanel
-     */
-    this.tabPanel = tabPanel;
-    /**
-     * The id for this TabPanelItem
-     * @type String
-     */
-    this.id = id;
-    /** @private */
-    this.disabled = false;
-    /** @private */
-    this.text = text;
-    /** @private */
-    this.loaded = false;
-    this.closable = closable;
+    * The container element for this TabPanel.
+    * @type Roo.Element
+    */
+    this.el = Roo.get(container, true);
+    if(config){
+        if(typeof config == "boolean"){
+            this.tabPosition = config ? "bottom" : "top";
+        }else{
+            Roo.apply(this, config);
+        }
+    }
+    if(this.tabPosition == "bottom"){
+        this.bodyEl = Roo.get(this.createBody(this.el.dom));
+        this.el.addClass("x-tabs-bottom");
+    }
+    this.stripWrap = Roo.get(this.createStrip(this.el.dom), true);
+    this.stripEl = Roo.get(this.createStripList(this.stripWrap.dom), true);
+    this.stripBody = Roo.get(this.stripWrap.dom.firstChild.firstChild, true);
+    if(Roo.isIE){
+        Roo.fly(this.stripWrap.dom.firstChild).setStyle("overflow-x", "hidden");
+    }
+    if(this.tabPosition != "bottom"){
+        /** The body element that contains {@link Roo.panel.TabItem} bodies. +
+         * @type Roo.Element
+         */
+        this.bodyEl = Roo.get(this.createBody(this.el.dom));
+        this.el.addClass("x-tabs-top");
+    }
+    this.items = [];
 
-    /**
-     * The body element for this TabPanelItem.
-     * @type Roo.Element
-     */
-    this.bodyEl = Roo.get(tabPanel.createItemBody(tabPanel.bodyEl.dom, id));
-    this.bodyEl.setVisibilityMode(Roo.Element.VISIBILITY);
-    this.bodyEl.setStyle("display", "block");
-    this.bodyEl.setStyle("zoom", "1");
-    this.hideAction();
+    this.bodyEl.setStyle("position", "relative");
 
-    var els = tabPanel.createStripElements(tabPanel.stripEl.dom, text, closable);
-    /** @private */
-    this.el = Roo.get(els.el, true);
-    this.inner = Roo.get(els.inner, true);
-    this.textEl = Roo.get(this.el.dom.firstChild.firstChild.firstChild, true);
-    this.pnode = Roo.get(els.el.parentNode, true);
-    this.el.on("mousedown", this.onTabMouseDown, this);
-    this.el.on("click", this.onTabClick, this);
-    /** @private */
-    if(closable){
-        var c = Roo.get(els.close, true);
-        c.dom.title = this.closeText;
-        c.addClassOnOver("close-over");
-        c.on("click", this.closeClick, this);
-     }
+    this.active = null;
+    this.activateDelegate = this.activate.createDelegate(this);
 
     this.addEvents({
-         /**
-         * @event activate
-         * Fires when this tab becomes the active tab.
-         * @param {Roo.TabPanel} tabPanel The parent TabPanel
-         * @param {Roo.TabPanelItem} 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 {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
+         * @event tabchange
+         * Fires when the active tab changes
+         * @param {Roo.panel.Tab} this
+         * @param {Roo.panel.TabItem} activePanel The new active tab
          */
-         "close": true,
+        "tabchange": true,
         /**
-         * @event deactivate
-         * Fires when this tab is no longer the active tab.
-         * @param {Roo.TabPanel} tabPanel The parent TabPanel
-         * @param {Roo.TabPanelItem} this
+         * @event beforetabchange
+         * Fires before the active tab changes, set cancel to true on the "e" parameter to cancel the change
+         * @param {Roo.panel.Tab} this
+         * @param {Object} e Set cancel to true on this object to cancel the tab change
+         * @param {Roo.panel.TabItem} tab The tab being changed to
          */
-         "deactivate" : true
+        "beforetabchange" : true
     });
-    this.hidden = false;
 
-    Roo.TabPanelItem.superclass.constructor.call(this);
+    Roo.EventManager.onWindowResize(this.onResize, this);
+    this.cpad = this.el.getPadding("lr");
+    this.hiddenCount = 0;
+
+
+    // toolbar on the tabbar support...
+    if (this.toolbar) {
+        var tcfg = this.toolbar;
+        tcfg.container = this.stripEl.child('td.x-tab-strip-toolbar');  
+        this.toolbar = new Roo.Toolbar(tcfg);
+        if (Roo.isSafari) {
+            var tbl = tcfg.container.child('table', true);
+            tbl.setAttribute('width', '100%');
+        }
+        
+    }
+   
+
+
+    Roo.panel.Tab.superclass.constructor.call(this);
 };
 
-Roo.extend(Roo.TabPanelItem, Roo.util.Observable, {
-    purgeListeners : function(){
-       Roo.util.Observable.prototype.purgeListeners.call(this);
-       this.el.removeAllListeners();
-    },
+Roo.extend(Roo.panel.Tab, Roo.util.Observable, {
+    /*
+     *@cfg {String} tabPosition "top" or "bottom" (defaults to "top")
+     */
+    tabPosition : "top",
+    /*
+     *@cfg {Number} currentTabWidth The width of the current tab (defaults to 0)
+     */
+    currentTabWidth : 0,
+    /*
+     *@cfg {Number} minTabWidth The minimum width of a tab (defaults to 40) (ignored if {@link #resizeTabs} is not true)
+     */
+    minTabWidth : 40,
+    /*
+     *@cfg {Number} maxTabWidth The maximum width of a tab (defaults to 250) (ignored if {@link #resizeTabs} is not true)
+     */
+    maxTabWidth : 250,
+    /*
+     *@cfg {Number} preferredTabWidth The preferred (default) width of a tab (defaults to 175) (ignored if {@link #resizeTabs} is not true)
+     */
+    preferredTabWidth : 175,
+    /*
+     *@cfg {Boolean} resizeTabs True to enable dynamic tab resizing (defaults to false)
+     */
+    resizeTabs : false,
+    /*
+     *@cfg {Boolean} monitorResize Set this to true to turn on window resize monitoring (ignored if {@link #resizeTabs} is not true) (defaults to true)
+     */
+    monitorResize : true,
+    /*
+     *@cfg {Object} toolbar xtype description of toolbar to show at the right of the tab bar. 
+     */
+    toolbar : false,
+
     /**
-     * Shows this TabPanelItem -- this <b>does not</b> deactivate the currently active TabPanelItem.
+     * 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.panel.TabItem} The created TabPanelItem
      */
-    show : function(){
-        this.pnode.addClass("on");
-        this.showAction();
-        if(Roo.isOpera){
-            this.tabPanel.stripWrap.repaint();
+    addTab : function(id, text, content, closable){
+        var item = new Roo.panel.TabItem(this, id, text, closable);
+        this.addTabItem(item);
+        if(content){
+            item.setContent(content);
         }
-        this.fireEvent("activate", this.tabPanel, this);
+        return item;
     },
 
     /**
-     * Returns true if this tab is the active tab.
-     * @return {Boolean}
+     * 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.panel.TabItem}
      */
-    isActive : function(){
-        return this.tabPanel.getActiveTab() == this;
+    getTab : function(id){
+        return this.items[id];
     },
 
     /**
-     * Hides this TabPanelItem -- if you don't activate another TabPanelItem this could look odd.
+     * Hides the {@link Roo.panel.TabItem} with the specified id/index
+     * @param {String/Number} id The id or index of the TabPanelItem to hide.
      */
-    hide : function(){
-        this.pnode.removeClass("on");
-        this.hideAction();
-        this.fireEvent("deactivate", this.tabPanel, this);
-    },
-
-    hideAction : function(){
-        this.bodyEl.hide();
-        this.bodyEl.setStyle("position", "absolute");
-        this.bodyEl.setLeft("-20000px");
-        this.bodyEl.setTop("-20000px");
+    hideTab : function(id){
+        var t = this.items[id];
+        if(!t.isHidden()){
+           t.setHidden(true);
+           this.hiddenCount++;
+           this.autoSizeTabs();
+        }
     },
 
-    showAction : function(){
-        this.bodyEl.setStyle("position", "relative");
-        this.bodyEl.setTop("");
-        this.bodyEl.setLeft("");
-        this.bodyEl.show();
+    /**
+     * "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){
+        var t = this.items[id];
+        if(t.isHidden()){
+           t.setHidden(false);
+           this.hiddenCount--;
+           this.autoSizeTabs();
+        }
     },
 
     /**
-     * Set the tooltip for the tab.
-     * @param {String} tooltip The tab's tooltip
+     * Adds an existing {@link Roo.panel.TabItem}.
+     * @param {Roo.panel.TabItem} item The TabPanelItem to add
      */
-    setTooltip : function(text){
-        if(Roo.QuickTips && Roo.QuickTips.isEnabled()){
-            this.textEl.dom.qtip = text;
-            this.textEl.dom.removeAttribute('title');
+    addTabItem : function(item){
+        this.items[item.id] = item;
+        this.items.push(item);
+        if(this.resizeTabs){
+           item.setWidth(this.currentTabWidth || this.preferredTabWidth);
+           this.autoSizeTabs();
         }else{
-            this.textEl.dom.title = text;
+            item.autoSize();
         }
     },
 
-    onTabClick : function(e){
-        e.preventDefault();
-        this.tabPanel.activate(this.id);
-    },
-
-    onTabMouseDown : function(e){
-        e.preventDefault();
-        this.tabPanel.activate(this.id);
-    },
-
-    getWidth : function(){
-        return this.inner.getWidth();
+    /**
+     * Removes a {@link Roo.panel.TabItem}.
+     * @param {String/Number} id The id or index of the TabPanelItem to remove.
+     */
+    removeTab : function(id){
+        var items = this.items;
+        var tab = items[id];
+        if(!tab) { return; }
+        var index = items.indexOf(tab);
+        if(this.active == tab && items.length > 1){
+            var newTab = this.getNextAvailable(index);
+            if(newTab) {
+                newTab.activate();
+            }
+        }
+        this.stripEl.dom.removeChild(tab.pnode.dom);
+        if(tab.bodyEl.dom.parentNode == this.bodyEl.dom){ // if it was moved already prevent error
+            this.bodyEl.dom.removeChild(tab.bodyEl.dom);
+        }
+        items.splice(index, 1);
+        delete this.items[tab.id];
+        tab.fireEvent("close", tab);
+        tab.purgeListeners();
+        this.autoSizeTabs();
     },
 
-    setWidth : function(width){
-        var iwidth = width - this.pnode.getPadding("lr");
-        this.inner.setWidth(iwidth);
-        this.textEl.setWidth(iwidth-this.inner.getPadding("lr"));
-        this.pnode.setWidth(width);
+    getNextAvailable : function(start){
+        var items = this.items;
+        var index = start;
+        // look for a next tab that will slide over to
+        // replace the one being removed
+        while(index < items.length){
+            var item = items[++index];
+            if(item && !item.isHidden()){
+                return item;
+            }
+        }
+        // if one isn't found select the previous tab (on the left)
+        index = start;
+        while(index >= 0){
+            var item = items[--index];
+            if(item && !item.isHidden()){
+                return item;
+            }
+        }
+        return null;
     },
 
     /**
-     * Show or hide the tab
-     * @param {Boolean} hidden True to hide or false to show.
+     * 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.
      */
-    setHidden : function(hidden){
-        this.hidden = hidden;
-        this.pnode.setStyle("display", hidden ? "none" : "");
+    disableTab : function(id){
+        var tab = this.items[id];
+        if(tab && this.active != tab){
+            tab.disable();
+        }
     },
 
     /**
-     * Returns true if this tab is "hidden"
-     * @return {Boolean}
+     * Enables a {@link Roo.panel.TabItem} that is disabled.
+     * @param {String/Number} id The id or index of the TabPanelItem to enable.
      */
-    isHidden : function(){
-        return this.hidden;
+    enableTab : function(id){
+        var tab = this.items[id];
+        tab.enable();
     },
 
     /**
-     * Returns the text for this tab
-     * @return {String}
+     * 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.panel.TabItem} The TabPanelItem.
      */
-    getText : function(){
-        return this.text;
-    },
-
-    autoSize : function(){
-        //this.el.beginMeasure();
-        this.textEl.setWidth(1);
-        /*
-         *  #2804 [new] Tabs in Roojs
-         *  increase the width by 2-4 pixels to prevent the ellipssis showing in chrome
-         */
-        this.setWidth(this.textEl.dom.scrollWidth+this.pnode.getPadding("lr")+this.inner.getPadding("lr") + 2);
-        //this.el.endMeasure();
+    activate : function(id){
+        var tab = this.items[id];
+        if(!tab){
+            return null;
+        }
+        if(tab == this.active || tab.disabled){
+            return tab;
+        }
+        var e = {};
+        this.fireEvent("beforetabchange", this, e, tab);
+        if(e.cancel !== true && !tab.disabled){
+            if(this.active){
+                this.active.hide();
+            }
+            this.active = this.items[id];
+            this.active.show();
+            this.fireEvent("tabchange", this, this.active);
+        }
+        return tab;
     },
 
     /**
-     * Sets the text for the tab (Note: this also sets the tooltip text)
-     * @param {String} text The tab's text and tooltip
+     * Gets the active {@link Roo.panel.TabItem}.
+     * @return {Roo.panel.TabItem} The active TabPanelItem or null if none are active.
      */
-    setText : function(text){
-        this.text = text;
-        this.textEl.update(text);
-        this.setTooltip(text);
-        if(!this.tabPanel.resizeTabs){
-            this.autoSize();
-        }
+    getActiveTab : function(){
+        return this.active;
     },
+
     /**
-     * Activates this TabPanelItem -- this <b>does</b> deactivate the currently active TabPanelItem.
+     * Updates the tab body element to fit the height of the container element
+     * for overflow scrolling
+     * @param {Number} targetHeight (optional) Override the starting height from the elements height
      */
-    activate : function(){
-        this.tabPanel.activate(this.id);
+    syncHeight : function(targetHeight){
+        var height = (targetHeight || this.el.getHeight())-this.el.getBorderWidth("tb")-this.el.getPadding("tb");
+        var bm = this.bodyEl.getMargins();
+        var newHeight = height-(this.stripWrap.getHeight()||0)-(bm.top+bm.bottom);
+        this.bodyEl.setHeight(newHeight);
+        return newHeight;
     },
 
-    /**
-     * Disables this TabPanelItem -- this does nothing if this is the active TabPanelItem.
-     */
-    disable : function(){
-        if(this.tabPanel.active != this){
-            this.disabled = true;
-            this.pnode.addClass("disabled");
+    onResize : function(){
+        if(this.monitorResize){
+            this.autoSizeTabs();
         }
     },
 
     /**
-     * Enables this TabPanelItem if it was previously disabled.
+     * Disables tab resizing while tabs are being added (if {@link #resizeTabs} is false this does nothing)
      */
-    enable : function(){
-        this.disabled = false;
-        this.pnode.removeClass("disabled");
+    beginUpdate : function(){
+        this.updating = true;
     },
 
     /**
-     * Sets the content for this TabPanelItem.
-     * @param {String} content The content
-     * @param {Boolean} loadScripts true to look for and load scripts
+     * Stops an update and resizes the tabs (if {@link #resizeTabs} is false this does nothing)
      */
-    setContent : function(content, loadScripts){
-        this.bodyEl.update(content, loadScripts);
+    endUpdate : function(){
+        this.updating = false;
+        this.autoSizeTabs();
     },
 
     /**
-     * Gets the {@link Roo.UpdateManager} for the body of this TabPanelItem. Enables you to perform Ajax updates.
-     * @return {Roo.UpdateManager} The UpdateManager
+     * Manual call to resize the tabs (if {@link #resizeTabs} is false this does nothing)
      */
-    getUpdateManager : function(){
-        return this.bodyEl.getUpdateManager();
+    autoSizeTabs : function(){
+        var count = this.items.length;
+        var vcount = count - this.hiddenCount;
+        if(!this.resizeTabs || count < 1 || vcount < 1 || this.updating) {
+            return;
+        }
+        var w = Math.max(this.el.getWidth() - this.cpad, 10);
+        var availWidth = Math.floor(w / vcount);
+        var b = this.stripBody;
+        if(b.getWidth() > w){
+            var tabs = this.items;
+            this.setTabWidth(Math.max(availWidth, this.minTabWidth)-2);
+            if(availWidth < this.minTabWidth){
+                /*if(!this.sleft){    // incomplete scrolling code
+                    this.createScrollButtons();
+                }
+                this.showScroll();
+                this.stripClip.setWidth(w - (this.sleft.getWidth()+this.sright.getWidth()));*/
+            }
+        }else{
+            if(this.currentTabWidth < this.preferredTabWidth){
+                this.setTabWidth(Math.min(availWidth, this.preferredTabWidth)-2);
+            }
+        }
     },
 
     /**
-     * Set a URL to be used to load the content for this TabPanelItem.
-     * @param {String/Function} url The URL to load the content from, or a function to call to get the URL
-     * @param {String/Object} params (optional) The string params for the update call or an object of the params. See {@link Roo.UpdateManager#update} for more details. (Defaults to null)
-     * @param {Boolean} loadOnce (optional) Whether to only load the content once. If this is false it makes the Ajax call every time this TabPanelItem is activated. (Defaults to false)
-     * @return {Roo.UpdateManager} The UpdateManager
+     * Returns the number of tabs in this TabPanel.
+     * @return {Number}
      */
-    setUrl : function(url, params, loadOnce){
-        if(this.refreshDelegate){
-            this.un('activate', this.refreshDelegate);
-        }
-        this.refreshDelegate = this._handleRefresh.createDelegate(this, [url, params, loadOnce]);
-        this.on("activate", this.refreshDelegate);
-        return this.bodyEl.getUpdateManager();
-    },
-
-    /** @private */
-    _handleRefresh : function(url, params, loadOnce){
-        if(!loadOnce || !this.loaded){
-            var updater = this.bodyEl.getUpdateManager();
-            updater.update(url, params, this._setLoaded.createDelegate(this));
-        }
-    },
+     getCount : function(){
+         return this.items.length;
+     },
 
     /**
-     *   Forces a content refresh from the URL specified in the {@link #setUrl} method.
-     *   Will fail silently if the setUrl method has not been called.
-     *   This does not activate the panel, just updates its content.
+     * Resizes all the tabs to the passed width
+     * @param {Number} The new width
      */
-    refresh : function(){
-        if(this.refreshDelegate){
-           this.loaded = false;
-           this.refreshDelegate();
+    setTabWidth : function(width){
+        this.currentTabWidth = width;
+        for(var i = 0, len = this.items.length; i < len; i++) {
+               if(!this.items[i].isHidden()) {
+                this.items[i].setWidth(width);
+            }
         }
     },
 
-    /** @private */
-    _setLoaded : function(){
-        this.loaded = true;
-    },
-
-    /** @private */
-    closeClick : function(e){
-        var o = {};
-        e.stopEvent();
-        this.fireEvent("beforeclose", this, o);
-        if(o.cancel !== true){
-            this.tabPanel.removeTab(this.id);
-        }
-    },
     /**
-     * The text displayed in the tooltip for the close icon.
-     * @type String
+     * Destroys this TabPanel
+     * @param {Boolean} removeEl (optional) True to remove the element from the DOM as well (defaults to undefined)
      */
-    closeText : "Close this tab"
+    destroy : function(removeEl){
+        Roo.EventManager.removeResizeListener(this.onResize, this);
+        for(var i = 0, len = this.items.length; i < len; i++){
+            this.items[i].purgeListeners();
+        }
+        if(removeEl === true){
+            this.el.update("");
+            this.el.remove();
+        }
+    }
 });
 
+
 /** @private */
-Roo.TabPanel.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){
+Roo.panel.Tab.prototype.createStripList = function(strip){
     // div wrapper for retard IE
     // returns the "tr" element.
     strip.innerHTML = '<div class="x-tabs-strip-wrap">'+
@@ -30721,7 +32306,7 @@ Roo.TabPanel.prototype.createStripList = function(strip){
     return strip.firstChild.firstChild.firstChild.firstChild;
 };
 /** @private */
-Roo.TabPanel.prototype.createBody = function(container){
+Roo.panel.Tab.prototype.createBody = function(container){
     var body = document.createElement("div");
     Roo.id(body, "tab-body");
     Roo.fly(body).addClass("x-tabs-body");
@@ -30729,7 +32314,7 @@ Roo.TabPanel.prototype.createBody = function(container){
     return body;
 };
 /** @private */
-Roo.TabPanel.prototype.createItemBody = function(bodyEl, id){
+Roo.panel.Tab.prototype.createItemBody = function(bodyEl, id){
     var body = Roo.getDom(id);
     if(!body){
         body = document.createElement("div");
@@ -30740,7 +32325,7 @@ Roo.TabPanel.prototype.createItemBody = function(bodyEl, id){
     return body;
 };
 /** @private */
-Roo.TabPanel.prototype.createStripElements = function(stripEl, text, closable){
+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);
@@ -30768,6 +32353,329 @@ Roo.TabPanel.prototype.createStripElements = function(stripEl, text, closable){
         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.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.panel.TabItem = function(tabPanel, id, text, closable){
+    /**
+     * The {@link Roo.panel.Tab} this TabPanelItem belongs to
+     * @type Roo.panel.Tab
+     */
+    this.tabPanel = tabPanel;
+    /**
+     * The id for this TabPanelItem
+     * @type String
+     */
+    this.id = id;
+    /** @private */
+    this.disabled = false;
+    /** @private */
+    this.text = text;
+    /** @private */
+    this.loaded = false;
+    this.closable = closable;
+
+    /**
+     * The body element for this TabPanelItem.
+     * @type Roo.Element
+     */
+    this.bodyEl = Roo.get(tabPanel.createItemBody(tabPanel.bodyEl.dom, id));
+    this.bodyEl.setVisibilityMode(Roo.Element.VISIBILITY);
+    this.bodyEl.setStyle("display", "block");
+    this.bodyEl.setStyle("zoom", "1");
+    this.hideAction();
+
+    var els = tabPanel.createStripElements(tabPanel.stripEl.dom, text, closable);
+    /** @private */
+    this.el = Roo.get(els.el, true);
+    this.inner = Roo.get(els.inner, true);
+    this.textEl = Roo.get(this.el.dom.firstChild.firstChild.firstChild, true);
+    this.pnode = Roo.get(els.el.parentNode, true);
+    this.el.on("mousedown", this.onTabMouseDown, this);
+    this.el.on("click", this.onTabClick, this);
+    /** @private */
+    if(closable){
+        var c = Roo.get(els.close, true);
+        c.dom.title = this.closeText;
+        c.addClassOnOver("close-over");
+        c.on("click", this.closeClick, this);
+     }
+
+    this.addEvents({
+         /**
+         * @event activate
+         * Fires when this tab becomes the active tab.
+         * @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.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.panel.TabItem} this
+         */
+         "close": true,
+        /**
+         * @event deactivate
+         * Fires when this tab is no longer the active tab.
+         * @param {Roo.panel.Tab} tabPanel The parent TabPanel
+         * @param {Roo.panel.TabItem} this
+         */
+         "deactivate" : true
+    });
+    this.hidden = false;
+
+    Roo.panel.TabItem.superclass.constructor.call(this);
+};
+
+Roo.extend(Roo.panel.TabItem, Roo.util.Observable, {
+    purgeListeners : function(){
+       Roo.util.Observable.prototype.purgeListeners.call(this);
+       this.el.removeAllListeners();
+    },
+    /**
+     * Shows this TabPanelItem -- this <b>does not</b> deactivate the currently active TabPanelItem.
+     */
+    show : function(){
+        this.pnode.addClass("on");
+        this.showAction();
+        if(Roo.isOpera){
+            this.tabPanel.stripWrap.repaint();
+        }
+        this.fireEvent("activate", this.tabPanel, this);
+    },
+
+    /**
+     * Returns true if this tab is the active tab.
+     * @return {Boolean}
+     */
+    isActive : function(){
+        return this.tabPanel.getActiveTab() == this;
+    },
+
+    /**
+     * Hides this TabPanelItem -- if you don't activate another TabPanelItem this could look odd.
+     */
+    hide : function(){
+        this.pnode.removeClass("on");
+        this.hideAction();
+        this.fireEvent("deactivate", this.tabPanel, this);
+    },
+
+    hideAction : function(){
+        this.bodyEl.hide();
+        this.bodyEl.setStyle("position", "absolute");
+        this.bodyEl.setLeft("-20000px");
+        this.bodyEl.setTop("-20000px");
+    },
+
+    showAction : function(){
+        this.bodyEl.setStyle("position", "relative");
+        this.bodyEl.setTop("");
+        this.bodyEl.setLeft("");
+        this.bodyEl.show();
+    },
+
+    /**
+     * Set the tooltip for the tab.
+     * @param {String} tooltip The tab's tooltip
+     */
+    setTooltip : function(text){
+        if(Roo.QuickTips && Roo.QuickTips.isEnabled()){
+            this.textEl.dom.qtip = text;
+            this.textEl.dom.removeAttribute('title');
+        }else{
+            this.textEl.dom.title = text;
+        }
+    },
+
+    onTabClick : function(e){
+        e.preventDefault();
+        this.tabPanel.activate(this.id);
+    },
+
+    onTabMouseDown : function(e){
+        e.preventDefault();
+        this.tabPanel.activate(this.id);
+    },
+
+    getWidth : function(){
+        return this.inner.getWidth();
+    },
+
+    setWidth : function(width){
+        var iwidth = width - this.pnode.getPadding("lr");
+        this.inner.setWidth(iwidth);
+        this.textEl.setWidth(iwidth-this.inner.getPadding("lr"));
+        this.pnode.setWidth(width);
+    },
+
+    /**
+     * Show or hide the tab
+     * @param {Boolean} hidden True to hide or false to show.
+     */
+    setHidden : function(hidden){
+        this.hidden = hidden;
+        this.pnode.setStyle("display", hidden ? "none" : "");
+    },
+
+    /**
+     * Returns true if this tab is "hidden"
+     * @return {Boolean}
+     */
+    isHidden : function(){
+        return this.hidden;
+    },
+
+    /**
+     * Returns the text for this tab
+     * @return {String}
+     */
+    getText : function(){
+        return this.text;
+    },
+
+    autoSize : function(){
+        //this.el.beginMeasure();
+        this.textEl.setWidth(1);
+        /*
+         *  #2804 [new] Tabs in Roojs
+         *  increase the width by 2-4 pixels to prevent the ellipssis showing in chrome
+         */
+        this.setWidth(this.textEl.dom.scrollWidth+this.pnode.getPadding("lr")+this.inner.getPadding("lr") + 2);
+        //this.el.endMeasure();
+    },
+
+    /**
+     * Sets the text for the tab (Note: this also sets the tooltip text)
+     * @param {String} text The tab's text and tooltip
+     */
+    setText : function(text){
+        this.text = text;
+        this.textEl.update(text);
+        this.setTooltip(text);
+        if(!this.tabPanel.resizeTabs){
+            this.autoSize();
+        }
+    },
+    /**
+     * Activates this TabPanelItem -- this <b>does</b> deactivate the currently active TabPanelItem.
+     */
+    activate : function(){
+        this.tabPanel.activate(this.id);
+    },
+
+    /**
+     * Disables this TabPanelItem -- this does nothing if this is the active TabPanelItem.
+     */
+    disable : function(){
+        if(this.tabPanel.active != this){
+            this.disabled = true;
+            this.pnode.addClass("disabled");
+        }
+    },
+
+    /**
+     * Enables this TabPanelItem if it was previously disabled.
+     */
+    enable : function(){
+        this.disabled = false;
+        this.pnode.removeClass("disabled");
+    },
+
+    /**
+     * Sets the content for this TabPanelItem.
+     * @param {String} content The content
+     * @param {Boolean} loadScripts true to look for and load scripts
+     */
+    setContent : function(content, loadScripts){
+        this.bodyEl.update(content, loadScripts);
+    },
+
+    /**
+     * Gets the {@link Roo.UpdateManager} for the body of this TabPanelItem. Enables you to perform Ajax updates.
+     * @return {Roo.UpdateManager} The UpdateManager
+     */
+    getUpdateManager : function(){
+        return this.bodyEl.getUpdateManager();
+    },
+
+    /**
+     * Set a URL to be used to load the content for this TabPanelItem.
+     * @param {String/Function} url The URL to load the content from, or a function to call to get the URL
+     * @param {String/Object} params (optional) The string params for the update call or an object of the params. See {@link Roo.UpdateManager#update} for more details. (Defaults to null)
+     * @param {Boolean} loadOnce (optional) Whether to only load the content once. If this is false it makes the Ajax call every time this TabPanelItem is activated. (Defaults to false)
+     * @return {Roo.UpdateManager} The UpdateManager
+     */
+    setUrl : function(url, params, loadOnce){
+        if(this.refreshDelegate){
+            this.un('activate', this.refreshDelegate);
+        }
+        this.refreshDelegate = this._handleRefresh.createDelegate(this, [url, params, loadOnce]);
+        this.on("activate", this.refreshDelegate);
+        return this.bodyEl.getUpdateManager();
+    },
+
+    /** @private */
+    _handleRefresh : function(url, params, loadOnce){
+        if(!loadOnce || !this.loaded){
+            var updater = this.bodyEl.getUpdateManager();
+            updater.update(url, params, this._setLoaded.createDelegate(this));
+        }
+    },
+
+    /**
+     *   Forces a content refresh from the URL specified in the {@link #setUrl} method.
+     *   Will fail silently if the setUrl method has not been called.
+     *   This does not activate the panel, just updates its content.
+     */
+    refresh : function(){
+        if(this.refreshDelegate){
+           this.loaded = false;
+           this.refreshDelegate();
+        }
+    },
+
+    /** @private */
+    _setLoaded : function(){
+        this.loaded = true;
+    },
+
+    /** @private */
+    closeClick : function(e){
+        var o = {};
+        e.stopEvent();
+        this.fireEvent("beforeclose", this, o);
+        if(o.cancel !== true){
+            this.tabPanel.removeTab(this.id);
+        }
+    },
+    /**
+     * The text displayed in the tooltip for the close icon.
+     * @type String
+     */
+    closeText : "Close this tab"
+});
+
+/** @private */
+Roo.panel.Tab.prototype.createStrip = function(container){
+    var strip = document.createElement("div");
+    strip.className = "x-tabs-wrap";
+    container.appendChild(strip);
+    return strip;
 };/*
  * Based on:
  * Ext JS Library 1.1.1
@@ -33866,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();
@@ -33987,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;
     },
@@ -34653,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>
@@ -34680,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,
@@ -34691,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();
@@ -34725,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
@@ -34743,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..
@@ -34780,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;
@@ -40539,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
@@ -41228,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);
@@ -41341,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;
@@ -41421,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.
@@ -41434,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:
@@ -41903,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)
      */
@@ -41932,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 += "-";
         }
@@ -41987,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;
     },
 
@@ -42002,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
@@ -42359,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){
@@ -43129,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 =
@@ -43891,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 
@@ -44010,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,
@@ -44104,8 +46138,10 @@ Roo.extend(Roo.form.ComboBoxArray, Roo.form.TextField,
             // add to list
             
         }, this);
-        
-        
+         
+       
+       
+           
     },
     
     
@@ -44339,7 +46375,7 @@ Roo.extend(Roo.form.ComboBoxArray.Item, Roo.BoxComponent, {
     cb: false,
     displayField : false,
     tipField : false,
-    
+     
     
     defaultAutoCreate : {
         tag: 'div',
@@ -45018,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;
         
     },
@@ -45109,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)
 {
@@ -45687,6 +47765,24 @@ Roo.htmleditor.Filter.prototype = {
            
         }
         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);
     }
 }; 
 
@@ -45885,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
@@ -45964,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,
@@ -45985,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]);
@@ -46004,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
@@ -46014,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,
@@ -46111,7 +48286,7 @@ Roo.htmleditor.FilterWord = function(cfg)
     this.replaceAname(cfg.node);
     // this is disabled as the removal is done by other filters;
    // this.walk(cfg.node);
-    
+    this.replaceImageTable(cfg.node);
     
 }
 
@@ -46262,32 +48437,47 @@ Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
     replaceDocBullets : function(doc)
     {
         // this is a bit odd - but it appears some indents use ql-indent-1
-        //Roo.log(doc.innerHTML);
+         //Roo.log(doc.innerHTML);
+        
+        var listpara = Array.from(doc.getElementsByClassName('MsoListParagraphCxSpFirst'));
+        for( var i = 0; i < listpara.length; i ++) {
+            listpara[i].className = "MsoListParagraph";
+        }
         
-        var listpara = doc.getElementsByClassName('MsoListParagraphCxSpFirst');
+        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.item(i).className = "MsoListParagraph";
+            listpara[i].className = "MsoListParagraph";
         }
+        
         // this is a bit hacky - we had one word document where h2 had a miso-list attribute.
-        var htwo = doc.getElementsByTagName('h2');
+        var htwo =  Array.from(doc.getElementsByTagName('h2'));
         for( var i = 0; i < htwo.length; i ++) {
-            if (htwo.item(i).hasAttribute('style') && htwo.item(i).getAttribute('style').match(/mso-list:/)) {
-                htwo.item(i).className = "MsoListParagraph";
+            if (htwo[i].hasAttribute('style') && htwo[i].getAttribute('style').match(/mso-list:/)) {
+                htwo[i].className = "MsoListParagraph";
             }
         }
-        listpara = doc.getElementsByClassName('MsoNormal');
-        while(listpara.length) {
-            if (listpara.item(0).hasAttribute('style') && listpara.item(0).getAttribute('style').match(/mso-list:/)) {
-                listpara.item(0).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.item(0).className = "MsoNormalx";
+                listpara[i].className = "MsoNormalx";
             }
         }
-        listpara = doc.getElementsByClassName('ql-indent-1');
-        while(listpara.length) {
-            this.replaceDocBullet(listpara.item(0));
-        }
+       
         listpara = doc.getElementsByClassName('MsoListParagraph');
+        // Roo.log(doc.innerHTML);
+        
+        
+        
         while(listpara.length) {
             
             this.replaceDocBullet(listpara.item(0));
@@ -46304,22 +48494,47 @@ Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
             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;
@@ -46344,7 +48559,7 @@ Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
             return;
         }
         
-        var ul = parent.ownerDocument.createElement('ul'); // what about number lists...
+        var ul = parent.ownerDocument.createElement(listtype); // what about number lists...
         parent.insertBefore(ul, p);
         var lvl = 0;
         var stack = [ ul ];
@@ -46367,7 +48582,7 @@ Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
             }
            
                 
-            
+            var num = 1;
             var style = {};
             for(var i = 0; i < spans.length; i++) {
             
@@ -46375,7 +48590,9 @@ Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
                 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;
             }
@@ -46398,7 +48615,7 @@ Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
              
             if (nlvl > lvl) {
                 //new indent
-                var nul = doc.createElement('ul'); // what about number lists...
+                var nul = doc.createElement(listtype); // what about number lists...
                 if (!last_li) {
                     last_li = doc.createElement('li');
                     stack[lvl].appendChild(last_li);
@@ -46409,6 +48626,11 @@ Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
             }
             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;
@@ -46423,9 +48645,63 @@ Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
         
         
         
-    }
-    
+    },
     
+    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);
+            
+            
+            
+        });
+        
+      
+    }
     
 });
 /**
@@ -46443,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']
         
         
     };
@@ -46481,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) {
@@ -46494,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]);
         }
@@ -46512,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,
@@ -46546,8 +48822,6 @@ Roo.extend(Roo.htmleditor.FilterLongBr, Roo.htmleditor.Filter,
         
         
         
-        
-        
         if (!node.previousSibling) {
             return false;
         }
@@ -48343,7 +50617,7 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
                 }
             },
             
-            
+              
             {
                 xtype : 'Button',
                 text: 'Hide Caption',
@@ -48395,8 +50669,11 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
                 maxWidth : iw + ' !important', // this is not getting rendered?
                 margin : m  
                 
-            }
+            },
+            width: this.align == 'center' ?  this.width : '100%' 
+
         };
+        
         /*
         '<div class="{0}" width="420" height="315" src="{1}" frameborder="0" allowfullscreen>' +
                     '<a href="{2}">' + 
@@ -48431,14 +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");
-        
+
+
   
         var ret =   {
             tag: 'figure',
             'data-block' : 'Figure',
-            'data-width' : this.width, 
+            'data-width' : this.width,
+            'data-caption' : this.caption, 
+            'data-caption-display' : this.caption_display,
             contenteditable : 'false',
             
             style : {
@@ -48451,51 +50729,52 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
                 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.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 : '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;
          
     },
@@ -48511,13 +50790,31 @@ 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);
+
         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.caption_display = this.getVal(node, 'figcaption', 'data-display');
         //this.text_align = this.getVal(node, 'figcaption', 'style','text-align');
         this.width = this.getVal(node, true, 'data-width');
         //this.margin = this.getVal(node, 'figure', 'style', 'margin');
@@ -48535,7 +50832,11 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
     
     
     
-})
+});
+
+Roo.apply(Roo.htmleditor.BlockFigure, {
+    caption_edit : true
+});
 
  
 
@@ -49407,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;
+        }
         
         
     },
@@ -49639,7 +51943,13 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
                 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  +'%';
@@ -49709,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);
          
@@ -49729,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);
          
@@ -49855,7 +52174,7 @@ Roo.HtmlEditorCore = function(config){
          * @param {Roo.HtmlEditorCore} this
          */
         editorevent: true 
-         
+        
         
     });
     
@@ -49879,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)
      */   
@@ -50015,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;
@@ -50158,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){
@@ -50352,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 ) {
@@ -50371,8 +52760,8 @@ 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(); })
@@ -50400,8 +52789,9 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         
         if (images.length > 0) {
             // replace all v:imagedata - with img.
-            Roo.each(d.getElementsByTagName('v:imagedata'), function(node) {
-                node.parentNode.insertBefore(node, document.createElement('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);
             });
             
@@ -50416,16 +52806,40 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
             new Roo.htmleditor.FilterStyleToTag({ node : d });
             new Roo.htmleditor.FilterAttributes({
                 node : d,
-                attrib_white : ['href', 'src', 'name', 'align', 'colspan', 'rowspan', 'data-display', 'data-width'],
+                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', ':' ]} );
             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});
             
             
         }
@@ -50451,6 +52865,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
          
         
         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..
@@ -50527,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 &&
@@ -50629,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;
@@ -51619,6 +54037,7 @@ Roo.extend(Roo.form.HtmlEditor, Roo.form.Field, {
             * @param {Roo.HtmlEditorCore} this
             */
             paste: true 
+            
         });
         this.defaultAutoCreate =  {
             tag: "textarea",
@@ -53842,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,
 
@@ -54218,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 &&
@@ -54232,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]);
                     }
@@ -54257,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)
@@ -54680,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} (left|center|right) 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',
 
@@ -55337,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,
@@ -55730,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 {
@@ -55739,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">
 
@@ -56670,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;
@@ -56712,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");
@@ -58163,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.
@@ -58175,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){
@@ -58197,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
     });
@@ -58224,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}
@@ -58297,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()];
@@ -58319,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
@@ -58367,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"));
@@ -58390,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]){
@@ -58402,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.
@@ -58538,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){
          
@@ -58550,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();
@@ -58561,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;
@@ -58578,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;
@@ -58602,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);
     },
 
@@ -58612,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,
@@ -58657,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++){
@@ -58667,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);
@@ -58701,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);
@@ -58726,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) {
@@ -58759,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());
@@ -58860,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,
@@ -58911,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){
@@ -58928,7 +61456,7 @@ Roo.BorderLayout.create = function(config, targetEl){
 };
 
 // private
-Roo.BorderLayout.RegionFactory = {
+Roo.layout.Border.RegionFactory = {
     // private
     validRegions : ["north","south","east","west","center"],
 
@@ -58936,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:
@@ -58964,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
@@ -59066,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 || {}
         });
@@ -59077,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();
     },
@@ -59161,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)){
@@ -59173,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;
@@ -59181,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){
@@ -59216,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){
@@ -59228,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);
@@ -59249,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
@@ -59278,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)
@@ -59310,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 */
@@ -59345,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 
@@ -59637,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',
@@ -59718,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)
     {
@@ -59740,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;
@@ -59760,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){
@@ -59798,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))){
@@ -59808,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))){
@@ -59824,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);
@@ -59874,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;
@@ -59900,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, 
@@ -59971,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(){
@@ -59985,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(){
@@ -60241,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
     },
@@ -60265,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.
@@ -60446,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: {},
@@ -60456,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");
@@ -60521,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
@@ -60545,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;
@@ -60623,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
          */
@@ -60645,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
          
@@ -60674,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"));
@@ -60686,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;
@@ -60758,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();
@@ -60937,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$/)) {
             
@@ -60984,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') {
@@ -61003,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);
@@ -61024,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;
     },
@@ -61057,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
@@ -61092,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;
@@ -61103,7 +63627,7 @@ Roo.NestedLayoutPanel = function(layout, config)
     
 };
 
-Roo.extend(Roo.NestedLayoutPanel, Roo.ContentPanel, {
+Roo.extend(Roo.panel.NestedLayout, Roo.panel.Content, {
 
     layout : false,
 
@@ -61157,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;
@@ -61175,7 +63699,7 @@ panel.addxtype({
 );
 
 panel.addxtype({
-        xtype : 'NestedLayoutPanel',
+        xtype : 'panel.NestedLayout',
         region: 'west',
         layout: {
            center: { },
@@ -61193,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"});
@@ -61218,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(){
@@ -61237,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();
     },
 
@@ -61257,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; 
@@ -61279,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);
@@ -61305,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
 
@@ -61327,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"));
@@ -61354,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,
@@ -61397,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,
@@ -61413,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();
@@ -61422,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.
@@ -61756,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.
      */
@@ -68189,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;
+